Commit 9d3ba0b10c295c9bd0a6a5b1be4779e482be4515

Authored by David Mayerich
1 parent 798cea97

added stim::hsi as a bridge, fixed warnings for a clean build of HSIproc

@@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
2 #define STIM_BIL_H 2 #define STIM_BIL_H
3 3
4 #include "../envi/envi_header.h" 4 #include "../envi/envi_header.h"
5 -#include "../envi/binary.h" 5 +#include "../envi/hsi.h"
6 #include <cstring> 6 #include <cstring>
7 #include <utility> 7 #include <utility>
8 8
@@ -19,28 +19,29 @@ namespace stim{ @@ -19,28 +19,29 @@ namespace stim{
19 19
20 template <typename T> 20 template <typename T>
21 21
22 -class bil: public binary<T> { 22 +class bil: public hsi<T> {
23 23
24 protected: 24 protected:
25 25
26 - std::vector<double> w; //band wavelength 26 + //std::vector<double> w; //band wavelengths
27 27
28 - unsigned long X(){ 28 + /*unsigned long long X(){
29 return R[0]; 29 return R[0];
30 } 30 }
31 - unsigned long Y(){ 31 + unsigned long long Y(){
32 return R[2]; 32 return R[2];
33 } 33 }
34 - unsigned long Z(){ 34 + unsigned long long Z(){
35 return R[1]; 35 return R[1];
36 - }  
37 - 36 + }*/
  37 + using hsi<T>::w; //use the wavelength array in stim::hsi
  38 + using hsi<T>::nnz;
38 using binary<T>::progress; 39 using binary<T>::progress;
39 40
40 /// Call the binary nnz() function for the BIL orientation 41 /// Call the binary nnz() function for the BIL orientation
41 - unsigned long long nnz(unsigned char* mask){  
42 - return binary<T>::nnz(mask, X()*Y());  
43 - } 42 + //unsigned long long nnz(unsigned char* mask){
  43 + // return binary<T>::nnz(mask, X()*Y());
  44 + //}
44 45
45 public: 46 public:
46 47
@@ -48,6 +49,8 @@ public: @@ -48,6 +49,8 @@ public:
48 using binary<T>::file; 49 using binary<T>::file;
49 using binary<T>::R; 50 using binary<T>::R;
50 51
  52 + bil(){ hsi<T>::init_bil(); }
  53 +
51 /// Open a data file for reading using the class interface. 54 /// Open a data file for reading using the class interface.
52 55
53 /// @param filename is the name of the binary file on disk 56 /// @param filename is the name of the binary file on disk
@@ -56,11 +59,16 @@ public: @@ -56,11 +59,16 @@ public:
56 /// @param B is the number of samples (bands) along dimension 3 59 /// @param B is the number of samples (bands) along dimension 3
57 /// @param header_offset is the number of bytes (if any) in the binary header 60 /// @param header_offset is the number of bytes (if any) in the binary header
58 /// @param wavelengths is an optional STL vector of size B specifying a numerical label for each band 61 /// @param wavelengths is an optional STL vector of size B specifying a numerical label for each band
59 - bool open(std::string filename, unsigned int X, unsigned int Y, unsigned int B, unsigned int header_offset, std::vector<double> wavelengths){ 62 + bool open(std::string filename,
  63 + unsigned long long X,
  64 + unsigned long long Y,
  65 + unsigned long long B,
  66 + unsigned long long header_offset,
  67 + std::vector<double> wavelengths){
60 68
61 w = wavelengths; 69 w = wavelengths;
62 70
63 - return open(filename, vec<unsigned int>(X, B, Y), header_offset); 71 + return open(filename, vec<unsigned long long>(X, B, Y), header_offset);
64 72
65 } 73 }
66 74
@@ -68,12 +76,12 @@ public: @@ -68,12 +76,12 @@ public:
68 76
69 /// @param p is a pointer to an allocated region of memory at least X * Y * sizeof(T) in size. 77 /// @param p is a pointer to an allocated region of memory at least X * Y * sizeof(T) in size.
70 /// @param page <= B is the integer number of the band to be copied. 78 /// @param page <= B is the integer number of the band to be copied.
71 - bool band_index( T * p, unsigned int page, bool PROGRESS = false){ 79 + bool band_index( T * p, unsigned long long page, bool PROGRESS = false){
72 //return binary<T>::read_plane_1(p, page); 80 //return binary<T>::read_plane_1(p, page);
73 81
74 if(PROGRESS) progress = 0; 82 if(PROGRESS) progress = 0;
75 - unsigned int L = X() * sizeof(T); //caculate the number of bytes in a sample line  
76 - unsigned int jump = X() * (Z() - 1) * sizeof(T); 83 + unsigned long long L = X() * sizeof(T); //caculate the number of bytes in a sample line
  84 + unsigned long long jump = X() * (Z() - 1) * sizeof(T);
77 85
78 if (page >= Z()){ //make sure the bank number is right 86 if (page >= Z()){ //make sure the bank number is right
79 std::cout<<"ERROR: page out of range"<<std::endl; 87 std::cout<<"ERROR: page out of range"<<std::endl;
@@ -81,7 +89,7 @@ public: @@ -81,7 +89,7 @@ public:
81 } 89 }
82 90
83 file.seekg(X() * page * sizeof(T), std::ios::beg); 91 file.seekg(X() * page * sizeof(T), std::ios::beg);
84 - for (unsigned i = 0; i < Y(); i++) 92 + for (unsigned long long i = 0; i < Y(); i++)
85 { 93 {
86 file.read((char *)(p + i * X()), L); 94 file.read((char *)(p + i * X()), L);
87 file.seekg( jump, std::ios::cur); 95 file.seekg( jump, std::ios::cur);
@@ -99,12 +107,12 @@ public: @@ -99,12 +107,12 @@ public:
99 107
100 //if there are no wavelengths in the BSQ file 108 //if there are no wavelengths in the BSQ file
101 if(w.size() == 0) 109 if(w.size() == 0)
102 - return band_index(p, (unsigned int)wavelength); 110 + return band_index(p, (unsigned long long)wavelength);
103 111
104 - unsigned int XY = X() * Y(); //calculate the number of pixels in a band  
105 - unsigned int S = XY * sizeof(T); //calculate the number of bytes of a band 112 + unsigned long long XY = X() * Y(); //calculate the number of pixels in a band
  113 + unsigned long long S = XY * sizeof(T); //calculate the number of bytes of a band
106 114
107 - unsigned page=0; //bands around the wavelength 115 + unsigned long long page=0; //bands around the wavelength
108 116
109 117
110 //get the bands numbers around the wavelength 118 //get the bands numbers around the wavelength
@@ -132,9 +140,9 @@ public: @@ -132,9 +140,9 @@ public:
132 p2=(T*)malloc(S); 140 p2=(T*)malloc(S);
133 band_index(p1, page - 1); 141 band_index(p1, page - 1);
134 band_index(p2, page, PROGRESS); 142 band_index(p2, page, PROGRESS);
135 - for(unsigned i=0; i < XY; i++){  
136 - double r = (double) (wavelength - w[page-1]) / (double) (w[page] - w[page-1]);  
137 - p[i] = (p2[i] - p1[i]) * r + p1[i]; 143 + for(unsigned long long i=0; i < XY; i++){
  144 + double r = (wavelength - w[page-1]) / (w[page] - w[page-1]);
  145 + p[i] = (T)(((double)p2[i] - (double)p1[i]) * r + (double)p1[i]);
138 } 146 }
139 free(p1); 147 free(p1);
140 free(p2); 148 free(p2);
@@ -154,10 +162,10 @@ public: @@ -154,10 +162,10 @@ public:
154 /// @param wavelength is the wavelength to retrieve 162 /// @param wavelength is the wavelength to retrieve
155 bool read_x_from_xz(T* p, T* c, double wavelength) 163 bool read_x_from_xz(T* p, T* c, double wavelength)
156 { 164 {
157 - unsigned int B = Z();  
158 - unsigned int L = X() * sizeof(T); 165 + unsigned long long B = Z();
  166 + unsigned long long L = X() * sizeof(T);
159 167
160 - unsigned page=0; //samples around the wavelength 168 + unsigned long long page=0; //samples around the wavelength
161 T * p1; 169 T * p1;
162 T * p2; 170 T * p2;
163 171
@@ -186,9 +194,9 @@ public: @@ -186,9 +194,9 @@ public:
186 memcpy(p1, c + (page - 1) * X(), L); 194 memcpy(p1, c + (page - 1) * X(), L);
187 memcpy(p2, c + page * X(), L); 195 memcpy(p2, c + page * X(), L);
188 196
189 - for(unsigned i=0; i < X(); i++){ 197 + for(unsigned long long i=0; i < X(); i++){
190 double r = (double) (wavelength - w[page-1]) / (double) (w[page] - w[page-1]); 198 double r = (double) (wavelength - w[page-1]) / (double) (w[page] - w[page-1]);
191 - p[i] = (p2[i] - p1[i]) * r + p1[i]; 199 + p[i] = (T)(((double)p2[i] - (double)p1[i]) * r + (double)p1[i]);
192 } 200 }
193 } 201 }
194 else //if the wavelength is equal to a wavelength in header file 202 else //if the wavelength is equal to a wavelength in header file
@@ -202,7 +210,7 @@ public: @@ -202,7 +210,7 @@ public:
202 /// @param p is a pointer to pre-allocated memory at least B * sizeof(T) in size. 210 /// @param p is a pointer to pre-allocated memory at least B * sizeof(T) in size.
203 /// @param x is the x-coordinate (dimension 1) of the spectrum. 211 /// @param x is the x-coordinate (dimension 1) of the spectrum.
204 /// @param y is the y-coordinate (dimension 2) of the spectrum. 212 /// @param y is the y-coordinate (dimension 2) of the spectrum.
205 - bool spectrum(T * p, unsigned x, unsigned y, bool PROGRESS = false){ 213 + bool spectrum(T * p, unsigned long long x, unsigned long long y, bool PROGRESS = false){
206 return binary<T>::read_line_1(p, x, y, PROGRESS); 214 return binary<T>::read_line_1(p, x, y, PROGRESS);
207 } 215 }
208 216
@@ -210,18 +218,18 @@ public: @@ -210,18 +218,18 @@ public:
210 218
211 /// @param p is a pointer to pre-allocated memory at least sizeof(T) in size. 219 /// @param p is a pointer to pre-allocated memory at least sizeof(T) in size.
212 /// @param n is an integer index to the pixel using linear array indexing. 220 /// @param n is an integer index to the pixel using linear array indexing.
213 - bool pixel(T * p, unsigned n){ 221 + bool pixel(T * p, unsigned long long n){
214 222
215 //calculate the corresponding x, y 223 //calculate the corresponding x, y
216 - unsigned int x = n % X();  
217 - unsigned int y = n / X(); 224 + unsigned long long x = n % X();
  225 + unsigned long long y = n / X();
218 226
219 //get the pixel 227 //get the pixel
220 return spectrum(p, x, y); 228 return spectrum(p, x, y);
221 } 229 }
222 230
223 //given a Y ,return a XZ slice 231 //given a Y ,return a XZ slice
224 - bool read_plane_y(T * p, unsigned y){ 232 + bool read_plane_y(T * p, unsigned long long y){
225 return binary<T>::read_plane_2(p, y); 233 return binary<T>::read_plane_2(p, y);
226 } 234 }
227 235
@@ -232,15 +240,15 @@ public: @@ -232,15 +240,15 @@ public:
232 /// @param wls is the list of baseline points based on band labels. 240 /// @param wls is the list of baseline points based on band labels.
233 bool baseline(std::string outname, std::vector<double> wls, unsigned char* mask = NULL, bool PROGRESS = false){ 241 bool baseline(std::string outname, std::vector<double> wls, unsigned char* mask = NULL, bool PROGRESS = false){
234 242
235 - unsigned N = wls.size(); //get the number of baseline points 243 + unsigned long long N = wls.size(); //get the number of baseline points
236 244
237 std::ofstream target(outname.c_str(), std::ios::binary); //open the target binary file 245 std::ofstream target(outname.c_str(), std::ios::binary); //open the target binary file
238 std::string headername = outname + ".hdr"; //the header file name 246 std::string headername = outname + ".hdr"; //the header file name
239 247
240 //simplify image resolution 248 //simplify image resolution
241 - unsigned int ZX = Z() * X(); //calculate the number of points in a Y slice  
242 - unsigned int L = ZX * sizeof(T); //calculate the number of bytes of a Y slice  
243 - unsigned int B = Z(); 249 + unsigned long long ZX = Z() * X(); //calculate the number of points in a Y slice
  250 + unsigned long long L = ZX * sizeof(T); //calculate the number of bytes of a Y slice
  251 + unsigned long long B = Z();
244 252
245 T* c; //pointer to the current Y slice 253 T* c; //pointer to the current Y slice
246 c = (T*)malloc(L); //memory allocation 254 c = (T*)malloc(L); //memory allocation
@@ -254,7 +262,7 @@ public: @@ -254,7 +262,7 @@ public:
254 262
255 double ai, bi; //stores the two baseline points wavelength surrounding the current band 263 double ai, bi; //stores the two baseline points wavelength surrounding the current band
256 double ci; //stores the current band's wavelength 264 double ci; //stores the current band's wavelength
257 - unsigned control; 265 + unsigned long long control;
258 266
259 if (a == NULL || b == NULL || c == NULL){ 267 if (a == NULL || b == NULL || c == NULL){
260 std::cout<<"ERROR: error allocating memory"; 268 std::cout<<"ERROR: error allocating memory";
@@ -262,7 +270,7 @@ public: @@ -262,7 +270,7 @@ public:
262 } 270 }
263 // loop start correct every y slice 271 // loop start correct every y slice
264 272
265 - for (unsigned k =0; k < Y(); k++) 273 + for (unsigned long long k =0; k < Y(); k++)
266 { 274 {
267 //get the current y slice 275 //get the current y slice
268 read_plane_y(c, k); 276 read_plane_y(c, k);
@@ -287,7 +295,7 @@ public: @@ -287,7 +295,7 @@ public:
287 295
288 //correct every YZ line 296 //correct every YZ line
289 297
290 - for(unsigned cii = 0; cii < B; cii++){ 298 + for(unsigned long long cii = 0; cii < B; cii++){
291 299
292 //update baseline points, if necessary 300 //update baseline points, if necessary
293 if( w[cii] >= bi && cii != B - 1) { 301 if( w[cii] >= bi && cii != B - 1) {
@@ -317,7 +325,7 @@ public: @@ -317,7 +325,7 @@ public:
317 325
318 ci = w[cii]; 326 ci = w[cii];
319 327
320 - unsigned jump = cii * X(); 328 + unsigned long long jump = cii * X();
321 //perform the baseline correction 329 //perform the baseline correction
322 for(unsigned i=0; i < X(); i++) 330 for(unsigned i=0; i < X(); i++)
323 { 331 {
@@ -347,11 +355,11 @@ public: @@ -347,11 +355,11 @@ public:
347 /// @param t is a threshold specified such that a spectrum with a value at w less than t is set to zero. Setting this threshold allows the user to limit division by extremely small numbers. 355 /// @param t is a threshold specified such that a spectrum with a value at w less than t is set to zero. Setting this threshold allows the user to limit division by extremely small numbers.
348 bool normalize(std::string outname, double w, unsigned char* mask = NULL, bool PROGRESS = false) 356 bool normalize(std::string outname, double w, unsigned char* mask = NULL, bool PROGRESS = false)
349 { 357 {
350 - unsigned int B = Z(); //calculate the number of bands  
351 - unsigned int ZX = Z() * X();  
352 - unsigned int XY = X() * Y(); //calculate the number of pixels in a band  
353 - unsigned int S = XY * sizeof(T); //calculate the number of bytes in a band  
354 - unsigned int L = ZX * sizeof(T); 358 + unsigned long long B = Z(); //calculate the number of bands
  359 + unsigned long long ZX = Z() * X();
  360 + unsigned long long XY = X() * Y(); //calculate the number of pixels in a band
  361 + unsigned long long S = XY * sizeof(T); //calculate the number of bytes in a band
  362 + unsigned long long L = ZX * sizeof(T);
355 363
356 std::ofstream target(outname.c_str(), std::ios::binary); //open the target binary file 364 std::ofstream target(outname.c_str(), std::ios::binary); //open the target binary file
357 std::string headername = outname + ".hdr"; //the header file name 365 std::string headername = outname + ".hdr"; //the header file name
@@ -364,12 +372,12 @@ public: @@ -364,12 +372,12 @@ public:
364 372
365 band(b, w); //get the certain band into memory 373 band(b, w); //get the certain band into memory
366 374
367 - for(unsigned j = 0; j < Y(); j++) 375 + for(unsigned long long j = 0; j < Y(); j++)
368 { 376 {
369 read_plane_y(c, j); 377 read_plane_y(c, j);
370 - for(unsigned i = 0; i < B; i++) 378 + for(unsigned long long i = 0; i < B; i++)
371 { 379 {
372 - for(unsigned m = 0; m < X(); m++) 380 + for(unsigned long long m = 0; m < X(); m++)
373 { 381 {
374 if( mask != NULL && !mask[m + j * X()] ) 382 if( mask != NULL && !mask[m + j * X()] )
375 c[m + i * X()] = (T)0.0; 383 c[m + i * X()] = (T)0.0;
@@ -393,7 +401,7 @@ public: @@ -393,7 +401,7 @@ public:
393 /// @param outname is the name of the output BSQ file to be saved to disk. 401 /// @param outname is the name of the output BSQ file to be saved to disk.
394 bool bsq(std::string outname, bool PROGRESS = false) 402 bool bsq(std::string outname, bool PROGRESS = false)
395 { 403 {
396 - unsigned int S = X() * Y() * sizeof(T); //calculate the number of bytes in a band 404 + unsigned long long S = X() * Y() * sizeof(T); //calculate the number of bytes in a band
397 405
398 std::ofstream target(outname.c_str(), std::ios::binary); 406 std::ofstream target(outname.c_str(), std::ios::binary);
399 std::string headername = outname + ".hdr"; 407 std::string headername = outname + ".hdr";
@@ -401,7 +409,7 @@ public: @@ -401,7 +409,7 @@ public:
401 T * p; //pointer to the current band 409 T * p; //pointer to the current band
402 p = (T*)malloc(S); 410 p = (T*)malloc(S);
403 411
404 - for ( unsigned i = 0; i < Z(); i++) 412 + for ( unsigned long long i = 0; i < Z(); i++)
405 { 413 {
406 band_index(p, i); 414 band_index(p, i);
407 target.write(reinterpret_cast<const char*>(p), S); //write a band data into target file 415 target.write(reinterpret_cast<const char*>(p), S); //write a band data into target file
@@ -429,13 +437,13 @@ public: @@ -429,13 +437,13 @@ public:
429 T * q; //pointer to the current ZX slice for bip file 437 T * q; //pointer to the current ZX slice for bip file
430 q = (T*)malloc(S); 438 q = (T*)malloc(S);
431 439
432 - for ( unsigned i = 0; i < Y(); i++) 440 + for ( unsigned long long i = 0; i < Y(); i++)
433 { 441 {
434 read_plane_y(p, i); 442 read_plane_y(p, i);
435 - for ( unsigned k = 0; k < Z(); k++) 443 + for ( unsigned long long k = 0; k < Z(); k++)
436 { 444 {
437 - unsigned ks = k * X();  
438 - for ( unsigned j = 0; j < X(); j++) 445 + unsigned long long ks = k * X();
  446 + for ( unsigned long long j = 0; j < X(); j++)
439 q[k + j * Z()] = p[ks + j]; 447 q[k + j * Z()] = p[ks + j];
440 448
441 if(PROGRESS) progress = (double)((i+1) * Z() + k+1) / (Z() * Y()) * 100; //store the progress for the current operation 449 if(PROGRESS) progress = (double)((i+1) * Z() + k+1) / (Z() * Y()) * 100; //store the progress for the current operation
@@ -461,12 +469,12 @@ public: @@ -461,12 +469,12 @@ public:
461 /// @param result is a pointer to a pre-allocated array at least X * Y * sizeof(T) in size. 469 /// @param result is a pointer to a pre-allocated array at least X * Y * sizeof(T) in size.
462 bool baseline_band(double lb, double rb, T* lp, T* rp, double wavelength, T* result){ 470 bool baseline_band(double lb, double rb, T* lp, T* rp, double wavelength, T* result){
463 471
464 - unsigned XY = X() * Y(); 472 + unsigned long long XY = X() * Y();
465 band(result, wavelength); //get band 473 band(result, wavelength); //get band
466 474
467 //perform the baseline correction 475 //perform the baseline correction
468 double r = (double) (wavelength - lb) / (double) (rb - lb); 476 double r = (double) (wavelength - lb) / (double) (rb - lb);
469 - for(unsigned i=0; i < XY; i++){ 477 + for(unsigned long long i=0; i < XY; i++){
470 result[i] =(T) (result[i] - (rp[i] - lp[i]) * r - lp[i] ); 478 result[i] =(T) (result[i] - (rp[i] - lp[i]) * r - lp[i] );
471 } 479 }
472 return true; 480 return true;
@@ -482,8 +490,8 @@ public: @@ -482,8 +490,8 @@ public:
482 490
483 T* lp; 491 T* lp;
484 T* rp; 492 T* rp;
485 - unsigned XY = X() * Y();  
486 - unsigned S = XY * sizeof(T); 493 + unsigned long long XY = X() * Y();
  494 + unsigned long long S = XY * sizeof(T);
487 lp = (T*) malloc(S); //memory allocation 495 lp = (T*) malloc(S); //memory allocation
488 rp = (T*) malloc(S); 496 rp = (T*) malloc(S);
489 497
@@ -513,8 +521,8 @@ public: @@ -513,8 +521,8 @@ public:
513 T* cur; //current band 1 521 T* cur; //current band 1
514 T* cur2; //current band 2 522 T* cur2; //current band 2
515 523
516 - unsigned XY = X() * Y();  
517 - unsigned S = XY * sizeof(T); 524 + unsigned long long XY = X() * Y();
  525 + unsigned long long S = XY * sizeof(T);
518 526
519 lp = (T*) malloc(S); //memory allocation 527 lp = (T*) malloc(S); //memory allocation
520 rp = (T*) malloc(S); 528 rp = (T*) malloc(S);
@@ -524,9 +532,9 @@ public: @@ -524,9 +532,9 @@ public:
524 memset(result, (char)0, S); 532 memset(result, (char)0, S);
525 533
526 //find the wavelenght position in the whole band 534 //find the wavelenght position in the whole band
527 - unsigned int n = w.size();  
528 - unsigned int ai = 0; //left bound position  
529 - unsigned int bi = n - 1; //right bound position 535 + unsigned long long n = w.size();
  536 + unsigned long long ai = 0; //left bound position
  537 + unsigned long long bi = n - 1; //right bound position
530 538
531 539
532 540
@@ -555,23 +563,23 @@ public: @@ -555,23 +563,23 @@ public:
555 //calculate the beginning and the ending part 563 //calculate the beginning and the ending part
556 baseline_band(lb, rb, lp, rp, rab, cur2); //ending part 564 baseline_band(lb, rb, lp, rp, rab, cur2); //ending part
557 baseline_band(lb, rb, lp, rp, w[bi], cur); 565 baseline_band(lb, rb, lp, rp, w[bi], cur);
558 - for(unsigned j = 0; j < XY; j++){  
559 - result[j] += (rab - w[bi]) * (cur[j] + cur2[j]) / 2.0; 566 + for(unsigned long long j = 0; j < XY; j++){
  567 + result[j] += (T)((rab - w[bi]) * ((double)cur[j] + (double)cur2[j]) / 2.0);
560 } 568 }
561 baseline_band(lb, rb, lp, rp, lab, cur2); //beginnning part 569 baseline_band(lb, rb, lp, rp, lab, cur2); //beginnning part
562 baseline_band(lb, rb, lp, rp, w[ai], cur); 570 baseline_band(lb, rb, lp, rp, w[ai], cur);
563 - for(unsigned j = 0; j < XY; j++){  
564 - result[j] += (w[ai] - lab) * (cur[j] + cur2[j]) / 2.0; 571 + for(unsigned long long j = 0; j < XY; j++){
  572 + result[j] += (T)((w[ai] - lab) * ((double)cur[j] + (double)cur2[j]) / 2.0);
565 } 573 }
566 574
567 //calculate the area 575 //calculate the area
568 ai++; 576 ai++;
569 - for(unsigned i = ai; i <= bi ;i++) 577 + for(unsigned long long i = ai; i <= bi ;i++)
570 { 578 {
571 baseline_band(lb, rb, lp, rp, w[ai], cur2); 579 baseline_band(lb, rb, lp, rp, w[ai], cur2);
572 - for(unsigned j = 0; j < XY; j++) 580 + for(unsigned long long j = 0; j < XY; j++)
573 { 581 {
574 - result[j] += (w[ai] - w[ai-1]) * (cur[j] + cur2[j]) / 2.0; 582 + result[j] += (T)((w[ai] - w[ai-1]) * ((double)cur[j] + (double)cur2[j]) / 2.0);
575 } 583 }
576 std::swap(cur,cur2); //swap the band pointers 584 std::swap(cur,cur2); //swap the band pointers
577 } 585 }
@@ -601,7 +609,7 @@ public: @@ -601,7 +609,7 @@ public:
601 height(lb1, rb1, pos1, p1); 609 height(lb1, rb1, pos1, p1);
602 height(lb2, rb2, pos2, p2); 610 height(lb2, rb2, pos2, p2);
603 //calculate the ratio in result 611 //calculate the ratio in result
604 - for(unsigned i = 0; i < X() * Y(); i++){ 612 + for(unsigned long long i = 0; i < X() * Y(); i++){
605 if(p1[i] == 0 && p2[i] ==0) 613 if(p1[i] == 0 && p2[i] ==0)
606 result[i] = 1; 614 result[i] = 1;
607 else 615 else
@@ -632,7 +640,7 @@ public: @@ -632,7 +640,7 @@ public:
632 area(lb1, rb1, lab1, rab1, p1); 640 area(lb1, rb1, lab1, rab1, p1);
633 height(lb2, rb2, pos, p2); 641 height(lb2, rb2, pos, p2);
634 //calculate the ratio in result 642 //calculate the ratio in result
635 - for(unsigned i = 0; i < X() * Y(); i++){ 643 + for(unsigned long long i = 0; i < X() * Y(); i++){
636 if(p1[i] == 0 && p2[i] ==0) 644 if(p1[i] == 0 && p2[i] ==0)
637 result[i] = 1; 645 result[i] = 1;
638 else 646 else
@@ -665,7 +673,7 @@ public: @@ -665,7 +673,7 @@ public:
665 area(lb1, rb1, lab1, rab1, p1); 673 area(lb1, rb1, lab1, rab1, p1);
666 area(lb2, rb2, lab2, rab2, p2); 674 area(lb2, rb2, lab2, rab2, p2);
667 //calculate the ratio in result 675 //calculate the ratio in result
668 - for(unsigned i = 0; i < X() * Y(); i++){ 676 + for(unsigned long long i = 0; i < X() * Y(); i++){
669 if(p1[i] == 0 && p2[i] ==0) 677 if(p1[i] == 0 && p2[i] ==0)
670 result[i] = 1; 678 result[i] = 1;
671 else 679 else
@@ -690,8 +698,8 @@ public: @@ -690,8 +698,8 @@ public:
690 T* cur; //current band 1 698 T* cur; //current band 1
691 T* cur2; //current band 2 699 T* cur2; //current band 2
692 700
693 - unsigned XY = X() * Y();  
694 - unsigned S = XY * sizeof(T); 701 + unsigned long long XY = X() * Y();
  702 + unsigned long long S = XY * sizeof(T);
695 703
696 lp = (T*) malloc(S); //memory allocation 704 lp = (T*) malloc(S); //memory allocation
697 rp = (T*) malloc(S); 705 rp = (T*) malloc(S);
@@ -701,9 +709,9 @@ public: @@ -701,9 +709,9 @@ public:
701 memset(result, (char)0, S); 709 memset(result, (char)0, S);
702 710
703 //find the wavelenght position in the whole band 711 //find the wavelenght position in the whole band
704 - unsigned int n = w.size();  
705 - unsigned int ai = 0; //left bound position  
706 - unsigned int bi = n - 1; //right bound position 712 + unsigned long long n = w.size();
  713 + unsigned long long ai = 0; //left bound position
  714 + unsigned long long bi = n - 1; //right bound position
707 715
708 //to make sure the left and the right bound are in the bandwidth 716 //to make sure the left and the right bound are in the bandwidth
709 if (lb < w[0] || rb < w[0] || lb > w[n-1] || rb >w[n-1]){ 717 if (lb < w[0] || rb < w[0] || lb > w[n-1] || rb >w[n-1]){
@@ -730,23 +738,23 @@ public: @@ -730,23 +738,23 @@ public:
730 //calculate the beginning and the ending part 738 //calculate the beginning and the ending part
731 baseline_band(lb, rb, lp, rp, rab, cur2); //ending part 739 baseline_band(lb, rb, lp, rp, rab, cur2); //ending part
732 baseline_band(lb, rb, lp, rp, w[bi], cur); 740 baseline_band(lb, rb, lp, rp, w[bi], cur);
733 - for(unsigned j = 0; j < XY; j++){  
734 - result[j] += (rab - w[bi]) * (rab + w[bi]) * (cur[j] + cur2[j]) / 4.0; 741 + for(unsigned long long j = 0; j < XY; j++){
  742 + result[j] += (T)((rab - w[bi]) * (rab + w[bi]) * ((double)cur[j] + (double)cur2[j]) / 4.0);
735 } 743 }
736 baseline_band(lb, rb, lp, rp, lab, cur2); //beginnning part 744 baseline_band(lb, rb, lp, rp, lab, cur2); //beginnning part
737 baseline_band(lb, rb, lp, rp, w[ai], cur); 745 baseline_band(lb, rb, lp, rp, w[ai], cur);
738 - for(unsigned j = 0; j < XY; j++){  
739 - result[j] += (w[ai] - lab) * (w[ai] + lab) * (cur[j] + cur2[j]) / 4.0; 746 + for(unsigned long long j = 0; j < XY; j++){
  747 + result[j] += (T)((w[ai] - lab) * (w[ai] + lab) * ((double)cur[j] + (double)cur2[j]) / 4.0);
740 } 748 }
741 749
742 //calculate f(x) times x 750 //calculate f(x) times x
743 ai++; 751 ai++;
744 - for(unsigned i = ai; i <= bi ;i++) 752 + for(unsigned long long i = ai; i <= bi ;i++)
745 { 753 {
746 baseline_band(lb, rb, lp, rp, w[ai], cur2); 754 baseline_band(lb, rb, lp, rp, w[ai], cur2);
747 - for(unsigned j = 0; j < XY; j++) 755 + for(unsigned long long j = 0; j < XY; j++)
748 { 756 {
749 - result[j] += (w[ai] - w[ai-1]) * (w[ai] + w[ai-1]) * (cur[j] + cur2[j]) / 4.0; 757 + result[j] += (T)((w[ai] - w[ai-1]) * (w[ai] + w[ai-1]) * ((double)cur[j] + (double)cur2[j]) / 4.0);
750 } 758 }
751 std::swap(cur,cur2); //swap the band pointers 759 std::swap(cur,cur2); //swap the band pointers
752 } 760 }
@@ -773,7 +781,7 @@ public: @@ -773,7 +781,7 @@ public:
773 x_area(lb, rb, lab, rab, p1); 781 x_area(lb, rb, lab, rab, p1);
774 area(lb, rb, lab, rab, p2); 782 area(lb, rb, lab, rab, p2);
775 //calculate the ratio in result 783 //calculate the ratio in result
776 - for(unsigned i = 0; i < X() * Y(); i++){ 784 + for(unsigned long long i = 0; i < X() * Y(); i++){
777 if(p1[i] == 0 && p2[i] ==0) 785 if(p1[i] == 0 && p2[i] ==0)
778 result[i] = 1; 786 result[i] = 1;
779 else 787 else
@@ -797,7 +805,7 @@ public: @@ -797,7 +805,7 @@ public:
797 T* temp = (T*)malloc(X() * Y() * sizeof(T)); //allocate memory for the certain band 805 T* temp = (T*)malloc(X() * Y() * sizeof(T)); //allocate memory for the certain band
798 band(temp, mask_band, PROGRESS); 806 band(temp, mask_band, PROGRESS);
799 807
800 - for (unsigned int i = 0; i < X() * Y(); i++) { 808 + for (unsigned long long i = 0; i < X() * Y(); i++) {
801 if (temp[i] < threshold) 809 if (temp[i] < threshold)
802 p[i] = 0; 810 p[i] = 0;
803 else 811 else
@@ -817,17 +825,17 @@ public: @@ -817,17 +825,17 @@ public:
817 std::ofstream target(outfile.c_str(), std::ios::binary); 825 std::ofstream target(outfile.c_str(), std::ios::binary);
818 826
819 //I THINK THIS IS WRONG 827 //I THINK THIS IS WRONG
820 - unsigned XZ = X() * Z(); //calculate the number of values in a page on disk  
821 - unsigned L = XZ * sizeof(T); //calculate the size of the page (in bytes) 828 + unsigned long long XZ = X() * Z(); //calculate the number of values in a page on disk
  829 + unsigned long long L = XZ * sizeof(T); //calculate the size of the page (in bytes)
822 830
823 T * temp = (T*)malloc(L); //allocate memory for a temporary page 831 T * temp = (T*)malloc(L); //allocate memory for a temporary page
824 832
825 - for (unsigned i = 0; i < Y(); i++) //for each value in Y() (BIP should be X) 833 + for (unsigned long long i = 0; i < Y(); i++) //for each value in Y() (BIP should be X)
826 { 834 {
827 read_plane_y(temp, i); //retrieve an ZX slice, stored in temp 835 read_plane_y(temp, i); //retrieve an ZX slice, stored in temp
828 - for ( unsigned j = 0; j < Z(); j++) //for each Z() (Y) 836 + for ( unsigned long long j = 0; j < Z(); j++) //for each Z() (Y)
829 { 837 {
830 - for (unsigned k = 0; k < X(); k++) //for each band 838 + for (unsigned long long k = 0; k < X(); k++) //for each band
831 { 839 {
832 if(p[i * X() + k] == 0) 840 if(p[i * X() + k] == 0)
833 temp[j * X() + k] = 0; 841 temp[j * X() + k] = 0;
@@ -849,9 +857,9 @@ public: @@ -849,9 +857,9 @@ public:
849 std::ofstream target(outfile.c_str(), std::ios::binary); 857 std::ofstream target(outfile.c_str(), std::ios::binary);
850 858
851 //for loading pages: 859 //for loading pages:
852 - unsigned long XZ = X() * Z(); //calculate the number of values in an XZ page on disk  
853 - unsigned long B = Z(); //calculate the number of bands  
854 - unsigned long L = XZ * sizeof(T); //calculate the size of the page (in bytes) 860 + unsigned long long XZ = X() * Z(); //calculate the number of values in an XZ page on disk
  861 + unsigned long long B = Z(); //calculate the number of bands
  862 + unsigned long long L = XZ * sizeof(T); //calculate the size of the page (in bytes)
855 863
856 //allocate temporary memory for a XZ slice 864 //allocate temporary memory for a XZ slice
857 T* slice = (T*) malloc(L); 865 T* slice = (T*) malloc(L);
@@ -860,18 +868,18 @@ public: @@ -860,18 +868,18 @@ public:
860 T* spec = (T*) malloc(B * sizeof(T)); 868 T* spec = (T*) malloc(B * sizeof(T));
861 869
862 //for each slice along the y axis 870 //for each slice along the y axis
863 - for (unsigned long y = 0; y < Y(); y++) //Select a page by choosing Y coordinate, Y() 871 + for (unsigned long long y = 0; y < Y(); y++) //Select a page by choosing Y coordinate, Y()
864 { 872 {
865 read_plane_y(slice, y); //retrieve an ZX page, store in "slice" 873 read_plane_y(slice, y); //retrieve an ZX page, store in "slice"
866 874
867 //for each sample along X 875 //for each sample along X
868 - for (unsigned long x = 0; x < X(); x++) //Select a pixel by choosing X coordinate in the page, X() 876 + for (unsigned long long x = 0; x < X(); x++) //Select a pixel by choosing X coordinate in the page, X()
869 { 877 {
870 //if the mask != 0 at that xy pixel 878 //if the mask != 0 at that xy pixel
871 if (p[y * X() + x] != 0) //if the mask != 0 at that XY pixel 879 if (p[y * X() + x] != 0) //if the mask != 0 at that XY pixel
872 { 880 {
873 //for each band at that pixel 881 //for each band at that pixel
874 - for (unsigned long b = 0; b < B; b++) //Select a voxel by choosing Z coordinate at the pixel 882 + for (unsigned long long b = 0; b < B; b++) //Select a voxel by choosing Z coordinate at the pixel
875 { 883 {
876 spec[b] = slice[b*X() + x]; //Pass the correct spectral value from XZ page into the spectrum to be saved. 884 spec[b] = slice[b*X() + x]; //Pass the correct spectral value from XZ page into the spectrum to be saved.
877 } 885 }
@@ -896,20 +904,20 @@ public: @@ -896,20 +904,20 @@ public:
896 T* temp = (T*)malloc(sizeof(T) * XZ); 904 T* temp = (T*)malloc(sizeof(T) * XZ);
897 T* line = (T*)malloc(sizeof(T) * X()); 905 T* line = (T*)malloc(sizeof(T) * X());
898 906
899 - for (unsigned i = 0; i < Y(); i++){ 907 + for (unsigned long long i = 0; i < Y(); i++){
900 getY(temp, i); 908 getY(temp, i);
901 //initialize x-line 909 //initialize x-line
902 - for (unsigned j = 0; j < X(); j++){ 910 + for (unsigned long long j = 0; j < X(); j++){
903 line[j] = 0; 911 line[j] = 0;
904 } 912 }
905 - unsigned c = 0;  
906 - for (unsigned j = 0; j < Z(); j++){  
907 - for (unsigned k = 0; k < X(); k++){ 913 + unsigned long long c = 0;
  914 + for (unsigned long long j = 0; j < Z(); j++){
  915 + for (unsigned long long k = 0; k < X(); k++){
908 line[k] += temp[c] / (T)Z(); 916 line[k] += temp[c] / (T)Z();
909 c++; 917 c++;
910 } 918 }
911 } 919 }
912 - for (unsigned j = 0; j < X(); j++){ 920 + for (unsigned long long j = 0; j < X(); j++){
913 p[j + i * X()] = line[j]; 921 p[j + i * X()] = line[j];
914 } 922 }
915 } 923 }
@@ -925,7 +933,7 @@ public: @@ -925,7 +933,7 @@ public:
925 unsigned long long XZ = X() * Z(); 933 unsigned long long XZ = X() * Z();
926 unsigned long long XY = X() * Y(); 934 unsigned long long XY = X() * Y();
927 T* temp = (T*)malloc(sizeof(T) * XZ); 935 T* temp = (T*)malloc(sizeof(T) * XZ);
928 - for (unsigned j = 0; j < Z(); j++){ 936 + for (unsigned long long j = 0; j < Z(); j++){
929 p[j] = 0; 937 p[j] = 0;
930 } 938 }
931 //calculate vaild number in a band 939 //calculate vaild number in a band
@@ -1038,9 +1046,9 @@ public: @@ -1038,9 +1046,9 @@ public:
1038 //set the start position for the cropped region 1046 //set the start position for the cropped region
1039 file.seekg((y0 * X() * Z() + b0 * X() + x0) * sizeof(T), std::ios::beg); 1047 file.seekg((y0 * X() * Z() + b0 * X() + x0) * sizeof(T), std::ios::beg);
1040 1048
1041 - for (unsigned x = 0; x < lines; x++) 1049 + for (unsigned long long x = 0; x < lines; x++)
1042 { 1050 {
1043 - for (unsigned z = b0; z < b1; z++) 1051 + for (unsigned long long z = b0; z < b1; z++)
1044 { 1052 {
1045 file.read((char *)(temp + z * samples), sizeof(T) * samples); 1053 file.read((char *)(temp + z * samples), sizeof(T) * samples);
1046 file.seekg(jumpb, std::ios::cur); //go to the next band 1054 file.seekg(jumpb, std::ios::cur); //go to the next band
stim/envi/binary.h
@@ -25,7 +25,7 @@ protected: @@ -25,7 +25,7 @@ protected:
25 std::string name; //file name 25 std::string name; //file name
26 26
27 unsigned long long R[D]; //resolution 27 unsigned long long R[D]; //resolution
28 - unsigned int header; //header size (in bytes) 28 + unsigned long long header; //header size (in bytes)
29 unsigned char* mask; //pointer to a character array: 0 = background, 1 = foreground (or valid data) 29 unsigned char* mask; //pointer to a character array: 0 = background, 1 = foreground (or valid data)
30 30
31 double progress; //stores the progress on the current operation (accessible using a thread) 31 double progress; //stores the progress on the current operation (accessible using a thread)
@@ -33,30 +33,13 @@ protected: @@ -33,30 +33,13 @@ protected:
33 33
34 /// Private initialization function used to set default parameters in the data structure. 34 /// Private initialization function used to set default parameters in the data structure.
35 void init(){ 35 void init(){
36 - memset(R, 0, sizeof(unsigned int) * D); //initialize the resolution to zero 36 + memset(R, 0, sizeof(unsigned long long) * D); //initialize the resolution to zero
37 header = 0; //initialize the header size to zero 37 header = 0; //initialize the header size to zero
38 mask = NULL; 38 mask = NULL;
39 39
40 progress = 0; 40 progress = 0;
41 } 41 }
42 42
43 - //calculate the number of non-zero pixels in a mask  
44 - unsigned long long nnz(unsigned char* mask, unsigned long long N){  
45 -  
46 - unsigned long long n = 0; //initialize the counter to 0 (zero)  
47 - if(mask == NULL) return N; //if the mask is NULL, assume all pixels are masked  
48 -  
49 - for(unsigned long long i = 0; i < N; i++){ //for each pixel  
50 - if(mask[i] != 0) n++; //increment the counter for every non-zero pixel in the mask  
51 - }  
52 - return n; //return the number of nonzero pixels  
53 - }  
54 -  
55 - /// Calculate the number of nonzero pixels in a mask over X-Y  
56 - unsigned long long nnz(unsigned char* mask){  
57 - return nnz(mask, R[0] * R[1]);  
58 - }  
59 -  
60 /// Private helper function that returns the size of the file on disk using system functions. 43 /// Private helper function that returns the size of the file on disk using system functions.
61 long long int get_file_size(){ 44 long long int get_file_size(){
62 #ifdef _WIN32 45 #ifdef _WIN32
@@ -122,7 +105,7 @@ protected: @@ -122,7 +105,7 @@ protected:
122 105
123 public: 106 public:
124 107
125 - unsigned int get_progress(){ 108 + double get_progress(){
126 return progress; 109 return progress;
127 } 110 }
128 111
@@ -135,9 +118,9 @@ public: @@ -135,9 +118,9 @@ public:
135 /// @param filename is the name of the binary file 118 /// @param filename is the name of the binary file
136 /// @param r is a STIM vector specifying the size of the binary file along each dimension 119 /// @param r is a STIM vector specifying the size of the binary file along each dimension
137 /// @param h is the length (in bytes) of any header file (default zero) 120 /// @param h is the length (in bytes) of any header file (default zero)
138 - bool open(std::string filename, vec<unsigned int> r, unsigned int h = 0){ 121 + bool open(std::string filename, vec<unsigned long long> r, unsigned long long h = 0){
139 122
140 - for(unsigned int i = 0; i < D; i++) //set the dimensions of the binary file object 123 + for(unsigned long long i = 0; i < D; i++) //set the dimensions of the binary file object
141 R[i] = r[i]; 124 R[i] = r[i];
142 125
143 header = h; //save the header size 126 header = h; //save the header size
@@ -154,17 +137,17 @@ public: @@ -154,17 +137,17 @@ public:
154 /// @param filename is the name of the binary file to be created 137 /// @param filename is the name of the binary file to be created
155 /// @param r is a STIM vector specifying the size of the file along each dimension 138 /// @param r is a STIM vector specifying the size of the file along each dimension
156 /// @offset specifies how many bytes to offset the file (used to leave room for a header) 139 /// @offset specifies how many bytes to offset the file (used to leave room for a header)
157 - bool create(std::string filename, vec<unsigned int> r, unsigned int offset = 0){ 140 + bool create(std::string filename, vec<unsigned long long> r, unsigned long long offset = 0){
158 141
159 std::ofstream target(filename.c_str(), std::ios::binary); 142 std::ofstream target(filename.c_str(), std::ios::binary);
160 143
161 //initialize binary file 144 //initialize binary file
162 T p = 0; 145 T p = 0;
163 - for(unsigned int i =0; i < r[0] * r[1] * r[2]; i++){ 146 + for(unsigned long long i =0; i < r[0] * r[1] * r[2]; i++){
164 target.write((char*)(&p), sizeof(T)); 147 target.write((char*)(&p), sizeof(T));
165 } 148 }
166 149
167 - for(unsigned int i = 0; i < D; i++) //set the dimensions of the binary file object 150 + for(unsigned long long i = 0; i < D; i++) //set the dimensions of the binary file object
168 R[i] = r[i]; 151 R[i] = r[i];
169 152
170 header = offset; //save the header size 153 header = offset; //save the header size
@@ -178,7 +161,7 @@ public: @@ -178,7 +161,7 @@ public:
178 161
179 /// @param p is a pointer to the data to be written 162 /// @param p is a pointer to the data to be written
180 /// @param page is the page number (index of the highest-numbered dimension) 163 /// @param page is the page number (index of the highest-numbered dimension)
181 - bool write_page( T * p, unsigned int page){ 164 + bool write_page( T * p, unsigned long long page){
182 165
183 if(p == NULL){ 166 if(p == NULL){
184 std::cout<<"ERROR: unable to write into file, empty pointer"<<std::endl; 167 std::cout<<"ERROR: unable to write into file, empty pointer"<<std::endl;
@@ -195,7 +178,7 @@ public: @@ -195,7 +178,7 @@ public:
195 178
196 /// @param p is a pointer to pre-allocated memory equal to the page size 179 /// @param p is a pointer to pre-allocated memory equal to the page size
197 /// @param page is the index of the page 180 /// @param page is the index of the page
198 - bool read_page( T * p, unsigned int page, bool PROGRESS = false){ 181 + bool read_page( T * p, unsigned long long page, bool PROGRESS = false){
199 182
200 if(PROGRESS) progress = 0; 183 if(PROGRESS) progress = 0;
201 184
@@ -217,8 +200,8 @@ public: @@ -217,8 +200,8 @@ public:
217 /// @param p is a pointer to pre-allocated memory equal to the line size R[2] 200 /// @param p is a pointer to pre-allocated memory equal to the line size R[2]
218 /// @param x is the x coordinate 201 /// @param x is the x coordinate
219 /// @param y is the y coordinate 202 /// @param y is the y coordinate
220 - bool read_line_2( T * p, unsigned int x, unsigned int y, bool PROGRESS = false){  
221 - unsigned int i; 203 + bool read_line_2( T * p, unsigned long long x, unsigned long long y, bool PROGRESS = false){
  204 + unsigned long long i;
222 205
223 if(PROGRESS) progress = 0; 206 if(PROGRESS) progress = 0;
224 207
@@ -244,7 +227,7 @@ public: @@ -244,7 +227,7 @@ public:
244 /// @param p is a pointer to pre-allocated memory equal to the line size R[2] 227 /// @param p is a pointer to pre-allocated memory equal to the line size R[2]
245 /// @param x is the y coordinate 228 /// @param x is the y coordinate
246 /// @param y is the z coordinate 229 /// @param y is the z coordinate
247 - bool read_line_0(T * p, unsigned int y, unsigned int z, bool PROGRESS = false){ 230 + bool read_line_0(T * p, unsigned long long y, unsigned long long z, bool PROGRESS = false){
248 //test to make sure the specified value is within range 231 //test to make sure the specified value is within range
249 if( y >= R[1] || z >= R[2] ){ 232 if( y >= R[1] || z >= R[2] ){
250 std::cout<<"ERROR: sample or line out of range"<<std::endl; 233 std::cout<<"ERROR: sample or line out of range"<<std::endl;
@@ -262,7 +245,7 @@ public: @@ -262,7 +245,7 @@ public:
262 /// @param p is a pointer to pre-allocated memory equal to the line size R[2] 245 /// @param p is a pointer to pre-allocated memory equal to the line size R[2]
263 /// @param x is the y coordinate 246 /// @param x is the y coordinate
264 /// @param z is the z coordinate 247 /// @param z is the z coordinate
265 - bool read_line_1(T * p, unsigned int x, unsigned int z, bool PROGRESS = false){ 248 + bool read_line_1(T * p, unsigned long long x, unsigned long long z, bool PROGRESS = false){
266 if(PROGRESS) progress = 0; 249 if(PROGRESS) progress = 0;
267 //test to make sure the specified value is within range 250 //test to make sure the specified value is within range
268 if( x >= R[0] || z >= R[2] ){ 251 if( x >= R[0] || z >= R[2] ){
@@ -271,7 +254,7 @@ public: @@ -271,7 +254,7 @@ public:
271 } 254 }
272 255
273 file.seekg((z * R[0] * R[1] + x) * sizeof(T), std::ios::beg); //seek to the start of the line 256 file.seekg((z * R[0] * R[1] + x) * sizeof(T), std::ios::beg); //seek to the start of the line
274 - for (unsigned int i = 0; i < R[1]; i++){ //for each pixel in the line 257 + for (unsigned long long i = 0; i < R[1]; i++){ //for each pixel in the line
275 file.read((char *)(p + i), sizeof(T)); //read the pixel 258 file.read((char *)(p + i), sizeof(T)); //read the pixel
276 file.seekg((R[0] - 1) * sizeof(T), std::ios::cur); //seek to the next pixel in the line 259 file.seekg((R[0] - 1) * sizeof(T), std::ios::cur); //seek to the next pixel in the line
277 if(PROGRESS) progress = (double)i / (double)R[1] * 100; 260 if(PROGRESS) progress = (double)i / (double)R[1] * 100;
@@ -284,22 +267,22 @@ public: @@ -284,22 +267,22 @@ public:
284 267
285 /// @param p is a pointer to pre-allocated memory of size R[1] * R[2] * sizeof(T) 268 /// @param p is a pointer to pre-allocated memory of size R[1] * R[2] * sizeof(T)
286 /// @param n is the 0-axis coordinate used to retrieve the plane 269 /// @param n is the 0-axis coordinate used to retrieve the plane
287 - bool read_plane_0(T* p, unsigned int n, bool PROGRESS = false){ 270 + bool read_plane_0(T* p, unsigned long long n, bool PROGRESS = false){
288 if(PROGRESS) progress = 0; 271 if(PROGRESS) progress = 0;
289 if (n >= R[0]){ //make sure the number is within the possible range 272 if (n >= R[0]){ //make sure the number is within the possible range
290 std::cout<<"ERROR read_plane_0: page out of range"<<std::endl; 273 std::cout<<"ERROR read_plane_0: page out of range"<<std::endl;
291 return false; 274 return false;
292 } 275 }
293 - unsigned int jump = (R[0] - 1) * sizeof(T); //number of bytes to skip between samples 276 + unsigned long long jump = (R[0] - 1) * sizeof(T); //number of bytes to skip between samples
294 277
295 //seek to the start of the plane 278 //seek to the start of the plane
296 file.seekg(n * sizeof(T), std::ios::beg); 279 file.seekg(n * sizeof(T), std::ios::beg);
297 280
298 - unsigned int N = R[1] * R[2];  
299 - for(unsigned int i = 0; i<N; i++){ 281 + unsigned long long N = R[1] * R[2];
  282 + for(unsigned long long i = 0; i<N; i++){
300 file.read((char*)(p+i), sizeof(T)); 283 file.read((char*)(p+i), sizeof(T));
301 file.seekg(jump, std::ios::cur); 284 file.seekg(jump, std::ios::cur);
302 - if(PROGRESS) progress = (double)i / N * 100; 285 + if(PROGRESS) progress = (double)(i+1) / N * 100;
303 } 286 }
304 287
305 if(PROGRESS) progress = 100; 288 if(PROGRESS) progress = 100;
@@ -312,10 +295,10 @@ public: @@ -312,10 +295,10 @@ public:
312 295
313 /// @param p is a pointer to pre-allocated memory of size R[0] * R[2] * sizeof(T) 296 /// @param p is a pointer to pre-allocated memory of size R[0] * R[2] * sizeof(T)
314 /// @param n is the 1-axis coordinate used to retrieve the plane 297 /// @param n is the 1-axis coordinate used to retrieve the plane
315 - bool read_plane_1(T* p, unsigned int n, bool PROGRESS = false){ 298 + bool read_plane_1(T* p, unsigned long long n, bool PROGRESS = false){
316 if(PROGRESS) progress = 0; 299 if(PROGRESS) progress = 0;
317 - unsigned int L = R[0] * sizeof(T); //caculate the number of bytes in a sample line  
318 - unsigned int jump = R[0] * (R[1] - 1) * sizeof(T); 300 + unsigned long long L = R[0] * sizeof(T); //caculate the number of bytes in a sample line
  301 + unsigned long long jump = R[0] * (R[1] - 1) * sizeof(T);
319 302
320 if (n >= R[1]){ //make sure the bank number is right 303 if (n >= R[1]){ //make sure the bank number is right
321 std::cout<<"ERROR read_plane_1: page out of range"<<std::endl; 304 std::cout<<"ERROR read_plane_1: page out of range"<<std::endl;
@@ -323,7 +306,7 @@ public: @@ -323,7 +306,7 @@ public:
323 } 306 }
324 307
325 file.seekg(R[0] * n * sizeof(T), std::ios::beg); 308 file.seekg(R[0] * n * sizeof(T), std::ios::beg);
326 - for (unsigned i = 0; i < R[2]; i++){ 309 + for (unsigned long long i = 0; i < R[2]; i++){
327 if(PROGRESS) progress = (double)i / R[2] * 100; 310 if(PROGRESS) progress = (double)i / R[2] * 100;
328 file.read((char *)(p + i * R[0]), L); 311 file.read((char *)(p + i * R[0]), L);
329 file.seekg( jump, std::ios::cur); 312 file.seekg( jump, std::ios::cur);
@@ -338,7 +321,7 @@ public: @@ -338,7 +321,7 @@ public:
338 321
339 /// @param p is a pointer to pre-allocated memory of size R[0] * R[1] * sizeof(T) 322 /// @param p is a pointer to pre-allocated memory of size R[0] * R[1] * sizeof(T)
340 /// @param n is the 2-axis coordinate used to retrieve the plane 323 /// @param n is the 2-axis coordinate used to retrieve the plane
341 - bool read_plane_2(T* p, unsigned int n, bool PROGRESS = false){ 324 + bool read_plane_2(T* p, unsigned long long n, bool PROGRESS = false){
342 return read_page(p, n, PROGRESS); 325 return read_page(p, n, PROGRESS);
343 } 326 }
344 327
@@ -346,7 +329,7 @@ public: @@ -346,7 +329,7 @@ public:
346 329
347 /// @param p is a pointer to pre-allocated memory of size sizeof(T) 330 /// @param p is a pointer to pre-allocated memory of size sizeof(T)
348 /// @param i is the index to the pixel using linear indexing 331 /// @param i is the index to the pixel using linear indexing
349 - bool read_pixel(T* p, unsigned int i){ 332 + bool read_pixel(T* p, unsigned long long i){
350 if(i >= R[0] * R[1] * R[2]){ 333 if(i >= R[0] * R[1] * R[2]){
351 std::cout<<"ERROR read_pixel: n is out of range"<<std::endl; 334 std::cout<<"ERROR read_pixel: n is out of range"<<std::endl;
352 return false; 335 return false;
@@ -363,14 +346,14 @@ public: @@ -363,14 +346,14 @@ public:
363 /// @param x is the x (0) axis coordinate 346 /// @param x is the x (0) axis coordinate
364 /// @param y is the y (1) axis coordinate 347 /// @param y is the y (1) axis coordinate
365 /// @param z is the z (2) axis coordinate 348 /// @param z is the z (2) axis coordinate
366 - bool read_pixel(T* p, unsigned int x, unsigned int y, unsigned int z){ 349 + bool read_pixel(T* p, unsigned long long x, unsigned long long y, unsigned long long z){
367 350
368 if(x < 0 || x >= R[0] || y < 0 || y >= R[1] || z < 0 || z > R[2]){ 351 if(x < 0 || x >= R[0] || y < 0 || y >= R[1] || z < 0 || z > R[2]){
369 std::cout<<"ERROR read_pixel: (x,y,z) is out of range"<<std::endl; 352 std::cout<<"ERROR read_pixel: (x,y,z) is out of range"<<std::endl;
370 return false; 353 return false;
371 } 354 }
372 355
373 - unsigned int i = z * R[0] * R[1] + y * R[0] + z; 356 + unsigned long long i = z * R[0] * R[1] + y * R[0] + z;
374 return read_pixel(p, i); 357 return read_pixel(p, i);
375 } 358 }
376 359
@@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
3 3
4 #include "../envi/envi_header.h" 4 #include "../envi/envi_header.h"
5 #include "../envi/bil.h" 5 #include "../envi/bil.h"
6 -#include "../envi/binary.h" 6 +#include "../envi/hsi.h"
7 #include <cstring> 7 #include <cstring>
8 #include <utility> 8 #include <utility>
9 9
@@ -23,15 +23,15 @@ namespace stim{ @@ -23,15 +23,15 @@ namespace stim{
23 */ 23 */
24 template <typename T> 24 template <typename T>
25 25
26 -class bip: public binary<T> { 26 +class bip: public hsi<T> {
27 27
28 protected: 28 protected:
29 29
30 30
31 - std::vector<double> w; //band wavelength  
32 - unsigned int offset; //header offset 31 + //std::vector<double> w; //band wavelength
  32 + unsigned long long offset; //header offset
33 33
34 - unsigned long long X(){ 34 + /*unsigned long long X(){
35 return R[1]; 35 return R[1];
36 } 36 }
37 unsigned long long Y(){ 37 unsigned long long Y(){
@@ -39,17 +39,18 @@ protected: @@ -39,17 +39,18 @@ protected:
39 } 39 }
40 unsigned long long Z(){ 40 unsigned long long Z(){
41 return R[0]; 41 return R[0];
42 - }  
43 - 42 + }*/
  43 + using hsi<T>::w; //use the wavelength array in stim::hsi
  44 + using hsi<T>::nnz;
44 using binary<T>::progress; 45 using binary<T>::progress;
45 46
46 /// Call the binary nnz() function for the BIP orientation 47 /// Call the binary nnz() function for the BIP orientation
47 - unsigned long long nnz(unsigned char* mask){  
48 - return binary<T>::nnz(mask, X()*Y());  
49 - } 48 + //unsigned long long nnz(unsigned char* mask){
  49 + // return binary<T>::nnz(mask, X()*Y());
  50 + //}
50 51
51 /// Linear interpolation of a spectral value given the bounding spectral samples 52 /// Linear interpolation of a spectral value given the bounding spectral samples
52 - T lerp(double w, T low_v, double low_w, T high_v, double high_w){ 53 + /*T lerp(double w, T low_v, double low_w, T high_v, double high_w){
53 if(low_w == high_w) return low_v; //if the interval is of zero length, just return one of the bounds 54 if(low_w == high_w) return low_v; //if the interval is of zero length, just return one of the bounds
54 double alpha = (w - low_w) / (high_w - low_w); //calculate the interpolation factor 55 double alpha = (w - low_w) / (high_w - low_w); //calculate the interpolation factor
55 return (1.0 - alpha) * low_v + alpha * high_v; //interpolate 56 return (1.0 - alpha) * low_v + alpha * high_v; //interpolate
@@ -104,7 +105,7 @@ protected: @@ -104,7 +105,7 @@ protected:
104 v[n] = interp_spectrum(s, wavelengths[n]); //interpolate the measurement 105 v[n] = interp_spectrum(s, wavelengths[n]); //interpolate the measurement
105 } 106 }
106 return v; 107 return v;
107 - } 108 + }*/
108 109
109 public: 110 public:
110 111
@@ -113,6 +114,8 @@ public: @@ -113,6 +114,8 @@ public:
113 using binary<T>::R; 114 using binary<T>::R;
114 using binary<T>::read_line_0; 115 using binary<T>::read_line_0;
115 116
  117 + bip(){ hsi<T>::init_bip(); }
  118 +
116 /// Open a data file for reading using the class interface. 119 /// Open a data file for reading using the class interface.
117 120
118 /// @param filename is the name of the binary file on disk 121 /// @param filename is the name of the binary file on disk
@@ -121,14 +124,19 @@ public: @@ -121,14 +124,19 @@ public:
121 /// @param B is the number of samples (bands) along dimension 3 124 /// @param B is the number of samples (bands) along dimension 3
122 /// @param header_offset is the number of bytes (if any) in the binary header 125 /// @param header_offset is the number of bytes (if any) in the binary header
123 /// @param wavelengths is an optional STL vector of size B specifying a numerical label for each band 126 /// @param wavelengths is an optional STL vector of size B specifying a numerical label for each band
124 - bool open(std::string filename, unsigned int X, unsigned int Y, unsigned int B, unsigned int header_offset, std::vector<double> wavelengths){ 127 + bool open(std::string filename,
  128 + unsigned long long X,
  129 + unsigned long long Y,
  130 + unsigned long long B,
  131 + unsigned long long header_offset,
  132 + std::vector<double> wavelengths){
125 133
126 //copy the wavelengths to the BSQ file structure 134 //copy the wavelengths to the BSQ file structure
127 w = wavelengths; 135 w = wavelengths;
128 //copy the offset to the structure 136 //copy the offset to the structure
129 offset = header_offset; 137 offset = header_offset;
130 138
131 - return open(filename, vec<unsigned int>(B, X, Y), header_offset); 139 + return open(filename, vec<unsigned long long>(B, X, Y), header_offset);
132 140
133 } 141 }
134 142
@@ -136,7 +144,7 @@ public: @@ -136,7 +144,7 @@ public:
136 144
137 /// @param p is a pointer to an allocated region of memory at least X * Y * sizeof(T) in size. 145 /// @param p is a pointer to an allocated region of memory at least X * Y * sizeof(T) in size.
138 /// @param page <= B is the integer number of the band to be copied. 146 /// @param page <= B is the integer number of the band to be copied.
139 - bool band_index( T * p, unsigned int page, bool PROGRESS = false){ 147 + bool band_index( T * p, unsigned long long page, bool PROGRESS = false){
140 return binary<T>::read_plane_0(p, page, PROGRESS); 148 return binary<T>::read_plane_0(p, page, PROGRESS);
141 } 149 }
142 150
@@ -148,9 +156,9 @@ public: @@ -148,9 +156,9 @@ public:
148 156
149 //if there are no wavelengths in the BSQ file 157 //if there are no wavelengths in the BSQ file
150 if(w.size() == 0) 158 if(w.size() == 0)
151 - return band_index(p, (unsigned int)wavelength, PROGRESS); 159 + return band_index(p, (unsigned long long)wavelength, PROGRESS);
152 160
153 - unsigned int XY = X() * Y(); //calculate the number of pixels in a band 161 + unsigned long long XY = X() * Y(); //calculate the number of pixels in a band
154 162
155 unsigned page=0; //bands around the wavelength 163 unsigned page=0; //bands around the wavelength
156 164
@@ -180,9 +188,9 @@ public: @@ -180,9 +188,9 @@ public:
180 p2=(T*)malloc( XY * sizeof(T)); 188 p2=(T*)malloc( XY * sizeof(T));
181 band_index(p1, page - 1); 189 band_index(p1, page - 1);
182 band_index(p2, page, PROGRESS); 190 band_index(p2, page, PROGRESS);
183 - for(unsigned i=0; i < XY; i++){ 191 + for(unsigned long long i=0; i < XY; i++){
184 double r = (double) (wavelength - w[page-1]) / (double) (w[page] - w[page-1]); 192 double r = (double) (wavelength - w[page-1]) / (double) (w[page] - w[page-1]);
185 - p[i] = (p2[i] - p1[i]) * r + p1[i]; 193 + p[i] = (T)(((double)p2[i] - (double)p1[i]) * r + (double)p1[i]);
186 } 194 }
187 free(p1); 195 free(p1);
188 free(p2); 196 free(p2);
@@ -200,7 +208,7 @@ public: @@ -200,7 +208,7 @@ public:
200 /// @param p is a pointer to pre-allocated memory at least B * sizeof(T) in size. 208 /// @param p is a pointer to pre-allocated memory at least B * sizeof(T) in size.
201 /// @param x is the x-coordinate (dimension 1) of the spectrum. 209 /// @param x is the x-coordinate (dimension 1) of the spectrum.
202 /// @param y is the y-coordinate (dimension 2) of the spectrum. 210 /// @param y is the y-coordinate (dimension 2) of the spectrum.
203 - bool spectrum(T * p, unsigned x, unsigned y, bool PROGRESS = false){ 211 + bool spectrum(T * p, unsigned long long x, unsigned long long y, bool PROGRESS = false){
204 return read_line_0(p, x, y, PROGRESS); //read a line in the binary YZ plane (dimension order for BIP is ZXY) 212 return read_line_0(p, x, y, PROGRESS); //read a line in the binary YZ plane (dimension order for BIP is ZXY)
205 } 213 }
206 214
@@ -211,16 +219,16 @@ public: @@ -211,16 +219,16 @@ public:
211 /// @param wavelength is the wavelength of X values to retrieve 219 /// @param wavelength is the wavelength of X values to retrieve
212 bool read_x_from_xz(T* p, T* c, double wavelength) 220 bool read_x_from_xz(T* p, T* c, double wavelength)
213 { 221 {
214 - unsigned int B = Z(); 222 + unsigned long long B = Z();
215 223
216 - unsigned page=0; //samples around the wavelength 224 + unsigned long long page=0; //samples around the wavelength
217 225
218 226
219 //get the bands numbers around the wavelength 227 //get the bands numbers around the wavelength
220 228
221 //if wavelength is smaller than the first one in header file 229 //if wavelength is smaller than the first one in header file
222 if ( w[page] > wavelength ){ 230 if ( w[page] > wavelength ){
223 - for(unsigned j = 0; j < X(); j++) 231 + for(unsigned long long j = 0; j < X(); j++)
224 { 232 {
225 p[j] = c[j * B]; 233 p[j] = c[j * B];
226 } 234 }
@@ -232,7 +240,7 @@ public: @@ -232,7 +240,7 @@ public:
232 page++; 240 page++;
233 //if wavelength is larger than the last wavelength in header file 241 //if wavelength is larger than the last wavelength in header file
234 if (page == B) { 242 if (page == B) {
235 - for(unsigned j = 0; j < X(); j++) 243 + for(unsigned long long j = 0; j < X(); j++)
236 { 244 {
237 p[j] = c[(j + 1) * B - 1]; 245 p[j] = c[(j + 1) * B - 1];
238 } 246 }
@@ -246,17 +254,17 @@ public: @@ -246,17 +254,17 @@ public:
246 p1=(T*)malloc( X() * sizeof(T)); //memory allocation 254 p1=(T*)malloc( X() * sizeof(T)); //memory allocation
247 p2=(T*)malloc( X() * sizeof(T)); 255 p2=(T*)malloc( X() * sizeof(T));
248 //band_index(p1, page - 1); 256 //band_index(p1, page - 1);
249 - for(unsigned j = 0; j < X(); j++) 257 + for(unsigned long long j = 0; j < X(); j++)
250 { 258 {
251 p1[j] = c[j * B + page - 1]; 259 p1[j] = c[j * B + page - 1];
252 } 260 }
253 //band_index(p2, page ); 261 //band_index(p2, page );
254 - for(unsigned j = 0; j < X(); j++) 262 + for(unsigned long long j = 0; j < X(); j++)
255 { 263 {
256 p2[j] = c[j * B + page]; 264 p2[j] = c[j * B + page];
257 } 265 }
258 266
259 - for(unsigned i=0; i < X(); i++){ 267 + for(unsigned long long i=0; i < X(); i++){
260 double r = (double) (wavelength - w[page-1]) / (double) (w[page] - w[page-1]); 268 double r = (double) (wavelength - w[page-1]) / (double) (w[page] - w[page-1]);
261 p[i] = (p2[i] - p1[i]) * r + p1[i]; 269 p[i] = (p2[i] - p1[i]) * r + p1[i];
262 } 270 }
@@ -266,7 +274,7 @@ public: @@ -266,7 +274,7 @@ public:
266 else //if the wavelength is equal to a wavelength in header file 274 else //if the wavelength is equal to a wavelength in header file
267 { 275 {
268 //band_index(p, page); 276 //band_index(p, page);
269 - for(unsigned j = 0; j < X(); j++) 277 + for(unsigned long long j = 0; j < X(); j++)
270 { 278 {
271 p[j] = c[j * B + page]; 279 p[j] = c[j * B + page];
272 } 280 }
@@ -276,29 +284,30 @@ public: @@ -276,29 +284,30 @@ public:
276 } 284 }
277 285
278 /// Retrieve a single pixel and store it in a pre-allocated double array. 286 /// Retrieve a single pixel and store it in a pre-allocated double array.
279 - bool pixeld(double* p, unsigned n){  
280 - unsigned bandnum = X() * Y(); //calculate numbers in one band 287 + bool pixeld(double* p, unsigned long long n){
  288 + unsigned long long bandnum = X() * Y(); //calculate numbers in one band
281 if ( n >= bandnum){ //make sure the pixel number is right 289 if ( n >= bandnum){ //make sure the pixel number is right
282 std::cout<<"ERROR: sample or line out of range"<<std::endl; 290 std::cout<<"ERROR: sample or line out of range"<<std::endl;
283 return false; 291 return false;
284 } 292 }
285 - unsigned B = Z(); 293 + unsigned long long B = Z();
286 294
287 T* temp = (T*) malloc(B * sizeof(T)); //allocate space for the raw pixel data 295 T* temp = (T*) malloc(B * sizeof(T)); //allocate space for the raw pixel data
288 file.seekg(n * B * sizeof(T), std::ios::beg); //point to the certain pixel 296 file.seekg(n * B * sizeof(T), std::ios::beg); //point to the certain pixel
289 file.read((char *)temp, sizeof(T) * B); //read the spectrum from disk to the temp pointer 297 file.read((char *)temp, sizeof(T) * B); //read the spectrum from disk to the temp pointer
290 298
291 - for(unsigned int i = 0; i < B; i++) //for each element of the spectrum 299 + for(unsigned long long i = 0; i < B; i++) //for each element of the spectrum
292 p[i] = (double) temp[i]; //cast each element to a double value 300 p[i] = (double) temp[i]; //cast each element to a double value
  301 + return true;
293 } 302 }
294 303
295 /// Retrieve a single pixel and stores it in pre-allocated memory. 304 /// Retrieve a single pixel and stores it in pre-allocated memory.
296 305
297 /// @param p is a pointer to pre-allocated memory at least sizeof(T) in size. 306 /// @param p is a pointer to pre-allocated memory at least sizeof(T) in size.
298 /// @param n is an integer index to the pixel using linear array indexing. 307 /// @param n is an integer index to the pixel using linear array indexing.
299 - bool pixel(T * p, unsigned n){ 308 + bool pixel(T * p, unsigned long long n){
300 309
301 - unsigned N = X() * Y(); //calculate numbers in one band 310 + unsigned long long N = X() * Y(); //calculate numbers in one band
302 if ( n >= N){ //make sure the pixel number is right 311 if ( n >= N){ //make sure the pixel number is right
303 std::cout<<"ERROR: sample or line out of range"<<std::endl; 312 std::cout<<"ERROR: sample or line out of range"<<std::endl;
304 return false; 313 return false;
@@ -310,7 +319,7 @@ public: @@ -310,7 +319,7 @@ public:
310 } 319 }
311 320
312 //given a Y ,return a ZX slice 321 //given a Y ,return a ZX slice
313 - bool read_plane_y(T * p, unsigned y){ 322 + bool read_plane_y(T * p, unsigned long long y){
314 return binary<T>::read_plane_2(p, y); 323 return binary<T>::read_plane_2(p, y);
315 } 324 }
316 325
@@ -330,7 +339,6 @@ public: @@ -330,7 +339,6 @@ public:
330 std::vector<T> base_vals; //allocate space for the values at each baseline point 339 std::vector<T> base_vals; //allocate space for the values at each baseline point
331 double aw, bw; //surrounding baseline point wavelengths 340 double aw, bw; //surrounding baseline point wavelengths
332 T av, bv; //surrounding baseline point values 341 T av, bv; //surrounding baseline point values
333 - double alpha;  
334 unsigned long long ai, bi; //surrounding baseline point band indices 342 unsigned long long ai, bi; //surrounding baseline point band indices
335 for(unsigned long long n = 0; n < N; n++){ //for each pixel in the image 343 for(unsigned long long n = 0; n < N; n++){ //for each pixel in the image
336 if(mask != NULL && !mask[n]){ //if the pixel isn't masked 344 if(mask != NULL && !mask[n]){ //if the pixel isn't masked
@@ -393,14 +401,14 @@ public: @@ -393,14 +401,14 @@ public:
393 T* s = (T*)malloc(sizeof(T) * B); //allocate memory to store a pixel 401 T* s = (T*)malloc(sizeof(T) * B); //allocate memory to store a pixel
394 T nv; //stores the value of the normalized band 402 T nv; //stores the value of the normalized band
395 for(unsigned long long n = 0; n < N; n++){ //for each pixel in the image 403 for(unsigned long long n = 0; n < N; n++){ //for each pixel in the image
396 - pixel(s, n); //retrieve the spectrum s  
397 - nv = interp_spectrum(s, w); //find the value of the normalization band  
398 if(mask != NULL && !mask[n]) //if the normalization band is below threshold 404 if(mask != NULL && !mask[n]) //if the normalization band is below threshold
399 memset(s, 0, sizeof(T) * B); //set the output to zero 405 memset(s, 0, sizeof(T) * B); //set the output to zero
400 else{ 406 else{
401 - for(unsigned long long b = 0; b < B; b++){ //for each band in the spectrum 407 + pixel(s, n); //retrieve the spectrum s
  408 + nv = interp_spectrum(s, w); //find the value of the normalization band
  409 +
  410 + for(unsigned long long b = 0; b < B; b++) //for each band in the spectrum
402 s[b] /= nv; //divide by the normalization value 411 s[b] /= nv; //divide by the normalization value
403 - }  
404 } 412 }
405 413
406 if(PROGRESS) progress = (double)(n+1) / N * 100; //set the current progress 414 if(PROGRESS) progress = (double)(n+1) / N * 100; //set the current progress
@@ -419,23 +427,23 @@ public: @@ -419,23 +427,23 @@ public:
419 /// @param outname is the name of the output BIL file to be saved to disk. 427 /// @param outname is the name of the output BIL file to be saved to disk.
420 bool bil(std::string outname, bool PROGRESS = false) 428 bool bil(std::string outname, bool PROGRESS = false)
421 { 429 {
422 - unsigned int S = X() * Z() * sizeof(T); //calculate the number of bytes in a ZX slice 430 + unsigned long long S = X() * Z() * sizeof(T); //calculate the number of bytes in a ZX slice
423 431
424 std::ofstream target(outname.c_str(), std::ios::binary); 432 std::ofstream target(outname.c_str(), std::ios::binary);
425 - std::string headername = outname + ".hdr"; 433 + //std::string headername = outname + ".hdr";
426 434
427 T * p; //pointer to the current ZX slice for bip file 435 T * p; //pointer to the current ZX slice for bip file
428 p = (T*)malloc(S); 436 p = (T*)malloc(S);
429 T * q; //pointer to the current XZ slice for bil file 437 T * q; //pointer to the current XZ slice for bil file
430 q = (T*)malloc(S); 438 q = (T*)malloc(S);
431 439
432 - for ( unsigned i = 0; i < Y(); i++) 440 + for ( unsigned long long i = 0; i < Y(); i++)
433 { 441 {
434 read_plane_y(p, i); 442 read_plane_y(p, i);
435 - for ( unsigned k = 0; k < Z(); k++) 443 + for ( unsigned long long k = 0; k < Z(); k++)
436 { 444 {
437 - unsigned ks = k * X();  
438 - for ( unsigned j = 0; j < X(); j++) 445 + unsigned long long ks = k * X();
  446 + for ( unsigned long long j = 0; j < X(); j++)
439 q[ks + j] = p[k + j * Z()]; 447 q[ks + j] = p[k + j * Z()];
440 448
441 if(PROGRESS) progress = (double)(i * Z() + k+1) / (Y() * Z()) * 100; 449 if(PROGRESS) progress = (double)(i * Z() + k+1) / (Y() * Z()) * 100;
@@ -459,12 +467,12 @@ public: @@ -459,12 +467,12 @@ public:
459 /// @param result is a pointer to a pre-allocated array at least X * Y * sizeof(T) in size. 467 /// @param result is a pointer to a pre-allocated array at least X * Y * sizeof(T) in size.
460 bool baseline_band(double lb, double rb, T* lp, T* rp, double wavelength, T* result){ 468 bool baseline_band(double lb, double rb, T* lp, T* rp, double wavelength, T* result){
461 469
462 - unsigned XY = X() * Y(); 470 + unsigned long long XY = X() * Y();
463 band(result, wavelength); //get band 471 band(result, wavelength); //get band
464 472
465 //perform the baseline correction 473 //perform the baseline correction
466 double r = (double) (wavelength - lb) / (double) (rb - lb); 474 double r = (double) (wavelength - lb) / (double) (rb - lb);
467 - for(unsigned i=0; i < XY; i++){ 475 + for(unsigned long long i=0; i < XY; i++){
468 result[i] =(T) (result[i] - (rp[i] - lp[i]) * r - lp[i] ); 476 result[i] =(T) (result[i] - (rp[i] - lp[i]) * r - lp[i] );
469 } 477 }
470 return true; 478 return true;
@@ -480,8 +488,8 @@ public: @@ -480,8 +488,8 @@ public:
480 488
481 T* lp; 489 T* lp;
482 T* rp; 490 T* rp;
483 - unsigned XY = X() * Y();  
484 - unsigned S = XY * sizeof(T); 491 + unsigned long long XY = X() * Y();
  492 + unsigned long long S = XY * sizeof(T);
485 lp = (T*) malloc(S); //memory allocation 493 lp = (T*) malloc(S); //memory allocation
486 rp = (T*) malloc(S); 494 rp = (T*) malloc(S);
487 495
@@ -510,8 +518,8 @@ public: @@ -510,8 +518,8 @@ public:
510 T* cur; //current band 1 518 T* cur; //current band 1
511 T* cur2; //current band 2 519 T* cur2; //current band 2
512 520
513 - unsigned XY = X() * Y();  
514 - unsigned S = XY * sizeof(T); 521 + unsigned long long XY = X() * Y();
  522 + unsigned long long S = XY * sizeof(T);
515 523
516 lp = (T*) malloc(S); //memory allocation 524 lp = (T*) malloc(S); //memory allocation
517 rp = (T*) malloc(S); 525 rp = (T*) malloc(S);
@@ -521,9 +529,9 @@ public: @@ -521,9 +529,9 @@ public:
521 memset(result, (char)0, S); 529 memset(result, (char)0, S);
522 530
523 //find the wavelenght position in the whole band 531 //find the wavelenght position in the whole band
524 - unsigned int n = w.size();  
525 - unsigned int ai = 0; //left bound position  
526 - unsigned int bi = n - 1; //right bound position 532 + unsigned long long n = w.size();
  533 + unsigned long long ai = 0; //left bound position
  534 + unsigned long long bi = n - 1; //right bound position
527 535
528 536
529 537
@@ -552,23 +560,23 @@ public: @@ -552,23 +560,23 @@ public:
552 //calculate the beginning and the ending part 560 //calculate the beginning and the ending part
553 baseline_band(lb, rb, lp, rp, rab, cur2); //ending part 561 baseline_band(lb, rb, lp, rp, rab, cur2); //ending part
554 baseline_band(lb, rb, lp, rp, w[bi], cur); 562 baseline_band(lb, rb, lp, rp, w[bi], cur);
555 - for(unsigned j = 0; j < XY; j++){  
556 - result[j] += (rab - w[bi]) * (cur[j] + cur2[j]) / 2.0; 563 + for(unsigned long long j = 0; j < XY; j++){
  564 + result[j] += (T)((rab - w[bi]) * ((double)cur[j] + (double)cur2[j]) / 2.0);
557 } 565 }
558 baseline_band(lb, rb, lp, rp, lab, cur2); //beginnning part 566 baseline_band(lb, rb, lp, rp, lab, cur2); //beginnning part
559 baseline_band(lb, rb, lp, rp, w[ai], cur); 567 baseline_band(lb, rb, lp, rp, w[ai], cur);
560 - for(unsigned j = 0; j < XY; j++){  
561 - result[j] += (w[ai] - lab) * (cur[j] + cur2[j]) / 2.0; 568 + for(unsigned long long j = 0; j < XY; j++){
  569 + result[j] += (T)((w[ai] - lab) * ((double)cur[j] + (double)cur2[j]) / 2.0);
562 } 570 }
563 571
564 //calculate the area 572 //calculate the area
565 ai++; 573 ai++;
566 - for(unsigned i = ai; i <= bi ;i++) 574 + for(unsigned long long i = ai; i <= bi ;i++)
567 { 575 {
568 baseline_band(lb, rb, lp, rp, w[ai], cur2); 576 baseline_band(lb, rb, lp, rp, w[ai], cur2);
569 - for(unsigned j = 0; j < XY; j++) 577 + for(unsigned long long j = 0; j < XY; j++)
570 { 578 {
571 - result[j] += (w[ai] - w[ai-1]) * (cur[j] + cur2[j]) / 2.0; 579 + result[j] += (T)((w[ai] - w[ai-1]) * ((double)cur[j] + (double)cur2[j]) / 2.0);
572 } 580 }
573 std::swap(cur,cur2); //swap the band pointers 581 std::swap(cur,cur2); //swap the band pointers
574 } 582 }
@@ -598,7 +606,7 @@ public: @@ -598,7 +606,7 @@ public:
598 height(lb1, rb1, pos1, p1); 606 height(lb1, rb1, pos1, p1);
599 height(lb2, rb2, pos2, p2); 607 height(lb2, rb2, pos2, p2);
600 //calculate the ratio in result 608 //calculate the ratio in result
601 - for(unsigned i = 0; i < X() * Y(); i++){ 609 + for(unsigned long long i = 0; i < X() * Y(); i++){
602 if(p1[i] == 0 && p2[i] ==0) 610 if(p1[i] == 0 && p2[i] ==0)
603 result[i] = 1; 611 result[i] = 1;
604 else 612 else
@@ -629,7 +637,7 @@ public: @@ -629,7 +637,7 @@ public:
629 area(lb1, rb1, lab1, rab1, p1); 637 area(lb1, rb1, lab1, rab1, p1);
630 height(lb2, rb2, pos, p2); 638 height(lb2, rb2, pos, p2);
631 //calculate the ratio in result 639 //calculate the ratio in result
632 - for(unsigned i = 0; i < X() * Y(); i++){ 640 + for(unsigned long long i = 0; i < X() * Y(); i++){
633 if(p1[i] == 0 && p2[i] ==0) 641 if(p1[i] == 0 && p2[i] ==0)
634 result[i] = 1; 642 result[i] = 1;
635 else 643 else
@@ -662,7 +670,7 @@ public: @@ -662,7 +670,7 @@ public:
662 area(lb1, rb1, lab1, rab1, p1); 670 area(lb1, rb1, lab1, rab1, p1);
663 area(lb2, rb2, lab2, rab2, p2); 671 area(lb2, rb2, lab2, rab2, p2);
664 //calculate the ratio in result 672 //calculate the ratio in result
665 - for(unsigned i = 0; i < X() * Y(); i++){ 673 + for(unsigned long long i = 0; i < X() * Y(); i++){
666 if(p1[i] == 0 && p2[i] ==0) 674 if(p1[i] == 0 && p2[i] ==0)
667 result[i] = 1; 675 result[i] = 1;
668 else 676 else
@@ -687,8 +695,8 @@ public: @@ -687,8 +695,8 @@ public:
687 T* cur; //current band 1 695 T* cur; //current band 1
688 T* cur2; //current band 2 696 T* cur2; //current band 2
689 697
690 - unsigned XY = X() * Y();  
691 - unsigned S = XY * sizeof(T); 698 + unsigned long long XY = X() * Y();
  699 + unsigned long long S = XY * sizeof(T);
692 700
693 lp = (T*) malloc(S); //memory allocation 701 lp = (T*) malloc(S); //memory allocation
694 rp = (T*) malloc(S); 702 rp = (T*) malloc(S);
@@ -698,9 +706,9 @@ public: @@ -698,9 +706,9 @@ public:
698 memset(result, (char)0, S); 706 memset(result, (char)0, S);
699 707
700 //find the wavelenght position in the whole band 708 //find the wavelenght position in the whole band
701 - unsigned int n = w.size();  
702 - unsigned int ai = 0; //left bound position  
703 - unsigned int bi = n - 1; //right bound position 709 + unsigned long long n = w.size();
  710 + unsigned long long ai = 0; //left bound position
  711 + unsigned long long bi = n - 1; //right bound position
704 712
705 //to make sure the left and the right bound are in the bandwidth 713 //to make sure the left and the right bound are in the bandwidth
706 if (lb < w[0] || rb < w[0] || lb > w[n-1] || rb >w[n-1]){ 714 if (lb < w[0] || rb < w[0] || lb > w[n-1] || rb >w[n-1]){
@@ -727,23 +735,23 @@ public: @@ -727,23 +735,23 @@ public:
727 //calculate the beginning and the ending part 735 //calculate the beginning and the ending part
728 baseline_band(lb, rb, lp, rp, rab, cur2); //ending part 736 baseline_band(lb, rb, lp, rp, rab, cur2); //ending part
729 baseline_band(lb, rb, lp, rp, w[bi], cur); 737 baseline_band(lb, rb, lp, rp, w[bi], cur);
730 - for(unsigned j = 0; j < XY; j++){  
731 - result[j] += (rab - w[bi]) * (rab + w[bi]) * (cur[j] + cur2[j]) / 4.0; 738 + for(unsigned long long j = 0; j < XY; j++){
  739 + result[j] += (T)((rab - w[bi]) * (rab + w[bi]) * ((double)cur[j] + (double)cur2[j]) / 4.0);
732 } 740 }
733 baseline_band(lb, rb, lp, rp, lab, cur2); //beginnning part 741 baseline_band(lb, rb, lp, rp, lab, cur2); //beginnning part
734 baseline_band(lb, rb, lp, rp, w[ai], cur); 742 baseline_band(lb, rb, lp, rp, w[ai], cur);
735 - for(unsigned j = 0; j < XY; j++){  
736 - result[j] += (w[ai] - lab) * (w[ai] + lab) * (cur[j] + cur2[j]) / 4.0; 743 + for(unsigned long long j = 0; j < XY; j++){
  744 + result[j] += (T)((w[ai] - lab) * (w[ai] + lab) * ((double)cur[j] + (double)cur2[j]) / 4.0);
737 } 745 }
738 746
739 //calculate f(x) times x 747 //calculate f(x) times x
740 ai++; 748 ai++;
741 - for(unsigned i = ai; i <= bi ;i++) 749 + for(unsigned long long i = ai; i <= bi ;i++)
742 { 750 {
743 baseline_band(lb, rb, lp, rp, w[ai], cur2); 751 baseline_band(lb, rb, lp, rp, w[ai], cur2);
744 - for(unsigned j = 0; j < XY; j++) 752 + for(unsigned long long j = 0; j < XY; j++)
745 { 753 {
746 - result[j] += (w[ai] - w[ai-1]) * (w[ai] + w[ai-1]) * (cur[j] + cur2[j]) / 4.0; 754 + result[j] += (T)((w[ai] - w[ai-1]) * (w[ai] + w[ai-1]) * ((double)cur[j] + (double)cur2[j]) / 4.0);
747 } 755 }
748 std::swap(cur,cur2); //swap the band pointers 756 std::swap(cur,cur2); //swap the band pointers
749 } 757 }
@@ -770,7 +778,7 @@ public: @@ -770,7 +778,7 @@ public:
770 x_area(lb, rb, lab, rab, p1); 778 x_area(lb, rb, lab, rab, p1);
771 area(lb, rb, lab, rab, p2); 779 area(lb, rb, lab, rab, p2);
772 //calculate the ratio in result 780 //calculate the ratio in result
773 - for(unsigned i = 0; i < X() * Y(); i++){ 781 + for(unsigned long long i = 0; i < X() * Y(); i++){
774 if(p1[i] == 0 && p2[i] ==0) 782 if(p1[i] == 0 && p2[i] ==0)
775 result[i] = 1; 783 result[i] = 1;
776 else 784 else
@@ -794,7 +802,7 @@ public: @@ -794,7 +802,7 @@ public:
794 T* temp = (T*)malloc(X() * Y() * sizeof(T)); //allocate memory for the certain band 802 T* temp = (T*)malloc(X() * Y() * sizeof(T)); //allocate memory for the certain band
795 band(temp, mask_band, PROGRESS); 803 band(temp, mask_band, PROGRESS);
796 804
797 - for (unsigned int i = 0; i < X() * Y();i++) { 805 + for (unsigned long long i = 0; i < X() * Y();i++) {
798 if (temp[i] < threshold) 806 if (temp[i] < threshold)
799 p[i] = 0; 807 p[i] = 0;
800 else 808 else
@@ -814,17 +822,17 @@ public: @@ -814,17 +822,17 @@ public:
814 822
815 std::ofstream target(outfile.c_str(), std::ios::binary); 823 std::ofstream target(outfile.c_str(), std::ios::binary);
816 824
817 - unsigned ZX = Z() * X(); //calculate the number of values in a page (XZ in BIP)  
818 - unsigned L = ZX * sizeof(T); //calculate the number of bytes in a page 825 + unsigned long long ZX = Z() * X(); //calculate the number of values in a page (XZ in BIP)
  826 + unsigned long long L = ZX * sizeof(T); //calculate the number of bytes in a page
819 827
820 T * temp = (T*)malloc(L); //allocate space for that page 828 T * temp = (T*)malloc(L); //allocate space for that page
821 829
822 - for (unsigned i = 0; i < Y(); i++) //for each page (Y in BIP) 830 + for (unsigned long long i = 0; i < Y(); i++) //for each page (Y in BIP)
823 { 831 {
824 read_plane_y(temp, i); //load that page (it's pointed to by temp) 832 read_plane_y(temp, i); //load that page (it's pointed to by temp)
825 - for ( unsigned j = 0; j < X(); j++) //for each X value 833 + for ( unsigned long long j = 0; j < X(); j++) //for each X value
826 { 834 {
827 - for (unsigned k = 0; k < Z(); k++) //for each B value (band) 835 + for (unsigned long long k = 0; k < Z(); k++) //for each B value (band)
828 { 836 {
829 if (p[i * X() + j] == 0) //if the mask value is zero 837 if (p[i * X() + j] == 0) //if the mask value is zero
830 temp[j * Z() + k] = 0; //set the pixel value to zero 838 temp[j * Z() + k] = 0; //set the pixel value to zero
@@ -850,15 +858,15 @@ public: @@ -850,15 +858,15 @@ public:
850 std::ofstream target(outfile.c_str(), std::ios::binary); 858 std::ofstream target(outfile.c_str(), std::ios::binary);
851 859
852 //allocate space for a single spectrum 860 //allocate space for a single spectrum
853 - unsigned long B = Z(); 861 + unsigned long long B = Z();
854 T* spectrum = (T*) malloc(B * sizeof(T)); 862 T* spectrum = (T*) malloc(B * sizeof(T));
855 863
856 //calculate the number of pixels in a band 864 //calculate the number of pixels in a band
857 - unsigned long XY = X() * Y(); 865 + unsigned long long XY = X() * Y();
858 866
859 //for each pixel 867 //for each pixel
860 - unsigned long skip = 0; //number of spectra to skip  
861 - for(unsigned long x = 0; x < XY; x++){ 868 + unsigned long long skip = 0; //number of spectra to skip
  869 + for(unsigned long long x = 0; x < XY; x++){
862 870
863 //if the current pixel isn't masked 871 //if the current pixel isn't masked
864 if( mask[x] == 0){ 872 if( mask[x] == 0){
@@ -879,9 +887,8 @@ public: @@ -879,9 +887,8 @@ public:
879 887
880 //write this pixel out 888 //write this pixel out
881 target.write((char *)spectrum, B * sizeof(T)); 889 target.write((char *)spectrum, B * sizeof(T));
882 -  
883 - if(PROGRESS) progress = (double) (x+1) / XY * 100;  
884 } 890 }
  891 + if(PROGRESS) progress = (double) (x+1) / XY * 100;
885 892
886 } 893 }
887 894
@@ -892,7 +899,7 @@ public: @@ -892,7 +899,7 @@ public:
892 return true; 899 return true;
893 } 900 }
894 901
895 - bool unsift(std::string outfile, unsigned char* mask, unsigned int samples, unsigned int lines){ 902 + bool unsift(std::string outfile, unsigned char* mask, unsigned long long samples, unsigned long long lines){
896 903
897 // open an output stream 904 // open an output stream
898 std::ofstream target(outfile.c_str(), std::ios::binary); 905 std::ofstream target(outfile.c_str(), std::ios::binary);
@@ -901,7 +908,7 @@ public: @@ -901,7 +908,7 @@ public:
901 file.seekg(0, std::ios::beg); 908 file.seekg(0, std::ios::beg);
902 909
903 //allocate space for a single spectrum 910 //allocate space for a single spectrum
904 - unsigned long B = Z(); 911 + unsigned long long B = Z();
905 T* spectrum = (T*) malloc(B * sizeof(T)); 912 T* spectrum = (T*) malloc(B * sizeof(T));
906 913
907 //allocate space for a spectrum of zeros 914 //allocate space for a spectrum of zeros
@@ -909,11 +916,11 @@ public: @@ -909,11 +916,11 @@ public:
909 memset(zeros, 0, B * sizeof(T)); 916 memset(zeros, 0, B * sizeof(T));
910 917
911 //calculate the number of pixels in a band 918 //calculate the number of pixels in a band
912 - unsigned long XY = samples * lines; 919 + unsigned long long XY = samples * lines;
913 920
914 //for each pixel 921 //for each pixel
915 - unsigned long skip = 0; //number of spectra to skip  
916 - for(unsigned long x = 0; x < XY; x++){ 922 + unsigned long long skip = 0; //number of spectra to skip
  923 + for(unsigned long long x = 0; x < XY; x++){
917 924
918 //if the current pixel isn't masked 925 //if the current pixel isn't masked
919 if( mask[x] == 0){ 926 if( mask[x] == 0){
@@ -951,24 +958,23 @@ public: @@ -951,24 +958,23 @@ public:
951 /// @param p is a pointer to pre-allocated memory of size [B * sizeof(T)] that stores the mean spectrum 958 /// @param p is a pointer to pre-allocated memory of size [B * sizeof(T)] that stores the mean spectrum
952 /// @param mask is a pointer to memory of size [X * Y] that stores the mask value at each pixel location 959 /// @param mask is a pointer to memory of size [X * Y] that stores the mask value at each pixel location
953 bool avg_band(double* p, unsigned char* mask = NULL, bool PROGRESS = false){ 960 bool avg_band(double* p, unsigned char* mask = NULL, bool PROGRESS = false){
954 - unsigned long long XY = X() * Y();  
955 - T* temp = (T*)malloc(sizeof(T) * Z());  
956 - //Iinitialize  
957 - for (unsigned j = 0; j < Z(); j++){  
958 - p[j] = 0;  
959 - }  
960 - //calculate vaild number in a band  
961 - unsigned count = nnz(mask);  
962 -  
963 - //calculate average number of a band  
964 - for (unsigned i = 0; i < XY; i++){  
965 - if (mask == NULL || mask[i] != 0){  
966 - pixel(temp, i);  
967 - for (unsigned j = 0; j < Z(); j++){  
968 - p[j] += (double)temp[j] / (double)count; 961 + unsigned long long XY = X() * Y(); //calculate the total number of pixels in the HSI
  962 + T* temp = (T*)malloc(sizeof(T) * Z()); //allocate space for the current spectrum to be read
  963 + memset(p, 0, sizeof(double) * Z()); //initialize the average spectrum to zero (0)
  964 + //for (unsigned j = 0; j < Z(); j++){
  965 + // p[j] = 0;
  966 + //}
  967 +
  968 + unsigned long long count = nnz(mask); //calculate the number of masked pixels
  969 +
  970 + for (unsigned long long i = 0; i < XY; i++){ //for each pixel in the HSI
  971 + if (mask == NULL || mask[i] != 0){ //if the pixel is masked
  972 + pixel(temp, i); //get the spectrum
  973 + for (unsigned long long j = 0; j < Z(); j++){ //for each spectral component
  974 + p[j] += (double)temp[j] / (double)count; //add the weighted value to the average
969 } 975 }
970 } 976 }
971 - if(PROGRESS) progress = (double)(i+1) / XY * 100; 977 + if(PROGRESS) progress = (double)(i+1) / XY * 100; //increment the progress
972 } 978 }
973 979
974 free(temp); 980 free(temp);
@@ -976,6 +982,7 @@ public: @@ -976,6 +982,7 @@ public:
976 } 982 }
977 #ifdef CUDA_FOUND 983 #ifdef CUDA_FOUND
978 /// Calculate the covariance matrix for masked pixels using cuBLAS 984 /// Calculate the covariance matrix for masked pixels using cuBLAS
  985 + /// Note that cuBLAS only supports integer-sized arrays, so there may be issues with large spectra
979 bool co_matrix_cublas(double* co, double* avg, unsigned char *mask, bool PROGRESS = false){ 986 bool co_matrix_cublas(double* co, double* avg, unsigned char *mask, bool PROGRESS = false){
980 987
981 cudaError_t cudaStat; 988 cudaError_t cudaStat;
@@ -994,7 +1001,7 @@ public: @@ -994,7 +1001,7 @@ public:
994 cudaStat = cudaMalloc(&A_dev, B * B * sizeof(double)); //allocate space on the CUDA device for the covariance matrix 1001 cudaStat = cudaMalloc(&A_dev, B * B * sizeof(double)); //allocate space on the CUDA device for the covariance matrix
995 cudaStat = cudaMemset(A_dev, 0, B * B * sizeof(double)); //initialize the covariance matrix to zero (0) 1002 cudaStat = cudaMemset(A_dev, 0, B * B * sizeof(double)); //initialize the covariance matrix to zero (0)
996 cudaStat = cudaMalloc(&avg_dev, B * sizeof(double)); //allocate space on the CUDA device for the average spectrum 1003 cudaStat = cudaMalloc(&avg_dev, B * sizeof(double)); //allocate space on the CUDA device for the average spectrum
997 - stat = cublasSetVector(B, sizeof(double), avg, 1, avg_dev, 1); //copy the average spectrum to the CUDA device 1004 + stat = cublasSetVector((int)B, sizeof(double), avg, 1, avg_dev, 1); //copy the average spectrum to the CUDA device
998 1005
999 double ger_alpha = 1.0/(double)XY; //scale the outer product by the inverse of the number of samples (mean outer product) 1006 double ger_alpha = 1.0/(double)XY; //scale the outer product by the inverse of the number of samples (mean outer product)
1000 double axpy_alpha = -1; //multiplication factor for the average spectrum (in order to perform a subtraction) 1007 double axpy_alpha = -1; //multiplication factor for the average spectrum (in order to perform a subtraction)
@@ -1007,22 +1014,22 @@ public: @@ -1007,22 +1014,22 @@ public:
1007 for (unsigned long long xy = 0; xy < XY; xy++){ //for each pixel 1014 for (unsigned long long xy = 0; xy < XY; xy++){ //for each pixel
1008 if (mask == NULL || mask[xy] != 0){ 1015 if (mask == NULL || mask[xy] != 0){
1009 pixeld(s, xy); //retreive the spectrum at the current xy pixel location 1016 pixeld(s, xy); //retreive the spectrum at the current xy pixel location
1010 - stat = cublasSetVector(B, sizeof(double), s, 1, s_dev, 1); //copy the spectrum from the host to the device  
1011 - stat = cublasDaxpy(handle, B, &axpy_alpha, avg_dev, 1, s_dev, 1); //subtract the average spectrum  
1012 - stat = cublasDsyr(handle, CUBLAS_FILL_MODE_UPPER, B, &ger_alpha, s_dev, 1, A_dev, B); //calculate the covariance matrix (symmetric outer product) 1017 + stat = cublasSetVector((int)B, sizeof(double), s, 1, s_dev, 1); //copy the spectrum from the host to the device
  1018 + stat = cublasDaxpy(handle, (int)B, &axpy_alpha, avg_dev, 1, s_dev, 1); //subtract the average spectrum
  1019 + stat = cublasDsyr(handle, CUBLAS_FILL_MODE_UPPER, (int)B, &ger_alpha, s_dev, 1, A_dev, (int)B); //calculate the covariance matrix (symmetric outer product)
1013 } 1020 }
1014 if(PROGRESS) progress = (double)(xy+1) / XY * 100; //record the current progress 1021 if(PROGRESS) progress = (double)(xy+1) / XY * 100; //record the current progress
1015 1022
1016 } 1023 }
1017 1024
1018 - cublasGetMatrix(B, B, sizeof(double), A_dev, B, co, B); //copy the result from the GPU to the CPU 1025 + cublasGetMatrix((int)B, (int)B, sizeof(double), A_dev, (int)B, co, (int)B); //copy the result from the GPU to the CPU
1019 1026
1020 cudaFree(A_dev); //clean up allocated device memory 1027 cudaFree(A_dev); //clean up allocated device memory
1021 cudaFree(s_dev); 1028 cudaFree(s_dev);
1022 cudaFree(avg_dev); 1029 cudaFree(avg_dev);
1023 1030
1024 - for(unsigned i = 0; i < B; i++){ //copy the upper triangular portion to the lower triangular portion  
1025 - for(unsigned j = i+1; j < B; j++){ 1031 + for(unsigned long long i = 0; i < B; i++){ //copy the upper triangular portion to the lower triangular portion
  1032 + for(unsigned long long j = i+1; j < B; j++){
1026 co[B * i + j] = co[B * j + i]; 1033 co[B * i + j] = co[B * j + i];
1027 } 1034 }
1028 } 1035 }
@@ -1046,14 +1053,13 @@ public: @@ -1046,14 +1053,13 @@ public:
1046 unsigned long long XY = X() * Y(); 1053 unsigned long long XY = X() * Y();
1047 unsigned long long B = Z(); 1054 unsigned long long B = Z();
1048 T* temp = (T*)malloc(sizeof(T) * B); 1055 T* temp = (T*)malloc(sizeof(T) * B);
1049 - //count vaild pixels in a band  
1050 - unsigned long long count = nnz(mask); 1056 +
  1057 + unsigned long long count = nnz(mask); //count the number of masked pixels
1051 1058
1052 //initialize covariance matrix 1059 //initialize covariance matrix
1053 memset(co, 0, B * B * sizeof(double)); 1060 memset(co, 0, B * B * sizeof(double));
1054 1061
1055 //calculate covariance matrix 1062 //calculate covariance matrix
1056 - T i_diff; //stores (temp[i] - avg[i]) to speed math  
1057 double* co_half = (double*) malloc(B * B * sizeof(double)); //allocate space for a higher-precision intermediate matrix 1063 double* co_half = (double*) malloc(B * B * sizeof(double)); //allocate space for a higher-precision intermediate matrix
1058 double* temp_precise = (double*) malloc(B * sizeof(double)); 1064 double* temp_precise = (double*) malloc(B * sizeof(double));
1059 memset(co_half, 0, B * B * sizeof(double)); //initialize the high-precision matrix with zeros 1065 memset(co_half, 0, B * B * sizeof(double)); //initialize the high-precision matrix with zeros
@@ -1083,10 +1089,10 @@ public: @@ -1083,10 +1089,10 @@ public:
1083 return true; 1089 return true;
1084 } 1090 }
1085 1091
1086 - bool project(std::string outfile, double* center, double* basis, unsigned long long M, bool PROGRESS = false){ 1092 + bool project(std::string outfile, double* center, double* basis, unsigned long long M, unsigned char* mask = NULL, bool PROGRESS = false){
1087 1093
1088 std::ofstream target(outfile.c_str(), std::ios::binary); //open the target binary file 1094 std::ofstream target(outfile.c_str(), std::ios::binary); //open the target binary file
1089 - std::string headername = outfile + ".hdr"; //the header file name 1095 + //std::string headername = outfile + ".hdr"; //the header file name
1090 1096
1091 //memory allocation 1097 //memory allocation
1092 unsigned long long XY = X() * Y(); 1098 unsigned long long XY = X() * Y();
@@ -1096,15 +1102,17 @@ public: @@ -1096,15 +1102,17 @@ public:
1096 T* rs = (T*)malloc(sizeof(T) * M); //allocate space for the projected spectrum 1102 T* rs = (T*)malloc(sizeof(T) * M); //allocate space for the projected spectrum
1097 double* bv; //pointer to the current projection vector 1103 double* bv; //pointer to the current projection vector
1098 for(unsigned long long xy = 0; xy < XY; xy++){ //for each spectrum in the image 1104 for(unsigned long long xy = 0; xy < XY; xy++){ //for each spectrum in the image
1099 - pixel(s, xy); //load the spectrum  
1100 - memset(rs, 0, sizeof(T) * M); //initialize the rotated spectrum to zero (0)  
1101 - for(unsigned long long m = 0; m < M; m++){ //for each basis vector  
1102 - bv = &basis[m * B]; //assign 'bv' to the beginning of the basis vector  
1103 - for(unsigned long long b = 0; b < B; b++){ //for each band  
1104 - rs[m] += (s[b] - center[b]) * bv[b]; //center the spectrum and perform the projection 1105 + memset(rs, 0, sizeof(T) * M);
  1106 + if(mask == NULL || mask[xy]){
  1107 + pixel(s, xy); //load the spectrum
  1108 + for(unsigned long long m = 0; m < M; m++){ //for each basis vector
  1109 + bv = &basis[m * B]; //assign 'bv' to the beginning of the basis vector
  1110 + for(unsigned long long b = 0; b < B; b++){ //for each band
  1111 + rs[m] += (T)(((double)s[b] - center[b]) * bv[b]); //center the spectrum and perform the projection
  1112 + }
1105 } 1113 }
1106 } 1114 }
1107 - 1115 +
1108 target.write(reinterpret_cast<const char*>(rs), sizeof(T) * M); //write the projected vector 1116 target.write(reinterpret_cast<const char*>(rs), sizeof(T) * M); //write the projected vector
1109 if(PROGRESS) progress = (double)(xy+1) / XY * 100; 1117 if(PROGRESS) progress = (double)(xy+1) / XY * 100;
1110 } 1118 }
@@ -1135,7 +1143,7 @@ public: @@ -1135,7 +1143,7 @@ public:
1135 for(unsigned long long c = 0; c < C; c++){ //for each basis vector coefficient 1143 for(unsigned long long c = 0; c < C; c++){ //for each basis vector coefficient
1136 bv = &basis[c * B]; //assign 'bv' to the beginning of the basis vector 1144 bv = &basis[c * B]; //assign 'bv' to the beginning of the basis vector
1137 for(unsigned long long b = 0; b < B; b++){ //for each component of the basis vector 1145 for(unsigned long long b = 0; b < B; b++){ //for each component of the basis vector
1138 - s[b] += coeff[c] * bv[b] + center[b]; //calculate the contribution of each element of the basis vector in the final spectrum 1146 + s[b] += (T)((double)coeff[c] * bv[b] + center[b]); //calculate the contribution of each element of the basis vector in the final spectrum
1139 } 1147 }
1140 } 1148 }
1141 1149
@@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
2 #define STIM_BSQ_H 2 #define STIM_BSQ_H
3 3
4 #include "../envi/envi_header.h" 4 #include "../envi/envi_header.h"
5 -#include "../envi/binary.h" 5 +#include "../envi/hsi.h"
6 #include "../envi/bil.h" 6 #include "../envi/bil.h"
7 #include <cstring> 7 #include <cstring>
8 #include <utility> 8 #include <utility>
@@ -22,27 +22,27 @@ namespace stim{ @@ -22,27 +22,27 @@ namespace stim{
22 */ 22 */
23 template <typename T> 23 template <typename T>
24 24
25 -class bsq: public binary<T> { 25 +class bsq: public hsi<T> {
26 26
27 27
28 protected: 28 protected:
29 29
30 - std::vector<double> w; //band wavelengths  
31 - unsigned int offset; 30 + //std::vector<double> w; //band wavelengths
  31 + unsigned long long offset;
32 32
33 using binary<T>::R; 33 using binary<T>::R;
34 34
35 - unsigned long X(){ 35 + /*unsigned long long X(){
36 return R[0]; 36 return R[0];
37 } 37 }
38 - unsigned long Y(){ 38 + unsigned long long Y(){
39 return R[1]; 39 return R[1];
40 } 40 }
41 - unsigned long Z(){ 41 + unsigned long long Z(){
42 return R[2]; 42 return R[2];
43 - }  
44 -  
45 - using binary<T>::nnz; 43 + }*/
  44 + using hsi<T>::w; //use the wavelength array in stim::hsi
  45 + using hsi<T>::nnz;
46 using binary<T>::progress; 46 using binary<T>::progress;
47 47
48 public: 48 public:
@@ -51,8 +51,8 @@ public: @@ -51,8 +51,8 @@ public:
51 using binary<T>::file; 51 using binary<T>::file;
52 using binary<T>::read_line_2; 52 using binary<T>::read_line_2;
53 using binary<T>::read_plane_2; 53 using binary<T>::read_plane_2;
54 - //using binary<T>::getSlice;  
55 54
  55 + bsq(){ hsi<T>::init_bsq(); }
56 56
57 /// Open a data file for reading using the class interface. 57 /// Open a data file for reading using the class interface.
58 58
@@ -62,21 +62,26 @@ public: @@ -62,21 +62,26 @@ public:
62 /// @param B is the number of samples (bands) along dimension 3 62 /// @param B is the number of samples (bands) along dimension 3
63 /// @param header_offset is the number of bytes (if any) in the binary header 63 /// @param header_offset is the number of bytes (if any) in the binary header
64 /// @param wavelengths is an STL vector of size B specifying a numerical label for each band 64 /// @param wavelengths is an STL vector of size B specifying a numerical label for each band
65 - bool open(std::string filename, unsigned int X, unsigned int Y, unsigned int B, unsigned int header_offset, std::vector<double> wavelengths){ 65 + bool open(std::string filename,
  66 + unsigned long long X,
  67 + unsigned long long Y,
  68 + unsigned long long B,
  69 + unsigned long long header_offset,
  70 + std::vector<double> wavelengths){
66 71
67 //copy the wavelengths to the BSQ file structure 72 //copy the wavelengths to the BSQ file structure
68 w = wavelengths; 73 w = wavelengths;
69 //copy the wavelengths to the structure 74 //copy the wavelengths to the structure
70 offset = header_offset; 75 offset = header_offset;
71 76
72 - return open(filename, vec<unsigned int>(X, Y, B), header_offset); 77 + return open(filename, vec<unsigned long long>(X, Y, B), header_offset);
73 } 78 }
74 79
75 /// Retrieve a single band (based on index) and stores it in pre-allocated memory. 80 /// Retrieve a single band (based on index) and stores it in pre-allocated memory.
76 81
77 /// @param p is a pointer to an allocated region of memory at least X * Y * sizeof(T) in size. 82 /// @param p is a pointer to an allocated region of memory at least X * Y * sizeof(T) in size.
78 /// @param page <= B is the integer number of the band to be copied. 83 /// @param page <= B is the integer number of the band to be copied.
79 - bool band_index( T * p, unsigned int page){ 84 + bool band_index( T * p, unsigned long long page){
80 return read_plane_2(p, page); //call the binary read_plane function (don't let it update the progress) 85 return read_plane_2(p, page); //call the binary read_plane function (don't let it update the progress)
81 } 86 }
82 87
@@ -88,10 +93,10 @@ public: @@ -88,10 +93,10 @@ public:
88 if(PROGRESS) progress = 0; 93 if(PROGRESS) progress = 0;
89 //if there are no wavelengths in the BSQ file 94 //if there are no wavelengths in the BSQ file
90 if(w.size() == 0) 95 if(w.size() == 0)
91 - return band_index(p, (unsigned int)wavelength); 96 + return band_index(p, (unsigned long long)wavelength);
92 97
93 - unsigned int XY = X() * Y(); //calculate the number of pixels in a band  
94 - unsigned page = 0; 98 + unsigned long long XY = X() * Y(); //calculate the number of pixels in a band
  99 + unsigned long long page = 0;
95 100
96 101
97 //get the two neighboring bands (above and below 'wavelength') 102 //get the two neighboring bands (above and below 'wavelength')
@@ -122,9 +127,9 @@ public: @@ -122,9 +127,9 @@ public:
122 p2=(T*)malloc( XY * sizeof(T)); 127 p2=(T*)malloc( XY * sizeof(T));
123 band_index(p1, page - 1); 128 band_index(p1, page - 1);
124 band_index(p2, page ); 129 band_index(p2, page );
125 - for(unsigned i=0; i < XY; i++){  
126 - double r = (double) (wavelength - w[page-1]) / (double) (w[page] - w[page-1]);  
127 - p[i] = (p2[i] - p1[i]) * r + p1[i]; 130 + for(unsigned long long i=0; i < XY; i++){
  131 + double r = (wavelength - w[page-1]) / (w[page] - w[page-1]);
  132 + p[i] = (T)(((double)p2[i] - (double)p1[i]) * r + (double)p1[i]);
128 } 133 }
129 free(p1); 134 free(p1);
130 free(p2); 135 free(p2);
@@ -142,7 +147,7 @@ public: @@ -142,7 +147,7 @@ public:
142 /// @param p is a pointer to pre-allocated memory at least B * sizeof(T) in size. 147 /// @param p is a pointer to pre-allocated memory at least B * sizeof(T) in size.
143 /// @param x is the x-coordinate (dimension 1) of the spectrum. 148 /// @param x is the x-coordinate (dimension 1) of the spectrum.
144 /// @param y is the y-coordinate (dimension 2) of the spectrum. 149 /// @param y is the y-coordinate (dimension 2) of the spectrum.
145 - bool spectrum(T * p, unsigned x, unsigned y, bool PROGRESS = false){ 150 + bool spectrum(T * p, unsigned long long x, unsigned long long y, bool PROGRESS = false){
146 return read_line_2(p, x, y, PROGRESS); 151 return read_line_2(p, x, y, PROGRESS);
147 } 152 }
148 153
@@ -150,16 +155,16 @@ public: @@ -150,16 +155,16 @@ public:
150 155
151 /// @param p is a pointer to pre-allocated memory at least sizeof(T) in size. 156 /// @param p is a pointer to pre-allocated memory at least sizeof(T) in size.
152 /// @param n is an integer index to the pixel using linear array indexing. 157 /// @param n is an integer index to the pixel using linear array indexing.
153 - bool pixel(T * p, unsigned n){ 158 + bool pixel(T * p, unsigned long long n){
154 159
155 - unsigned bandnum = X() * Y(); //calculate numbers in one band 160 + unsigned long long bandnum = X() * Y(); //calculate numbers in one band
156 if ( n >= bandnum){ //make sure the pixel number is right 161 if ( n >= bandnum){ //make sure the pixel number is right
157 std::cout<<"ERROR: sample or line out of range"<<std::endl; 162 std::cout<<"ERROR: sample or line out of range"<<std::endl;
158 return false; 163 return false;
159 } 164 }
160 165
161 file.seekg(n * sizeof(T) + binary<T>::header, std::ios::beg); //point to the certain pixel 166 file.seekg(n * sizeof(T) + binary<T>::header, std::ios::beg); //point to the certain pixel
162 - for (unsigned i = 0; i < Z(); i++) 167 + for (unsigned long long i = 0; i < Z(); i++)
163 { 168 {
164 file.read((char *)(p + i), sizeof(T)); 169 file.read((char *)(p + i), sizeof(T));
165 file.seekg((bandnum - 1) * sizeof(T), std::ios::cur); //go to the next band 170 file.seekg((bandnum - 1) * sizeof(T), std::ios::cur); //go to the next band
@@ -174,20 +179,20 @@ public: @@ -174,20 +179,20 @@ public:
174 /// @param wls is the list of baseline points based on band labels. 179 /// @param wls is the list of baseline points based on band labels.
175 bool baseline(std::string outname, std::vector<double> wls, unsigned char* mask = NULL, bool PROGRESS = false ) 180 bool baseline(std::string outname, std::vector<double> wls, unsigned char* mask = NULL, bool PROGRESS = false )
176 { 181 {
177 - unsigned N = wls.size(); //get the number of baseline points 182 + size_t N = wls.size(); //get the number of baseline points
178 183
179 std::ofstream target(outname.c_str(), std::ios::binary); //open the target binary file 184 std::ofstream target(outname.c_str(), std::ios::binary); //open the target binary file
180 std::string headername = outname + ".hdr"; //the header file name 185 std::string headername = outname + ".hdr"; //the header file name
181 186
182 //simplify image resolution 187 //simplify image resolution
183 - unsigned int B = Z(); //calculate the number of bands  
184 - unsigned int XY = X() * Y(); //calculate the number of pixels in a band  
185 - unsigned int S = XY * sizeof(T); //calculate the number of bytes in a band 188 + unsigned long long B = Z(); //calculate the number of bands
  189 + unsigned long long XY = X() * Y(); //calculate the number of pixels in a band
  190 + unsigned long long S = XY * sizeof(T); //calculate the number of bytes in a band
186 191
187 double ai, bi; //stores the two baseline points wavelength surrounding the current band 192 double ai, bi; //stores the two baseline points wavelength surrounding the current band
188 double ci; //stores the current band's wavelength 193 double ci; //stores the current band's wavelength
189 194
190 - unsigned control=0; 195 + unsigned long long control=0;
191 196
192 T * a; //pointers to the high and low band images 197 T * a; //pointers to the high and low band images
193 T * b; 198 T * b;
@@ -222,7 +227,7 @@ public: @@ -222,7 +227,7 @@ public:
222 band(b, bi); 227 band(b, bi);
223 228
224 //correct every band 229 //correct every band
225 - for(unsigned cii = 0; cii < B; cii++){ 230 + for(unsigned long long cii = 0; cii < B; cii++){
226 231
227 //update baseline points, if necessary 232 //update baseline points, if necessary
228 if( w[cii] >= bi && cii != B - 1) { 233 if( w[cii] >= bi && cii != B - 1) {
@@ -255,7 +260,7 @@ public: @@ -255,7 +260,7 @@ public:
255 ci = w[cii]; 260 ci = w[cii];
256 261
257 //perform the baseline correction 262 //perform the baseline correction
258 - for(unsigned i=0; i < XY; i++){ 263 + for(unsigned long long i=0; i < XY; i++){
259 if(mask != NULL && !mask[i]) //if the pixel is excluded by a mask 264 if(mask != NULL && !mask[i]) //if the pixel is excluded by a mask
260 c[i] = 0; //set the value to zero 265 c[i] = 0; //set the value to zero
261 else{ 266 else{
@@ -287,9 +292,9 @@ public: @@ -287,9 +292,9 @@ public:
287 /// @param t is a threshold specified such that a spectrum with a value at w less than t is set to zero. Setting this threshold allows the user to limit division by extremely small numbers. 292 /// @param t is a threshold specified such that a spectrum with a value at w less than t is set to zero. Setting this threshold allows the user to limit division by extremely small numbers.
288 bool normalize(std::string outname, double w, unsigned char* mask = NULL, bool PROGRESS = false) 293 bool normalize(std::string outname, double w, unsigned char* mask = NULL, bool PROGRESS = false)
289 { 294 {
290 - unsigned int B = Z(); //calculate the number of bands  
291 - unsigned int XY = X() * Y(); //calculate the number of pixels in a band  
292 - unsigned int S = XY * sizeof(T); //calculate the number of bytes in a band 295 + unsigned long long B = Z(); //calculate the number of bands
  296 + unsigned long long XY = X() * Y(); //calculate the number of pixels in a band
  297 + unsigned long long S = XY * sizeof(T); //calculate the number of bytes in a band
293 298
294 std::ofstream target(outname.c_str(), std::ios::binary); //open the target binary file 299 std::ofstream target(outname.c_str(), std::ios::binary); //open the target binary file
295 std::string headername = outname + ".hdr"; //the header file name 300 std::string headername = outname + ".hdr"; //the header file name
@@ -302,10 +307,10 @@ public: @@ -302,10 +307,10 @@ public:
302 307
303 band(b, w); //get the certain band into memory 308 band(b, w); //get the certain band into memory
304 309
305 - for(unsigned j = 0; j < B; j++) 310 + for(unsigned long long j = 0; j < B; j++)
306 { 311 {
307 band_index(c, j); //get the current band into memory 312 band_index(c, j); //get the current band into memory
308 - for(unsigned i = 0; i < XY; i++) 313 + for(unsigned long long i = 0; i < XY; i++)
309 { 314 {
310 if(mask != NULL && !mask[i]) 315 if(mask != NULL && !mask[i])
311 c[i] = (T)0.0; 316 c[i] = (T)0.0;
@@ -333,26 +338,24 @@ public: @@ -333,26 +338,24 @@ public:
333 bool bil(std::string outname, bool PROGRESS = false) 338 bool bil(std::string outname, bool PROGRESS = false)
334 { 339 {
335 //simplify image resolution 340 //simplify image resolution
336 - //unsigned int L = X() * Z() * sizeof(T); //calculate the number of bytes of a ZX slice  
337 - unsigned int jump = (Y() - 1) * X() * sizeof(T); 341 + unsigned long long jump = (Y() - 1) * X() * sizeof(T);
338 342
339 std::ofstream target(outname.c_str(), std::ios::binary); 343 std::ofstream target(outname.c_str(), std::ios::binary);
340 std::string headername = outname + ".hdr"; 344 std::string headername = outname + ".hdr";
341 345
342 - unsigned int L = X(); 346 + unsigned long long L = X();
343 T* line = (T*)malloc(sizeof(T) * L); 347 T* line = (T*)malloc(sizeof(T) * L);
344 348
345 - for ( unsigned y = 0; y < Y(); y++) //for each y position 349 + for ( unsigned long long y = 0; y < Y(); y++) //for each y position
346 { 350 {
347 file.seekg(y * X() * sizeof(T), std::ios::beg); //seek to the beginning of the xz slice 351 file.seekg(y * X() * sizeof(T), std::ios::beg); //seek to the beginning of the xz slice
348 - for ( unsigned z = 0; z < Z(); z++ ) //for each band 352 + for ( unsigned long long z = 0; z < Z(); z++ ) //for each band
349 { 353 {
350 file.read((char *)line, sizeof(T) * X()); //read a line 354 file.read((char *)line, sizeof(T) * X()); //read a line
351 target.write((char*)line, sizeof(T) * X()); //write the line to the output file 355 target.write((char*)line, sizeof(T) * X()); //write the line to the output file
352 file.seekg(jump, std::ios::cur); //seek to the next band 356 file.seekg(jump, std::ios::cur); //seek to the next band
353 if(PROGRESS) progress = (double)((y+1) * Z() + z + 1) / (Z() * Y()) * 100; //update the progress counter 357 if(PROGRESS) progress = (double)((y+1) * Z() + z + 1) / (Z() * Y()) * 100; //update the progress counter
354 } 358 }
355 - //std::cout<<progress<<": "<<y<<std::endl;  
356 } 359 }
357 360
358 free(line); 361 free(line);
@@ -371,12 +374,12 @@ public: @@ -371,12 +374,12 @@ public:
371 /// @param result is a pointer to a pre-allocated array at least X * Y * sizeof(T) in size. 374 /// @param result is a pointer to a pre-allocated array at least X * Y * sizeof(T) in size.
372 bool baseline_band(double lb, double rb, T* lp, T* rp, double wavelength, T* result){ 375 bool baseline_band(double lb, double rb, T* lp, T* rp, double wavelength, T* result){
373 376
374 - unsigned XY = X() * Y(); 377 + unsigned long long XY = X() * Y();
375 band(result, wavelength); //get band 378 band(result, wavelength); //get band
376 379
377 //perform the baseline correction 380 //perform the baseline correction
378 double r = (double) (wavelength - lb) / (double) (rb - lb); 381 double r = (double) (wavelength - lb) / (double) (rb - lb);
379 - for(unsigned i=0; i < XY; i++){ 382 + for(unsigned long long i=0; i < XY; i++){
380 result[i] =(T) (result[i] - (rp[i] - lp[i]) * r - lp[i] ); 383 result[i] =(T) (result[i] - (rp[i] - lp[i]) * r - lp[i] );
381 } 384 }
382 return true; 385 return true;
@@ -392,8 +395,8 @@ public: @@ -392,8 +395,8 @@ public:
392 395
393 T* lp; 396 T* lp;
394 T* rp; 397 T* rp;
395 - unsigned XY = X() * Y();  
396 - unsigned S = XY * sizeof(T); 398 + unsigned long long XY = X() * Y();
  399 + unsigned long long S = XY * sizeof(T);
397 lp = (T*) malloc(S); //memory allocation 400 lp = (T*) malloc(S); //memory allocation
398 rp = (T*) malloc(S); 401 rp = (T*) malloc(S);
399 402
@@ -422,8 +425,8 @@ public: @@ -422,8 +425,8 @@ public:
422 T* cur; //current band 1 425 T* cur; //current band 1
423 T* cur2; //current band 2 426 T* cur2; //current band 2
424 427
425 - unsigned XY = X() * Y();  
426 - unsigned S = XY * sizeof(T); 428 + unsigned long long XY = X() * Y();
  429 + unsigned long long S = XY * sizeof(T);
427 430
428 lp = (T*) malloc(S); //memory allocation 431 lp = (T*) malloc(S); //memory allocation
429 rp = (T*) malloc(S); 432 rp = (T*) malloc(S);
@@ -433,9 +436,9 @@ public: @@ -433,9 +436,9 @@ public:
433 memset(result, (char)0, S); 436 memset(result, (char)0, S);
434 437
435 //find the wavelenght position in the whole band 438 //find the wavelenght position in the whole band
436 - unsigned int n = w.size();  
437 - unsigned int ai = 0; //left bound position  
438 - unsigned int bi = n - 1; //right bound position 439 + unsigned long long n = w.size();
  440 + unsigned long long ai = 0; //left bound position
  441 + unsigned long long bi = n - 1; //right bound position
439 442
440 443
441 444
@@ -464,23 +467,23 @@ public: @@ -464,23 +467,23 @@ public:
464 //calculate the beginning and the ending part 467 //calculate the beginning and the ending part
465 baseline_band(lb, rb, lp, rp, rab, cur2); //ending part 468 baseline_band(lb, rb, lp, rp, rab, cur2); //ending part
466 baseline_band(lb, rb, lp, rp, w[bi], cur); 469 baseline_band(lb, rb, lp, rp, w[bi], cur);
467 - for(unsigned j = 0; j < XY; j++){  
468 - result[j] += (rab - w[bi]) * (cur[j] + cur2[j]) / 2.0; 470 + for(unsigned long long j = 0; j < XY; j++){
  471 + result[j] += (T)((rab - w[bi]) * ((double)cur[j] + (double)cur2[j]) / 2.0);
469 } 472 }
470 baseline_band(lb, rb, lp, rp, lab, cur2); //beginnning part 473 baseline_band(lb, rb, lp, rp, lab, cur2); //beginnning part
471 baseline_band(lb, rb, lp, rp, w[ai], cur); 474 baseline_band(lb, rb, lp, rp, w[ai], cur);
472 - for(unsigned j = 0; j < XY; j++){  
473 - result[j] += (w[ai] - lab) * (cur[j] + cur2[j]) / 2.0; 475 + for(unsigned long long j = 0; j < XY; j++){
  476 + result[j] += (T)((w[ai] - lab) * ((double)cur[j] + (double)cur2[j]) / 2.0);
474 } 477 }
475 478
476 //calculate the area 479 //calculate the area
477 ai++; 480 ai++;
478 - for(unsigned i = ai; i <= bi ;i++) 481 + for(unsigned long long i = ai; i <= bi ;i++)
479 { 482 {
480 baseline_band(lb, rb, lp, rp, w[ai], cur2); 483 baseline_band(lb, rb, lp, rp, w[ai], cur2);
481 - for(unsigned j = 0; j < XY; j++) 484 + for(unsigned long long j = 0; j < XY; j++)
482 { 485 {
483 - result[j] += (w[ai] - w[ai-1]) * (cur[j] + cur2[j]) / 2.0; 486 + result[j] += (T)((w[ai] - w[ai-1]) * ((double)cur[j] + (double)cur2[j]) / 2.0);
484 } 487 }
485 std::swap(cur,cur2); //swap the band pointers 488 std::swap(cur,cur2); //swap the band pointers
486 } 489 }
@@ -510,7 +513,7 @@ public: @@ -510,7 +513,7 @@ public:
510 height(lb1, rb1, pos1, p1); 513 height(lb1, rb1, pos1, p1);
511 height(lb2, rb2, pos2, p2); 514 height(lb2, rb2, pos2, p2);
512 //calculate the ratio in result 515 //calculate the ratio in result
513 - for(unsigned i = 0; i < X() * Y(); i++){ 516 + for(unsigned long long i = 0; i < X() * Y(); i++){
514 if(p1[i] == 0 && p2[i] ==0) 517 if(p1[i] == 0 && p2[i] ==0)
515 result[i] = 1; 518 result[i] = 1;
516 else 519 else
@@ -541,7 +544,7 @@ public: @@ -541,7 +544,7 @@ public:
541 area(lb1, rb1, lab1, rab1, p1); 544 area(lb1, rb1, lab1, rab1, p1);
542 height(lb2, rb2, pos, p2); 545 height(lb2, rb2, pos, p2);
543 //calculate the ratio in result 546 //calculate the ratio in result
544 - for(unsigned i = 0; i < X() * Y(); i++){ 547 + for(unsigned long long i = 0; i < X() * Y(); i++){
545 if(p1[i] == 0 && p2[i] ==0) 548 if(p1[i] == 0 && p2[i] ==0)
546 result[i] = 1; 549 result[i] = 1;
547 else 550 else
@@ -574,7 +577,7 @@ public: @@ -574,7 +577,7 @@ public:
574 area(lb1, rb1, lab1, rab1, p1); 577 area(lb1, rb1, lab1, rab1, p1);
575 area(lb2, rb2, lab2, rab2, p2); 578 area(lb2, rb2, lab2, rab2, p2);
576 //calculate the ratio in result 579 //calculate the ratio in result
577 - for(unsigned i = 0; i < X() * Y(); i++){ 580 + for(unsigned long long i = 0; i < X() * Y(); i++){
578 if(p1[i] == 0 && p2[i] ==0) 581 if(p1[i] == 0 && p2[i] ==0)
579 result[i] = 1; 582 result[i] = 1;
580 else 583 else
@@ -599,8 +602,8 @@ public: @@ -599,8 +602,8 @@ public:
599 T* cur; //current band 1 602 T* cur; //current band 1
600 T* cur2; //current band 2 603 T* cur2; //current band 2
601 604
602 - unsigned XY = X() * Y();  
603 - unsigned S = XY * sizeof(T); 605 + unsigned long long XY = X() * Y();
  606 + unsigned long long S = XY * sizeof(T);
604 607
605 lp = (T*) malloc(S); //memory allocation 608 lp = (T*) malloc(S); //memory allocation
606 rp = (T*) malloc(S); 609 rp = (T*) malloc(S);
@@ -610,9 +613,9 @@ public: @@ -610,9 +613,9 @@ public:
610 memset(result, (char)0, S); 613 memset(result, (char)0, S);
611 614
612 //find the wavelenght position in the whole band 615 //find the wavelenght position in the whole band
613 - unsigned int n = w.size();  
614 - unsigned int ai = 0; //left bound position  
615 - unsigned int bi = n - 1; //right bound position 616 + unsigned long long n = w.size();
  617 + unsigned long long ai = 0; //left bound position
  618 + unsigned long long bi = n - 1; //right bound position
616 619
617 //to make sure the left and the right bound are in the bandwidth 620 //to make sure the left and the right bound are in the bandwidth
618 if (lb < w[0] || rb < w[0] || lb > w[n-1] || rb >w[n-1]){ 621 if (lb < w[0] || rb < w[0] || lb > w[n-1] || rb >w[n-1]){
@@ -639,23 +642,23 @@ public: @@ -639,23 +642,23 @@ public:
639 //calculate the beginning and the ending part 642 //calculate the beginning and the ending part
640 baseline_band(lb, rb, lp, rp, rab, cur2); //ending part 643 baseline_band(lb, rb, lp, rp, rab, cur2); //ending part
641 baseline_band(lb, rb, lp, rp, w[bi], cur); 644 baseline_band(lb, rb, lp, rp, w[bi], cur);
642 - for(unsigned j = 0; j < XY; j++){  
643 - result[j] += (rab - w[bi]) * (rab + w[bi]) * (cur[j] + cur2[j]) / 4.0; 645 + for(unsigned long long j = 0; j < XY; j++){
  646 + result[j] += (T)((rab - w[bi]) * (rab + w[bi]) * ((double)cur[j] + (double)cur2[j]) / 4.0);
644 } 647 }
645 baseline_band(lb, rb, lp, rp, lab, cur2); //beginnning part 648 baseline_band(lb, rb, lp, rp, lab, cur2); //beginnning part
646 baseline_band(lb, rb, lp, rp, w[ai], cur); 649 baseline_band(lb, rb, lp, rp, w[ai], cur);
647 - for(unsigned j = 0; j < XY; j++){  
648 - result[j] += (w[ai] - lab) * (w[ai] + lab) * (cur[j] + cur2[j]) / 4.0; 650 + for(unsigned long long j = 0; j < XY; j++){
  651 + result[j] += (T)((w[ai] - lab) * (w[ai] + lab) * ((double)cur[j] + (double)cur2[j]) / 4.0);
649 } 652 }
650 653
651 //calculate f(x) times x 654 //calculate f(x) times x
652 ai++; 655 ai++;
653 - for(unsigned i = ai; i <= bi ;i++) 656 + for(unsigned long long i = ai; i <= bi ;i++)
654 { 657 {
655 baseline_band(lb, rb, lp, rp, w[ai], cur2); 658 baseline_band(lb, rb, lp, rp, w[ai], cur2);
656 - for(unsigned j = 0; j < XY; j++) 659 + for(unsigned long long j = 0; j < XY; j++)
657 { 660 {
658 - result[j] += (w[ai] - w[ai-1]) * (w[ai] + w[ai-1]) * (cur[j] + cur2[j]) / 4.0; 661 + result[j] += (T)((w[ai] - w[ai-1]) * (w[ai] + w[ai-1]) * ((double)cur[j] + (double)cur2[j]) / 4.0);
659 } 662 }
660 std::swap(cur,cur2); //swap the band pointers 663 std::swap(cur,cur2); //swap the band pointers
661 } 664 }
@@ -682,7 +685,7 @@ public: @@ -682,7 +685,7 @@ public:
682 x_area(lb, rb, lab, rab, p1); 685 x_area(lb, rb, lab, rab, p1);
683 area(lb, rb, lab, rab, p2); 686 area(lb, rb, lab, rab, p2);
684 //calculate the ratio in result 687 //calculate the ratio in result
685 - for(unsigned i = 0; i < X() * Y(); i++){ 688 + for(unsigned long long i = 0; i < X() * Y(); i++){
686 if(p1[i] == 0 && p2[i] ==0) 689 if(p1[i] == 0 && p2[i] ==0)
687 result[i] = 1; 690 result[i] = 1;
688 else 691 else
@@ -706,13 +709,13 @@ public: @@ -706,13 +709,13 @@ public:
706 T* temp = (T*)malloc(X() * Y() * sizeof(T)); //allocate memory for the certain band 709 T* temp = (T*)malloc(X() * Y() * sizeof(T)); //allocate memory for the certain band
707 band(temp, mask_band); 710 band(temp, mask_band);
708 711
709 - for (unsigned int i = 0; i < X() * Y(); i++) { 712 + for (unsigned long long i = 0; i < X() * Y(); i++) {
710 if (temp[i] < threshold) 713 if (temp[i] < threshold)
711 p[i] = 0; 714 p[i] = 0;
712 else 715 else
713 p[i] = 255; 716 p[i] = 255;
714 717
715 - if(PROGRESS) progress = (double) (i+1) / (X() * Y()); 718 + if(PROGRESS) progress = (double) (i+1) / (X() * Y()) * 100;
716 } 719 }
717 720
718 free(temp); 721 free(temp);
@@ -728,15 +731,15 @@ public: @@ -728,15 +731,15 @@ public:
728 731
729 std::ofstream target(outfile.c_str(), std::ios::binary); 732 std::ofstream target(outfile.c_str(), std::ios::binary);
730 733
731 - unsigned XY = X() * Y(); //calculate number of a band  
732 - unsigned L = XY * sizeof(T); 734 + unsigned long long XY = X() * Y(); //calculate number of a band
  735 + unsigned long long L = XY * sizeof(T);
733 736
734 T * temp = (T*)malloc(L); 737 T * temp = (T*)malloc(L);
735 738
736 - for (unsigned i = 0; i < Z(); i++) //for each spectral bin 739 + for (unsigned long long i = 0; i < Z(); i++) //for each spectral bin
737 { 740 {
738 band_index(temp, i); //get the specified band (by index) 741 band_index(temp, i); //get the specified band (by index)
739 - for ( unsigned j = 0; j < XY; j++) // for each pixel 742 + for ( unsigned long long j = 0; j < XY; j++) // for each pixel
740 { 743 {
741 if(p[j] == 0){ //if the mask is 0 at that pixel 744 if(p[j] == 0){ //if the mask is 0 at that pixel
742 temp[j] = 0; //set temp to zero 745 temp[j] = 0; //set temp to zero
@@ -787,56 +790,24 @@ public: @@ -787,56 +790,24 @@ public:
787 790
788 return true; 791 return true;
789 } 792 }
790 -  
791 - /// Saves only those spectra corresponding to mask value != 0 to pre-allocated memory  
792 - /// @param matrix is the destination for the sifted pixels  
793 - /// @param p is the mask file used for sifting  
794 - /*bool sift(T* matrix, unsigned char* p){  
795 -  
796 - // open a band (XY plane)  
797 - unsigned long XY = X() * Y(); //Number of XY pixels  
798 - unsigned long L = XY * sizeof(T); //size of XY pixels  
799 -  
800 - //count the number of masked pixels  
801 - unsigned long P = 0; //allocate space for the number of pixels  
802 - for(unsigned long xy = 0; xy < XY; xy++){ //count the number of pixels  
803 - if(p[xy] != 0) P++;  
804 - }  
805 -  
806 - T* bandvals = (T*) malloc(sizeof(T) * P); //allocate a temporary array to store the pixels for a single band  
807 - memset(matrix, 0, sizeof(T) * P * Z());  
808 - for (unsigned long z = 0; z < Z(); z++){ //for each band  
809 -  
810 - if(!sift_band(bandvals, z, p)){  
811 - std::cout<<"ERROR sifting band index "<<z<<std::endl;  
812 - exit(1);  
813 - }  
814 -  
815 - for(unsigned long p = 0; p < P; p++) //for each pixel in the array representing a single band  
816 - matrix[p * Z() + z] = bandvals[p]; //copy it to the appropriate location in the matrix  
817 - }  
818 -  
819 - free(bandvals); //clean up temporary memory  
820 - return true;  
821 - }*/  
822 - 793 +
823 /// Saves to disk only those spectra corresponding to mask values != 0 794 /// Saves to disk only those spectra corresponding to mask values != 0
824 /// @param outfile is the name of the sifted ENVI file to be written to disk 795 /// @param outfile is the name of the sifted ENVI file to be written to disk
825 /// @param unsigned char* p is the mask file used for sifting 796 /// @param unsigned char* p is the mask file used for sifting
826 bool sift(std::string outfile, unsigned char* p, bool PROGRESS = false){ 797 bool sift(std::string outfile, unsigned char* p, bool PROGRESS = false){
827 std::ofstream target(outfile.c_str(), std::ios::binary); 798 std::ofstream target(outfile.c_str(), std::ios::binary);
828 // open a band (XY plane) 799 // open a band (XY plane)
829 - unsigned long XY = X() * Y(); //Number of XY pixels  
830 - unsigned long L = XY * sizeof(T); //size of XY pixels 800 + unsigned long long XY = X() * Y(); //Number of XY pixels
  801 + unsigned long long L = XY * sizeof(T); //size of XY pixels
831 unsigned long long B = Z(); 802 unsigned long long B = Z();
832 803
833 T * temp = (T*)malloc(L); //allocate memory for a band 804 T * temp = (T*)malloc(L); //allocate memory for a band
834 T * temp_vox = (T*)malloc(sizeof(T)); //allocate memory for one voxel 805 T * temp_vox = (T*)malloc(sizeof(T)); //allocate memory for one voxel
835 806
836 - for (unsigned long i = 0; i < B; i++) //for each spectral bin 807 + for (unsigned long long i = 0; i < B; i++) //for each spectral bin
837 { 808 {
838 band_index(temp, i); //get the specified band (XY sheet by index) 809 band_index(temp, i); //get the specified band (XY sheet by index)
839 - for (unsigned long j = 0; j < XY; j++) // for each pixel 810 + for (unsigned long long j = 0; j < XY; j++) // for each pixel
840 { 811 {
841 if (p[j] != 0){ //if the mask is != 0 at that pixel 812 if (p[j] != 0){ //if the mask is != 0 at that pixel
842 temp_vox[0] = temp[j]; 813 temp_vox[0] = temp[j];
@@ -844,9 +815,7 @@ public: @@ -844,9 +815,7 @@ public:
844 } 815 }
845 else{ 816 else{
846 continue; 817 continue;
847 - }  
848 -  
849 - 818 + }
850 } 819 }
851 if(PROGRESS) progress = (double)(i+1)/ B * 100; 820 if(PROGRESS) progress = (double)(i+1)/ B * 100;
852 } 821 }
@@ -859,7 +828,7 @@ public: @@ -859,7 +828,7 @@ public:
859 } 828 }
860 829
861 /// Generates a spectral image from a matrix of spectral values in lexicographic order and a mask 830 /// Generates a spectral image from a matrix of spectral values in lexicographic order and a mask
862 - bool unsift(std::string outfile, unsigned char* p, unsigned int samples, unsigned int lines){ 831 + bool unsift(std::string outfile, unsigned char* p, unsigned long long samples, unsigned long long lines){
863 832
864 //create a binary output stream 833 //create a binary output stream
865 std::ofstream target(outfile.c_str(), std::ios::binary); 834 std::ofstream target(outfile.c_str(), std::ios::binary);
@@ -873,9 +842,9 @@ public: @@ -873,9 +842,9 @@ public:
873 std::cout<<"started sifting"<<std::endl; 842 std::cout<<"started sifting"<<std::endl;
874 843
875 //get the number of pixels and bands in the input image 844 //get the number of pixels and bands in the input image
876 - unsigned long P = X(); //Number of pixels  
877 - unsigned long B = Z(); //number of bands  
878 - unsigned long XY = samples * lines; //total number of pixels in an unsifted image 845 + unsigned long long P = X(); //Number of pixels
  846 + unsigned long long B = Z(); //number of bands
  847 + unsigned long long XY = samples * lines; //total number of pixels in an unsifted image
879 848
880 // allocate memory for a sifted band 849 // allocate memory for a sifted band
881 T * sifted = (T*)malloc(P * sizeof(T)); //allocate memory for a band 850 T * sifted = (T*)malloc(P * sizeof(T)); //allocate memory for a band
@@ -884,16 +853,16 @@ public: @@ -884,16 +853,16 @@ public:
884 T* unsifted = (T*) malloc(XY * sizeof(T)); 853 T* unsifted = (T*) malloc(XY * sizeof(T));
885 854
886 //for each band 855 //for each band
887 - for(unsigned long b = 0; b < B; b++){ 856 + for(unsigned long long b = 0; b < B; b++){
888 857
889 //set the unsifted index value to zero 858 //set the unsifted index value to zero
890 - unsigned long i = 0; 859 + unsigned long long i = 0;
891 860
892 //retrieve the sifted band (masked pixels only) 861 //retrieve the sifted band (masked pixels only)
893 band_index(sifted, b); 862 band_index(sifted, b);
894 863
895 //for each pixel in the final image (treat it as a 1D image) 864 //for each pixel in the final image (treat it as a 1D image)
896 - for(unsigned long xi = 0; xi < XY; xi++){ 865 + for(unsigned long long xi = 0; xi < XY; xi++){
897 if( p[xi] == 0 ) 866 if( p[xi] == 0 )
898 unsifted[xi] = 0; 867 unsifted[xi] = 0;
899 else{ 868 else{
@@ -923,13 +892,13 @@ public: @@ -923,13 +892,13 @@ public:
923 T* temp = (T*)malloc(sizeof(T) * XY); 892 T* temp = (T*)malloc(sizeof(T) * XY);
924 //initialize p 893 //initialize p
925 band_index(p, 0); 894 band_index(p, 0);
926 - for (unsigned j = 0; j < XY; j++){ 895 + for (unsigned long long j = 0; j < XY; j++){
927 p[j] /= (T)Z(); 896 p[j] /= (T)Z();
928 } 897 }
929 //get every band and add them all 898 //get every band and add them all
930 - for (unsigned i = 1; i < Z(); i++){ 899 + for (unsigned long long i = 1; i < Z(); i++){
931 band_index(temp, i); 900 band_index(temp, i);
932 - for (unsigned j = 0; j < XY; j++){ 901 + for (unsigned long long j = 0; j < XY; j++){
933 p[j] += temp[j]/(T)Z(); 902 p[j] += temp[j]/(T)Z();
934 } 903 }
935 } 904 }
@@ -966,54 +935,7 @@ public: @@ -966,54 +935,7 @@ public:
966 free(temp); 935 free(temp);
967 return true; 936 return true;
968 } 937 }
969 -  
970 - /// Calculate the covariance matrix for all masked pixels in the image.  
971 -  
972 - /// @param co is a pointer to pre-allocated memory of size [B * B] that stores the resulting covariance matrix  
973 - /// @param avg is a pointer to memory of size B that stores the average spectrum  
974 - /// @param mask is a pointer to memory of size [X * Y] that stores the mask value at each pixel location  
975 - /*bool co_matrix(double* co, double* avg, unsigned char *mask){  
976 - progress = 0; //initialize thread data for timers and progress bars  
977 - //memory allocation  
978 - unsigned long long xy = X() * Y();  
979 - unsigned long long B = Z();  
980 - T* bandi = (T*)malloc(sizeof(T) * xy);  
981 - T* bandj = (T*)malloc(sizeof(T) * xy);  
982 -  
983 - //count vaild pixels in a band  
984 - unsigned long long count = 0;  
985 - for (unsigned long long j = 0; j < xy; j++){  
986 - if (mask == NULL || mask[j] != 0){  
987 - count++;  
988 - }  
989 - }  
990 - //calculate correlation coefficient matrix  
991 - for (unsigned long long i = 0; i < B; i++)  
992 - {  
993 - band_index(bandi, i);  
994 - for (unsigned long long j = i; j < B; j++){  
995 - band_index(bandj, j);  
996 - double numerator = 0; //to calculate element in correlation coefficient matrix, numerator part  
997 - //calculate the R(i,j) in correlation coeffient matrix  
998 - for (unsigned long long k = 0; k < xy; k++){  
999 - if (mask == NULL || mask[k] != 0){  
1000 - numerator += ((double)bandi[k] - (double)avg[i]) * ((double)bandj[k] - (double)avg[j]) / (double)count;  
1001 - }  
1002 - }  
1003 - co[i*B + j] = numerator;  
1004 - co[j*B + i] = numerator; //because correlated matrix is a symmetric matrix  
1005 - }  
1006 - progress = (double)i / B * 100;  
1007 - }  
1008 - free(bandi);  
1009 - free(bandj);  
1010 -  
1011 - progress = 100; //processing complete  
1012 -  
1013 - return true;  
1014 - }*/  
1015 -  
1016 - 938 +
1017 /// Crop a region of the image and save it to a new file. 939 /// Crop a region of the image and save it to a new file.
1018 940
1019 /// @param outfile is the file name for the new cropped image 941 /// @param outfile is the file name for the new cropped image
@@ -1055,7 +977,7 @@ public: @@ -1055,7 +977,7 @@ public:
1055 //for each band 977 //for each band
1056 for (unsigned long long z = b0; z < b1; z++) 978 for (unsigned long long z = b0; z < b1; z++)
1057 { 979 {
1058 - for (unsigned y = 0; y < lines; y++) 980 + for (unsigned long long y = 0; y < lines; y++)
1059 { 981 {
1060 file.read((char *)(temp + y * samples), sizeof(T) * samples); 982 file.read((char *)(temp + y * samples), sizeof(T) * samples);
1061 file.seekg(jumpl, std::ios::cur); //go to the next band 983 file.seekg(jumpl, std::ios::cur); //go to the next band
@@ -69,7 +69,7 @@ public: @@ -69,7 +69,7 @@ public:
69 } 69 }
70 70
71 /// Returns the progress of the current processing operation as a percentage 71 /// Returns the progress of the current processing operation as a percentage
72 - unsigned int progress(){ 72 + double progress(){
73 73
74 if(header.interleave == envi_header::BSQ){ //if the infile is bsq file 74 if(header.interleave == envi_header::BSQ){ //if the infile is bsq file
75 if(header.data_type ==envi_header::float32) 75 if(header.data_type ==envi_header::float32)
@@ -105,31 +105,29 @@ public: @@ -105,31 +105,29 @@ public:
105 } 105 }
106 106
107 /// Allocate memory for a new ENVI file based on the current interleave format (BIP, BIL, BSQ) and data type. 107 /// Allocate memory for a new ENVI file based on the current interleave format (BIP, BIL, BSQ) and data type.
108 - bool allocate(){ 108 + void allocate(){
109 109
110 file = NULL; //set file to a NULL pointer 110 file = NULL; //set file to a NULL pointer
111 111
112 if(header.interleave == envi_header::BSQ){ 112 if(header.interleave == envi_header::BSQ){
113 if(header.data_type ==envi_header::float32) 113 if(header.data_type ==envi_header::float32)
114 - return(file = new bsq<float>()); 114 + file = new bsq<float>();
115 else if(header.data_type == envi_header::float64) 115 else if(header.data_type == envi_header::float64)
116 - return(file = new bsq<double>()); 116 + file = new bsq<double>();
117 } 117 }
118 else if(header.interleave == envi_header::BIP){ 118 else if(header.interleave == envi_header::BIP){
119 if(header.data_type ==envi_header::float32) 119 if(header.data_type ==envi_header::float32)
120 - return(file = new bip<float>()); 120 + file = new bip<float>();
121 else if(header.data_type == envi_header::float64) 121 else if(header.data_type == envi_header::float64)
122 - return(file = new bip<double>()); 122 + file = new bip<double>();
123 } 123 }
124 else if(header.interleave == envi_header::BIL){ 124 else if(header.interleave == envi_header::BIL){
125 if(header.data_type ==envi_header::float32) 125 if(header.data_type ==envi_header::float32)
126 - return(file = new bil<float>()); 126 + file = new bil<float>();
127 else if(header.data_type == envi_header::float64) 127 else if(header.data_type == envi_header::float64)
128 - return(file = new bil<double>()); 128 + file = new bil<double>();
129 } 129 }
130 130
131 - exit(1); //if the function hasn't already returned, we don't handle this state  
132 -  
133 } 131 }
134 132
135 /// Open a previously opened ENVI file 133 /// Open a previously opened ENVI file
@@ -179,11 +177,13 @@ public: @@ -179,11 +177,13 @@ public:
179 /// @param filename is the name of the ENVI binary file 177 /// @param filename is the name of the ENVI binary file
180 /// @param header is an ENVI header structure 178 /// @param header is an ENVI header structure
181 bool open(std::string filename, stim::envi_header h){ 179 bool open(std::string filename, stim::envi_header h){
182 - allocate(); 180 +
183 181
184 header = h; //store the header 182 header = h; //store the header
185 fname = filename; //save the filename 183 fname = filename; //save the filename
186 184
  185 + allocate();
  186 +
187 return open(); //open the ENVI file; 187 return open(); //open the ENVI file;
188 188
189 189
@@ -294,7 +294,7 @@ public: @@ -294,7 +294,7 @@ public:
294 } 294 }
295 } 295 }
296 296
297 - void project(std::string outfile, double* center, double* basis, unsigned long long M, bool PROGRESS = false){ 297 + void project(std::string outfile, double* center, double* basis, unsigned long long M, unsigned char* mask, bool PROGRESS = false){
298 if(header.interleave == envi_header::BSQ){ //if the infile is bsq file 298 if(header.interleave == envi_header::BSQ){ //if the infile is bsq file
299 std::cout<<"ERROR: BSQ projection not supported"<<std::endl; 299 std::cout<<"ERROR: BSQ projection not supported"<<std::endl;
300 exit(1); 300 exit(1);
@@ -307,9 +307,9 @@ public: @@ -307,9 +307,9 @@ public:
307 307
308 else if(header.interleave == envi_header::BIP){ //if the infile is bip file 308 else if(header.interleave == envi_header::BIP){ //if the infile is bip file
309 if(header.data_type ==envi_header::float32) 309 if(header.data_type ==envi_header::float32)
310 - ((bip<float>*)file)->project(outfile, center, basis, M, PROGRESS); 310 + ((bip<float>*)file)->project(outfile, center, basis, M, mask, PROGRESS);
311 else if(header.data_type == envi_header::float64) 311 else if(header.data_type == envi_header::float64)
312 - ((bip<double>*)file)->project(outfile, center, basis, M, PROGRESS); 312 + ((bip<double>*)file)->project(outfile, center, basis, M, mask, PROGRESS);
313 else{ 313 else{
314 std::cout<<"ERROR: unidentified data type"<<std::endl; 314 std::cout<<"ERROR: unidentified data type"<<std::endl;
315 exit(1); 315 exit(1);
@@ -318,6 +318,8 @@ public: @@ -318,6 +318,8 @@ public:
318 318
319 stim::envi_header out_hdr = header; 319 stim::envi_header out_hdr = header;
320 out_hdr.bands = M; //set the number of bands in the output header 320 out_hdr.bands = M; //set the number of bands in the output header
  321 + out_hdr.wavelength.clear();
  322 + out_hdr.band_names.clear();
321 out_hdr.save(outfile + ".hdr"); //save the output header 323 out_hdr.save(outfile + ".hdr"); //save the output header
322 } 324 }
323 325
@@ -577,9 +579,9 @@ public: @@ -577,9 +579,9 @@ public:
577 { 579 {
578 580
579 //calculate the number of non-zero values in the mask 581 //calculate the number of non-zero values in the mask
580 - unsigned int nnz = 0;  
581 - unsigned int npixels = header.lines * header.samples;  
582 - for(unsigned int i = 0; i < npixels; i++) 582 + unsigned long long nnz = 0;
  583 + unsigned long long npixels = header.lines * header.samples;
  584 + for(unsigned long long i = 0; i < npixels; i++)
583 if( p[i] > 0 ) nnz++; 585 if( p[i] > 0 ) nnz++;
584 586
585 //create a new header 587 //create a new header
@@ -625,12 +627,10 @@ public: @@ -625,12 +627,10 @@ public:
625 std::cout << "ERROR: unidentified file type" << std::endl; 627 std::cout << "ERROR: unidentified file type" << std::endl;
626 exit(1); 628 exit(1);
627 } 629 }
628 -  
629 -  
630 return false; 630 return false;
631 } 631 }
632 632
633 - bool unsift(std::string outfile, unsigned char* mask, unsigned int samples, unsigned int lines){ 633 + bool unsift(std::string outfile, unsigned char* mask, unsigned long long samples, unsigned long long lines){
634 634
635 //create a new header 635 //create a new header
636 envi_header new_header = header; 636 envi_header new_header = header;
@@ -976,7 +976,7 @@ public: @@ -976,7 +976,7 @@ public:
976 /// @param ptr is a pointer to pre-allocated memory of size B*sizeof(T) 976 /// @param ptr is a pointer to pre-allocated memory of size B*sizeof(T)
977 /// @param x is the x-coordinate of the spectrum 977 /// @param x is the x-coordinate of the spectrum
978 /// @param y is the y-coordinate of the spectrum 978 /// @param y is the y-coordinate of the spectrum
979 - bool spectrum(void* ptr, unsigned int x, unsigned int y, bool PROGRESS = false){ 979 + bool spectrum(void* ptr, unsigned long long x, unsigned long long y, bool PROGRESS = false){
980 980
981 if(header.interleave == envi_header::BSQ){ //if the infile is bsq file 981 if(header.interleave == envi_header::BSQ){ //if the infile is bsq file
982 if(header.data_type ==envi_header::float32) 982 if(header.data_type ==envi_header::float32)
@@ -1015,7 +1015,7 @@ public: @@ -1015,7 +1015,7 @@ public:
1015 1015
1016 /// @param p is a pointer to an allocated region of memory at least X * Y * sizeof(T) in size. 1016 /// @param p is a pointer to an allocated region of memory at least X * Y * sizeof(T) in size.
1017 /// @param page <= B is the integer number of the band to be copied. 1017 /// @param page <= B is the integer number of the band to be copied.
1018 - bool band_index(void* ptr, unsigned int b){ 1018 + bool band_index(void* ptr, unsigned long long b){
1019 if (header.interleave == envi_header::BSQ){ //if the infile is bsq file 1019 if (header.interleave == envi_header::BSQ){ //if the infile is bsq file
1020 if (header.data_type == envi_header::float32) 1020 if (header.data_type == envi_header::float32)
1021 return ((bsq<float>*)file)->band_index((float*)ptr, b); 1021 return ((bsq<float>*)file)->band_index((float*)ptr, b);
stim/envi/envi_header.h
@@ -23,10 +23,10 @@ struct envi_header @@ -23,10 +23,10 @@ struct envi_header
23 23
24 std::string description; 24 std::string description;
25 25
26 - unsigned int samples; //x-axis  
27 - unsigned int lines; //y-axis  
28 - unsigned int bands; //spectral axis  
29 - unsigned int header_offset; //header offset for binary file (in bytes) 26 + unsigned long long samples; //x-axis
  27 + unsigned long long lines; //y-axis
  28 + unsigned long long bands; //spectral axis
  29 + unsigned long long header_offset; //header offset for binary file (in bytes)
30 std::string file_type; //should be "ENVI Standard" 30 std::string file_type; //should be "ENVI Standard"
31 31
32 envi_header::dataType data_type; //data representation; common value is 4 (32-bit float) 32 envi_header::dataType data_type; //data representation; common value is 4 (32-bit float)
@@ -81,7 +81,7 @@ struct envi_header @@ -81,7 +81,7 @@ struct envi_header
81 if(line.length() == 0) 81 if(line.length() == 0)
82 return line; 82 return line;
83 //trims whitespace from the beginning and end of line 83 //trims whitespace from the beginning and end of line
84 - unsigned int start_i, end_i; 84 + size_t start_i, end_i;
85 for(start_i=0; start_i < line.length(); start_i++) 85 for(start_i=0; start_i < line.length(); start_i++)
86 if(line[start_i] != 32) 86 if(line[start_i] != 32)
87 { 87 {
@@ -307,7 +307,7 @@ struct envi_header @@ -307,7 +307,7 @@ struct envi_header
307 } 307 }
308 308
309 //make sure the number of bands matches the number of wavelengths 309 //make sure the number of bands matches the number of wavelengths
310 - unsigned int wavelengths = wavelength.size(); 310 + size_t wavelengths = wavelength.size();
311 if(wavelengths && bands != wavelengths) 311 if(wavelengths && bands != wavelengths)
312 { 312 {
313 std::cout<<"ENVI Header Error -- Number of wavelengths doesn't match the number of bands. Bands = "<<bands<<", Wavelengths = "<<wavelength.size()<<std::endl; 313 std::cout<<"ENVI Header Error -- Number of wavelengths doesn't match the number of bands. Bands = "<<bands<<", Wavelengths = "<<wavelength.size()<<std::endl;
stim/envi/hsi.h 0 โ†’ 100644
  1 +#ifndef STIM_HSI_H
  2 +#define STIM_HSI_H
  3 +
  4 +#include "../envi/envi_header.h"
  5 +#include "../envi/binary.h"
  6 +#include <cstring>
  7 +#include <utility>
  8 +
  9 +namespace stim{
  10 +
  11 +/**
  12 + The BIL class represents a 3-dimensional binary file stored using band interleaved by line (BIL) image encoding. The binary file is stored
  13 + such that X-Z "frames" are stored sequentially to form an image stack along the y-axis. When accessing the data sequentially on disk,
  14 + the dimensions read, from fastest to slowest, are X, Z, Y.
  15 +
  16 + This class is optimized for data streaming, and therefore supports extremely large (terabyte-scale) files. Data is loaded from disk
  17 + on request. Functions used to access data are written to support efficient reading.
  18 +*/
  19 +
  20 +template <typename T>
  21 +class hsi: public binary<T> {
  22 +
  23 +protected:
  24 + unsigned char O[3]; //order of dimensions (orientation on disk)
  25 + //[X Y B]: [0 1 2] = bsq, [0 2 1] = bil, [1 2 0] = bip
  26 +
  27 + std::vector<double> w; //band wavelengths
  28 +
  29 + unsigned long long X(){ return R[O[0]]; }
  30 + unsigned long long Y(){ return R[O[1]]; }
  31 + unsigned long long Z(){ return R[O[2]]; }
  32 +
  33 + /// Initialize axis orders based on common interleave formats
  34 + void init_bsq(){ O[0] = 0; O[1] = 1; O[2] = 2; }
  35 + void init_bil(){ O[0] = 0; O[1] = 2; O[2] = 1; }
  36 + void init_bip(){ O[0] = 1; O[1] = 2; O[2] = 0; }
  37 +
  38 + /// Calculate the number of masked pixels in a given mask
  39 + unsigned long long nnz(unsigned char* mask){
  40 + unsigned long long XY = X() * Y(); //calculate the total number of pixels in the HSI
  41 + if(mask == NULL) return XY; //if the mask is null, assume that all of the pixels are masked
  42 +
  43 + unsigned long long n = 0; //initialize the number of masked pixels to zero (0)
  44 + for(unsigned long long xy = 0; xy < XY; xy++) //for each pixel in the HSI
  45 + if(mask[xy]) n++; //if the mask value is nonzero, increment the number of masked pixels
  46 + return n; //return the number of masked pixels
  47 + }
  48 +
  49 + T lerp(double w, T low_v, double low_w, T high_v, double high_w){
  50 + if(low_w == high_w) return low_v; //if the interval is of zero length, just return one of the bounds
  51 + double alpha = (w - low_w) / (high_w - low_w); //calculate the interpolation factor
  52 + return (T)((1.0 - alpha) * low_v + alpha * high_v); //interpolate
  53 + }
  54 +
  55 + /// Gets the two band indices surrounding a given wavelength
  56 + void band_bounds(double wavelength, unsigned long long& low, unsigned long long& high){
  57 + unsigned long long B = Z();
  58 + for(high = 0; high < B; high++){
  59 + if(w[high] > wavelength) break;
  60 + }
  61 + low = 0;
  62 + if(high > 0)
  63 + low = high-1;
  64 + }
  65 +
  66 + /// Get the list of band numbers that bound a list of wavelengths
  67 + void band_bounds(std::vector<double> wavelengths,
  68 + std::vector<unsigned long long>& low_bands,
  69 + std::vector<unsigned long long>& high_bands){
  70 +
  71 + unsigned long long W = w.size(); //get the number of wavelengths in the list
  72 + low_bands.resize(W); //pre-allocate space for the band lists
  73 + high_bands.resize(W);
  74 +
  75 + for(unsigned long long wl = 0; wl < W; wl++){ //for each wavelength
  76 + band_bounds(wavelengths[wl], low_bands[wl], high_bands[wl]); //find the low and high bands
  77 + }
  78 + }
  79 +
  80 + /// Returns the interpolated in the given spectrum based on the given wavelength
  81 +
  82 + /// @param s is the spectrum in main memory of length Z()
  83 + /// @param wavelength is the wavelength value to interpolate out
  84 + T interp_spectrum(T* s, double wavelength){
  85 + unsigned long long low, high; //indices for the bands surrounding wavelength
  86 + band_bounds(wavelength, low, high); //get the surrounding band indices
  87 +
  88 + if(high == w.size()) return s[w.size()-1]; //if the high band is above the wavelength range, return the highest wavelength value
  89 +
  90 + return lerp(wavelength, s[low], w[low], s[high], w[high]);
  91 + }
  92 +
  93 + /// Returns the interpolated value corresponding to the given list of wavelengths
  94 + std::vector<T> interp_spectrum(T* s, std::vector<double> wavelengths){
  95 +
  96 + unsigned long long N = wavelengths.size(); //get the number of wavelength measurements
  97 +
  98 + std::vector<T> v; //allocate space for the resulting values
  99 + v.resize(wavelengths.size());
  100 + for(unsigned long long n = 0; n < N; n++){ //for each measurement
  101 + v[n] = interp_spectrum(s, wavelengths[n]); //interpolate the measurement
  102 + }
  103 + return v;
  104 + }
  105 +};
  106 +
  107 +} //end namespace STIM
  108 +
  109 +#endif
0 \ No newline at end of file 110 \ No newline at end of file
@@ -54,7 +54,7 @@ @@ -54,7 +54,7 @@
54 54
55 // Set version number of the library. 55 // Set version number of the library.
56 #ifndef cimg_version 56 #ifndef cimg_version
57 -#define cimg_version 169 57 +#define cimg_version 170
58 58
59 /*----------------------------------------------------------- 59 /*-----------------------------------------------------------
60 # 60 #
@@ -2340,7 +2340,7 @@ namespace cimg_library_suffixed { @@ -2340,7 +2340,7 @@ namespace cimg_library_suffixed {
2340 char *_message; 2340 char *_message;
2341 CImgException() { _message = new char[1]; *_message = 0; } 2341 CImgException() { _message = new char[1]; *_message = 0; }
2342 CImgException(const char *const format, ...):_message(0) { _cimg_exception_err("CImgException",true); } 2342 CImgException(const char *const format, ...):_message(0) { _cimg_exception_err("CImgException",true); }
2343 - CImgException(const CImgException& e) { 2343 + CImgException(const CImgException& e):std::exception(e) {
2344 const int size = std::strlen(e._message); 2344 const int size = std::strlen(e._message);
2345 _message = new char[size + 1]; 2345 _message = new char[size + 1];
2346 std::strncpy(_message,e._message,size); 2346 std::strncpy(_message,e._message,size);
@@ -2364,7 +2364,7 @@ namespace cimg_library_suffixed { @@ -2364,7 +2364,7 @@ namespace cimg_library_suffixed {
2364 char *_message; 2364 char *_message;
2365 CImgAbortException() { _message = new char[1]; *_message = 0; } 2365 CImgAbortException() { _message = new char[1]; *_message = 0; }
2366 CImgAbortException(const char *const format, ...):_message(0) { _cimg_exception_err("CImgAbortException",true); } 2366 CImgAbortException(const char *const format, ...):_message(0) { _cimg_exception_err("CImgAbortException",true); }
2367 - CImgAbortException(const CImgAbortException& e) { 2367 + CImgAbortException(const CImgAbortException& e):std::exception(e) {
2368 const int size = std::strlen(e._message); 2368 const int size = std::strlen(e._message);
2369 _message = new char[size + 1]; 2369 _message = new char[size + 1];
2370 std::strncpy(_message,e._message,size); 2370 std::strncpy(_message,e._message,size);
@@ -2442,7 +2442,7 @@ namespace cimg_library_suffixed { @@ -2442,7 +2442,7 @@ namespace cimg_library_suffixed {
2442 static bool is_inf(const T) { return false; } 2442 static bool is_inf(const T) { return false; }
2443 static bool is_nan(const T) { return false; } 2443 static bool is_nan(const T) { return false; }
2444 static T min() { return ~max(); } 2444 static T min() { return ~max(); }
2445 - static T max() { return (T)(1UL<<(8*sizeof(T) - 1)); } 2445 + static T max() { return (T)1<<(8*sizeof(T) - 1); }
2446 static T inf() { return max(); } 2446 static T inf() { return max(); }
2447 static T cut(const double val) { return val<(double)min()?min():val>(double)max()?max():(T)val; } 2447 static T cut(const double val) { return val<(double)min()?min():val>(double)max()?max():(T)val; }
2448 static const char* format() { return "%s"; } 2448 static const char* format() { return "%s"; }
@@ -13726,8 +13726,9 @@ namespace cimg_library_suffixed { @@ -13726,8 +13726,9 @@ namespace cimg_library_suffixed {
13726 char *user_function; 13726 char *user_function;
13727 13727
13728 unsigned int mempos, mem_img_median, debug_indent, init_size, result_dim; 13728 unsigned int mempos, mem_img_median, debug_indent, init_size, result_dim;
  13729 + bool is_parallelizable, need_input_copy;
13729 double *result; 13730 double *result;
13730 - const char *const calling_function; 13731 + const char *const calling_function, *s_op, *ss_op;
13731 typedef double (*mp_func)(_cimg_math_parser&); 13732 typedef double (*mp_func)(_cimg_math_parser&);
13732 13733
13733 #define _cimg_mp_is_constant(arg) (memtype[arg]==1) // Is constant? 13734 #define _cimg_mp_is_constant(arg) (memtype[arg]==1) // Is constant?
@@ -13737,12 +13738,14 @@ namespace cimg_library_suffixed { @@ -13737,12 +13738,14 @@ namespace cimg_library_suffixed {
13737 #define _cimg_mp_is_vector(arg) (memtype[arg]>1) // Is vector? 13738 #define _cimg_mp_is_vector(arg) (memtype[arg]>1) // Is vector?
13738 #define _cimg_mp_vector_size(arg) (_cimg_mp_is_scalar(arg)?0U:(unsigned int)memtype[arg] - 1) // Vector size 13739 #define _cimg_mp_vector_size(arg) (_cimg_mp_is_scalar(arg)?0U:(unsigned int)memtype[arg] - 1) // Vector size
13739 #define _cimg_mp_calling_function calling_function_s()._data 13740 #define _cimg_mp_calling_function calling_function_s()._data
13740 -#define _cimg_mp_check_type(arg,n_arg,s_op,mode,N) check_type(arg,n_arg,s_op,mode,N,ss,se,saved_char)  
13741 -#define _cimg_mp_check_constant(arg,n_arg,s_op,is_strict) check_constant(arg,n_arg,s_op,is_strict,ss,se,saved_char)  
13742 -#define _cimg_mp_check_matrix_square(arg,n_arg,s_op) check_matrix_square(arg,n_arg,s_op,ss,se,saved_char)  
13743 -#define _cimg_mp_check_vector0(dim,s_op) check_vector0(dim,s_op,ss,se,saved_char) 13741 +#define _cimg_mp_op(s) s_op = s; ss_op = ss
  13742 +#define _cimg_mp_check_type(arg,n_arg,mode,N) check_type(arg,n_arg,mode,N,ss,se,saved_char)
  13743 +#define _cimg_mp_check_constant(arg,n_arg,is_strict) check_constant(arg,n_arg,is_strict,ss,se,saved_char)
  13744 +#define _cimg_mp_check_matrix_square(arg,n_arg) check_matrix_square(arg,n_arg,ss,se,saved_char)
  13745 +#define _cimg_mp_check_vector0(dim) check_vector0(dim,ss,se,saved_char)
  13746 +#define _cimg_mp_check_list(is_out) check_list(is_out,ss,se,saved_char)
13744 #define _cimg_mp_defunc(mp) (*(mp_func)(*(mp).opcode))(mp) 13747 #define _cimg_mp_defunc(mp) (*(mp_func)(*(mp).opcode))(mp)
13745 -#define _cimg_mp_return(x) { *se = saved_char; return x; } 13748 +#define _cimg_mp_return(x) { *se = saved_char; s_op = previous_s_op; ss_op = previous_ss_op; return x; }
13746 #define _cimg_mp_constant(val) _cimg_mp_return(constant(val)) 13749 #define _cimg_mp_constant(val) _cimg_mp_return(constant(val))
13747 #define _cimg_mp_scalar0(op) _cimg_mp_return(scalar0(op)) 13750 #define _cimg_mp_scalar0(op) _cimg_mp_return(scalar0(op))
13748 #define _cimg_mp_scalar1(op,i1) _cimg_mp_return(scalar1(op,i1)) 13751 #define _cimg_mp_scalar1(op,i1) _cimg_mp_return(scalar1(op,i1))
@@ -13763,19 +13766,22 @@ namespace cimg_library_suffixed { @@ -13763,19 +13766,22 @@ namespace cimg_library_suffixed {
13763 code(_code),imgin(img_input),listin(list_input?*list_input:CImgList<T>::const_empty()), 13766 code(_code),imgin(img_input),listin(list_input?*list_input:CImgList<T>::const_empty()),
13764 imgout(img_output?*img_output:CImg<T>::empty()),listout(list_output?*list_output:CImgList<T>::empty()), 13767 imgout(img_output?*img_output:CImg<T>::empty()),listout(list_output?*list_output:CImgList<T>::empty()),
13765 img_stats(_img_stats),list_stats(_list_stats),list_median(_list_median),user_function(0), 13768 img_stats(_img_stats),list_stats(_list_stats),list_median(_list_median),user_function(0),
13766 - mem_img_median(~0U),debug_indent(0),init_size(0),result_dim(0),  
13767 - calling_function(funcname?funcname:"cimg_math_parser") { 13769 + mem_img_median(~0U),debug_indent(0),init_size(0),result_dim(0),is_parallelizable(true),
  13770 + need_input_copy(false),calling_function(funcname?funcname:"cimg_math_parser") {
13768 if (!expression || !*expression) 13771 if (!expression || !*expression)
13769 throw CImgArgumentException("[_cimg_math_parser] " 13772 throw CImgArgumentException("[_cimg_math_parser] "
13770 "CImg<%s>::%s: Empty expression.", 13773 "CImg<%s>::%s: Empty expression.",
13771 pixel_type(),_cimg_mp_calling_function); 13774 pixel_type(),_cimg_mp_calling_function);
13772 const char *_expression = expression; 13775 const char *_expression = expression;
13773 - while (*_expression && *_expression<=' ') ++_expression; 13776 + while (*_expression && (*_expression<=' ' || *_expression==';')) ++_expression;
13774 CImg<charT>::string(_expression).move_to(expr); 13777 CImg<charT>::string(_expression).move_to(expr);
  13778 + char *ps = &expr.back() - 1;
  13779 + while (ps>expr._data && (*ps==' ' || *ps==';')) --ps;
  13780 + *(++ps) = 0; expr._width = ps - expr._data + 1;
13775 13781
13776 // Ease the retrieval of previous non-space characters afterwards. 13782 // Ease the retrieval of previous non-space characters afterwards.
13777 pexpr.assign(expr._width); 13783 pexpr.assign(expr._width);
13778 - const char *ps; 13784 +
13779 char c, *pe = pexpr._data; 13785 char c, *pe = pexpr._data;
13780 for (ps = expr._data, c = ' '; *ps; ++ps) { 13786 for (ps = expr._data, c = ' '; *ps; ++ps) {
13781 if (*ps!=' ') c = *ps; 13787 if (*ps!=' ') c = *ps;
@@ -13854,6 +13860,7 @@ namespace cimg_library_suffixed { @@ -13854,6 +13860,7 @@ namespace cimg_library_suffixed {
13854 // [11] = xm, [12] = ym, [13] = zm, [14] = cm, [15] = xM, [16] = yM, [17] = zM, [18]=cM, [19]=i0...[28]=i9, 13860 // [11] = xm, [12] = ym, [13] = zm, [14] = cm, [15] = xM, [16] = yM, [17] = zM, [18]=cM, [19]=i0...[28]=i9,
13855 13861
13856 // Compile expression into a serie of opcodes. 13862 // Compile expression into a serie of opcodes.
  13863 + s_op = ""; ss_op = expr._data;
13857 const unsigned int ind_result = compile(expr._data,expr._data + expr._width - 1,0,0); 13864 const unsigned int ind_result = compile(expr._data,expr._data + expr._width - 1,0,0);
13858 p_code_end = code.end(); 13865 p_code_end = code.end();
13859 13866
@@ -13867,6 +13874,7 @@ namespace cimg_library_suffixed { @@ -13867,6 +13874,7 @@ namespace cimg_library_suffixed {
13867 reserved_label.assign(); 13874 reserved_label.assign();
13868 expr.assign(); 13875 expr.assign();
13869 pexpr.assign(); 13876 pexpr.assign();
  13877 + opcode.assign();
13870 opcode._width = opcode._depth = opcode._spectrum = 1; 13878 opcode._width = opcode._depth = opcode._spectrum = 1;
13871 opcode._is_shared = true; 13879 opcode._is_shared = true;
13872 13880
@@ -13888,7 +13896,7 @@ namespace cimg_library_suffixed { @@ -13888,7 +13896,7 @@ namespace cimg_library_suffixed {
13888 imgin(CImg<T>::const_empty()),listin(CImgList<T>::const_empty()), 13896 imgin(CImg<T>::const_empty()),listin(CImgList<T>::const_empty()),
13889 imgout(CImg<T>::empty()),listout(CImgList<T>::empty()), 13897 imgout(CImg<T>::empty()),listout(CImgList<T>::empty()),
13890 img_stats(_img_stats),list_stats(_list_stats),list_median(_list_median),debug_indent(0), 13898 img_stats(_img_stats),list_stats(_list_stats),list_median(_list_median),debug_indent(0),
13891 - result_dim(0),calling_function(0) { 13899 + result_dim(0),is_parallelizable(true),need_input_copy(false),calling_function(0) {
13892 mem.assign(1 + _cimg_mp_c,1,1,1,0); // Allow to skip 'is_empty?' test in operator()() 13900 mem.assign(1 + _cimg_mp_c,1,1,1,0); // Allow to skip 'is_empty?' test in operator()()
13893 result = mem._data; 13901 result = mem._data;
13894 } 13902 }
@@ -13896,8 +13904,9 @@ namespace cimg_library_suffixed { @@ -13896,8 +13904,9 @@ namespace cimg_library_suffixed {
13896 _cimg_math_parser(const _cimg_math_parser& mp): 13904 _cimg_math_parser(const _cimg_math_parser& mp):
13897 mem(mp.mem),code(mp.code),p_code_begin(mp.p_code_begin),p_code_end(mp.p_code_end), 13905 mem(mp.mem),code(mp.code),p_code_begin(mp.p_code_begin),p_code_end(mp.p_code_end),
13898 imgin(mp.imgin),listin(mp.listin),imgout(mp.imgout),listout(mp.listout),img_stats(mp.img_stats), 13906 imgin(mp.imgin),listin(mp.listin),imgout(mp.imgout),listout(mp.listout),img_stats(mp.img_stats),
13899 - list_stats(mp.list_stats),list_median(mp.list_median),debug_indent(0),  
13900 - result_dim(mp.result_dim), result(mem._data + (mp.result - mp.mem._data)),calling_function(0) { 13907 + list_stats(mp.list_stats),list_median(mp.list_median),debug_indent(0),result_dim(mp.result_dim),
  13908 + is_parallelizable(mp.is_parallelizable), need_input_copy(mp.need_input_copy),
  13909 + result(mem._data + (mp.result - mp.mem._data)),calling_function(0) {
13901 #ifdef cimg_use_openmp 13910 #ifdef cimg_use_openmp
13902 mem[17] = omp_get_thread_num(); 13911 mem[17] = omp_get_thread_num();
13903 #endif 13912 #endif
@@ -13905,30 +13914,8 @@ namespace cimg_library_suffixed { @@ -13905,30 +13914,8 @@ namespace cimg_library_suffixed {
13905 opcode._is_shared = true; 13914 opcode._is_shared = true;
13906 } 13915 }
13907 13916
13908 - // Return 'true' is the specified mathematical expression requires the input image to be copied.  
13909 - // Set 'is_parallelizable' to 'false' if expression should be evaluated with a single thread.  
13910 - static bool needs_input_copy(const char *expression, bool &is_parallelizable) {  
13911 - if (!expression || *expression=='>' || *expression=='<') return is_parallelizable = false;  
13912 - for (const char *s = expression; *s; ++s)  
13913 - if ((*s=='i' || *s=='j' || *s=='I' || *s=='J') && (s[1]=='(' || s[1]=='[')) {  
13914 - if (s[2]=='#') is_parallelizable = false;  
13915 - else {  
13916 - const char opening = s[1], ending = opening=='('?')':']';  
13917 - const char *ns;  
13918 - int level = 0;  
13919 - for (ns = s + 2; *ns; ++ns) { // Find ending ')' or ']'.  
13920 - if (*ns==ending && !level) break;  
13921 - if (*ns==opening) ++level; else if (*ns==ending) --level;  
13922 - }  
13923 - if (*ns && (ns[1]!='=' || ns[2]=='=')) return true;  
13924 - }  
13925 - } else if (((*s=='R' || *s=='G' || *s=='B' || *s=='A' || *s=='I' || *s=='J') && s[1]!='#') ||  
13926 - (*s=='i' && s[1]>='0' && s[1]<='7' && s[2]!='#')) return true;  
13927 - return false;  
13928 - }  
13929 -  
13930 // Compilation procedure. 13917 // Compilation procedure.
13931 - unsigned int compile(char *ss, char *se, const unsigned int depth, unsigned int *p_ref) { 13918 + unsigned int compile(char *ss, char *se, const unsigned int depth, unsigned int *const p_ref) {
13932 if (depth>256) { 13919 if (depth>256) {
13933 cimg::strellipsize(expr,64); 13920 cimg::strellipsize(expr,64);
13934 throw CImgArgumentException("[_cimg_math_parser] " 13921 throw CImgArgumentException("[_cimg_math_parser] "
@@ -13954,10 +13941,15 @@ namespace cimg_library_suffixed { @@ -13954,10 +13941,15 @@ namespace cimg_library_suffixed {
13954 if (se<=ss || !*ss) { 13941 if (se<=ss || !*ss) {
13955 cimg::strellipsize(expr,64); 13942 cimg::strellipsize(expr,64);
13956 throw CImgArgumentException("[_cimg_math_parser] " 13943 throw CImgArgumentException("[_cimg_math_parser] "
13957 - "CImg<%s>::%s: Missing item, in expression '%s'.",  
13958 - pixel_type(),_cimg_mp_calling_function,  
13959 - expr._data); 13944 + "CImg<%s>::%s: %s%s Missing %s, in expression '%s%s%s'.",
  13945 + pixel_type(),_cimg_mp_calling_function,s_op,*s_op?":":"",
  13946 + *s_op=='F'?"argument":"item",
  13947 + (ss_op - 4)>expr._data?"...":"",
  13948 + (ss_op - 4)>expr._data?ss_op - 4:expr._data,
  13949 + ss_op + std::strlen(ss_op)<&expr.back()?"...":"");
13960 } 13950 }
  13951 +
  13952 + const char *const previous_s_op = s_op, *const previous_ss_op = ss_op;
13961 const unsigned int depth1 = depth + 1; 13953 const unsigned int depth1 = depth + 1;
13962 unsigned int pos, p1, p2, p3, arg1, arg2, arg3, arg4, arg5, arg6; 13954 unsigned int pos, p1, p2, p3, arg1, arg2, arg3, arg4, arg5, arg6;
13963 char 13955 char
@@ -13966,7 +13958,6 @@ namespace cimg_library_suffixed { @@ -13966,7 +13958,6 @@ namespace cimg_library_suffixed {
13966 *const ss5 = ss + 5, *const ss6 = ss + 6, *const ss7 = ss + 7, *const ss8 = ss + 8, 13958 *const ss5 = ss + 5, *const ss6 = ss + 6, *const ss7 = ss + 7, *const ss8 = ss + 8,
13967 *s, *ps, *ns, *s0, *s1, *s2, *s3, sep = 0, end = 0; 13959 *s, *ps, *ns, *s0, *s1, *s2, *s3, sep = 0, end = 0;
13968 double val, val1, val2; 13960 double val, val1, val2;
13969 - const char *s_op;  
13970 mp_func op; 13961 mp_func op;
13971 13962
13972 // 'p_ref' is a 'unsigned int[7]' used to return a reference to an image or vector value 13963 // 'p_ref' is a 'unsigned int[7]' used to return a reference to an image or vector value
@@ -14022,22 +14013,28 @@ namespace cimg_library_suffixed { @@ -14022,22 +14013,28 @@ namespace cimg_library_suffixed {
14022 if (reserved_label['i']!=~0U) _cimg_mp_return(reserved_label['i']); 14013 if (reserved_label['i']!=~0U) _cimg_mp_return(reserved_label['i']);
14023 _cimg_mp_scalar0(mp_i); 14014 _cimg_mp_scalar0(mp_i);
14024 case 'I' : 14015 case 'I' :
  14016 + _cimg_mp_op("Variable 'I'");
14025 if (reserved_label['I']!=~0U) _cimg_mp_return(reserved_label['I']); 14017 if (reserved_label['I']!=~0U) _cimg_mp_return(reserved_label['I']);
14026 - _cimg_mp_check_vector0(imgin._spectrum,"variable 'I'"); 14018 + _cimg_mp_check_vector0(imgin._spectrum);
  14019 + need_input_copy = true;
14027 pos = vector(imgin._spectrum); 14020 pos = vector(imgin._spectrum);
14028 CImg<uptrT>::vector((uptrT)mp_Joff,pos,0,0).move_to(code); 14021 CImg<uptrT>::vector((uptrT)mp_Joff,pos,0,0).move_to(code);
14029 _cimg_mp_return(pos); 14022 _cimg_mp_return(pos);
14030 case 'R' : 14023 case 'R' :
14031 if (reserved_label['R']!=~0U) _cimg_mp_return(reserved_label['R']); 14024 if (reserved_label['R']!=~0U) _cimg_mp_return(reserved_label['R']);
  14025 + need_input_copy = true;
14032 _cimg_mp_scalar6(mp_ixyzc,_cimg_mp_x,_cimg_mp_y,_cimg_mp_z,0,0,0); 14026 _cimg_mp_scalar6(mp_ixyzc,_cimg_mp_x,_cimg_mp_y,_cimg_mp_z,0,0,0);
14033 case 'G' : 14027 case 'G' :
14034 if (reserved_label['G']!=~0U) _cimg_mp_return(reserved_label['G']); 14028 if (reserved_label['G']!=~0U) _cimg_mp_return(reserved_label['G']);
  14029 + need_input_copy = true;
14035 _cimg_mp_scalar6(mp_ixyzc,_cimg_mp_x,_cimg_mp_y,_cimg_mp_z,1,0,0); 14030 _cimg_mp_scalar6(mp_ixyzc,_cimg_mp_x,_cimg_mp_y,_cimg_mp_z,1,0,0);
14036 case 'B' : 14031 case 'B' :
14037 if (reserved_label['B']!=~0U) _cimg_mp_return(reserved_label['B']); 14032 if (reserved_label['B']!=~0U) _cimg_mp_return(reserved_label['B']);
  14033 + need_input_copy = true;
14038 _cimg_mp_scalar6(mp_ixyzc,_cimg_mp_x,_cimg_mp_y,_cimg_mp_z,2,0,0); 14034 _cimg_mp_scalar6(mp_ixyzc,_cimg_mp_x,_cimg_mp_y,_cimg_mp_z,2,0,0);
14039 case 'A' : 14035 case 'A' :
14040 if (reserved_label['A']!=~0U) _cimg_mp_return(reserved_label['A']); 14036 if (reserved_label['A']!=~0U) _cimg_mp_return(reserved_label['A']);
  14037 + need_input_copy = true;
14041 _cimg_mp_scalar6(mp_ixyzc,_cimg_mp_x,_cimg_mp_y,_cimg_mp_z,3,0,0); 14038 _cimg_mp_scalar6(mp_ixyzc,_cimg_mp_x,_cimg_mp_y,_cimg_mp_z,3,0,0);
14042 } 14039 }
14043 else if (ss2==se) { // Two-chars variable 14040 else if (ss2==se) { // Two-chars variable
@@ -14048,6 +14045,7 @@ namespace cimg_library_suffixed { @@ -14048,6 +14045,7 @@ namespace cimg_library_suffixed {
14048 if (*ss1>='0' && *ss1<='9') { // i0...i9 14045 if (*ss1>='0' && *ss1<='9') { // i0...i9
14049 pos = 19 + *ss1 - '0'; 14046 pos = 19 + *ss1 - '0';
14050 if (reserved_label[pos]!=~0U) _cimg_mp_return(reserved_label[pos]); 14047 if (reserved_label[pos]!=~0U) _cimg_mp_return(reserved_label[pos]);
  14048 + need_input_copy = true;
14051 _cimg_mp_scalar6(mp_ixyzc,_cimg_mp_x,_cimg_mp_y,_cimg_mp_z,pos - 19,0,0); 14049 _cimg_mp_scalar6(mp_ixyzc,_cimg_mp_x,_cimg_mp_y,_cimg_mp_z,pos - 19,0,0);
14052 } 14050 }
14053 switch (*ss1) { 14051 switch (*ss1) {
@@ -14109,7 +14107,7 @@ namespace cimg_library_suffixed { @@ -14109,7 +14107,7 @@ namespace cimg_library_suffixed {
14109 cimg::strpare(variable_name); 14107 cimg::strpare(variable_name);
14110 const unsigned int l_variable_name = (unsigned int)std::strlen(variable_name); 14108 const unsigned int l_variable_name = (unsigned int)std::strlen(variable_name);
14111 char *const ve1 = ss + l_variable_name - 1; 14109 char *const ve1 = ss + l_variable_name - 1;
14112 - s_op = "Operator '='"; 14110 + _cimg_mp_op("Operator '='");
14113 14111
14114 // Assign image value (direct). 14112 // Assign image value (direct).
14115 if (l_variable_name>2 && (*ss=='i' || *ss=='j' || *ss=='I' || *ss=='J') && (*ss1=='(' || *ss1=='[') && 14113 if (l_variable_name>2 && (*ss=='i' || *ss=='j' || *ss=='I' || *ss=='J') && (*ss1=='(' || *ss1=='[') &&
@@ -14117,9 +14115,11 @@ namespace cimg_library_suffixed { @@ -14117,9 +14115,11 @@ namespace cimg_library_suffixed {
14117 is_relative = *ss=='j' || *ss=='J'; 14115 is_relative = *ss=='j' || *ss=='J';
14118 14116
14119 if (*ss1=='[' && *ve1==']') { // i/j/I/J[_#ind,offset] = value 14117 if (*ss1=='[' && *ve1==']') { // i/j/I/J[_#ind,offset] = value
  14118 + is_parallelizable = false;
14120 if (*ss2=='#') { // Index specified 14119 if (*ss2=='#') { // Index specified
14121 s0 = ss3; while (s0<ve1 && (*s0!=',' || level[s0 - expr._data]!=clevel1)) ++s0; 14120 s0 = ss3; while (s0<ve1 && (*s0!=',' || level[s0 - expr._data]!=clevel1)) ++s0;
14122 p1 = compile(ss3,s0++,depth1,0); 14121 p1 = compile(ss3,s0++,depth1,0);
  14122 + _cimg_mp_check_list(true);
14123 } else { p1 = ~0U; s0 = ss2; } 14123 } else { p1 = ~0U; s0 = ss2; }
14124 arg1 = compile(s0,ve1,depth1,0); // Offset 14124 arg1 = compile(s0,ve1,depth1,0); // Offset
14125 arg2 = compile(s + 1,se,depth1,0); // Value to assign 14125 arg2 = compile(s + 1,se,depth1,0); // Value to assign
@@ -14130,9 +14130,9 @@ namespace cimg_library_suffixed { @@ -14130,9 +14130,9 @@ namespace cimg_library_suffixed {
14130 p3 = (unsigned int)cimg::mod((int)mem[p1],listin.width()); 14130 p3 = (unsigned int)cimg::mod((int)mem[p1],listin.width());
14131 p2 = listin[p3]._spectrum; 14131 p2 = listin[p3]._spectrum;
14132 } 14132 }
14133 - _cimg_mp_check_vector0(p2,s_op); 14133 + _cimg_mp_check_vector0(p2);
14134 } else p2 = 0; 14134 } else p2 = 0;
14135 - _cimg_mp_check_type(arg2,2,s_op,*ss>='i'?1:3,p2); 14135 + _cimg_mp_check_type(arg2,2,*ss>='i'?1:3,p2);
14136 14136
14137 if (p_ref) { 14137 if (p_ref) {
14138 *p_ref = _cimg_mp_is_vector(arg2)?4:2; 14138 *p_ref = _cimg_mp_is_vector(arg2)?4:2;
@@ -14172,9 +14172,11 @@ namespace cimg_library_suffixed { @@ -14172,9 +14172,11 @@ namespace cimg_library_suffixed {
14172 } 14172 }
14173 14173
14174 if (*ss1=='(' && *ve1==')') { // i/j/I/J(_#ind,_x,_y,_z,_c) = value 14174 if (*ss1=='(' && *ve1==')') { // i/j/I/J(_#ind,_x,_y,_z,_c) = value
  14175 + is_parallelizable = false;
14175 if (*ss2=='#') { // Index specified 14176 if (*ss2=='#') { // Index specified
14176 s0 = ss3; while (s0<ve1 && (*s0!=',' || level[s0 - expr._data]!=clevel1)) ++s0; 14177 s0 = ss3; while (s0<ve1 && (*s0!=',' || level[s0 - expr._data]!=clevel1)) ++s0;
14177 p1 = compile(ss3,s0++,depth1,0); 14178 p1 = compile(ss3,s0++,depth1,0);
  14179 + _cimg_mp_check_list(true);
14178 } else { p1 = ~0U; s0 = ss2; } 14180 } else { p1 = ~0U; s0 = ss2; }
14179 arg1 = is_relative?0U:(unsigned int)_cimg_mp_x; 14181 arg1 = is_relative?0U:(unsigned int)_cimg_mp_x;
14180 arg2 = is_relative?0U:(unsigned int)_cimg_mp_y; 14182 arg2 = is_relative?0U:(unsigned int)_cimg_mp_y;
@@ -14184,9 +14186,9 @@ namespace cimg_library_suffixed { @@ -14184,9 +14186,9 @@ namespace cimg_library_suffixed {
14184 if (s0<ve1) { // X or [ X,_Y,_Z,_C ] 14186 if (s0<ve1) { // X or [ X,_Y,_Z,_C ]
14185 s1 = s0; while (s1<ve1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1; 14187 s1 = s0; while (s1<ve1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
14186 arg1 = compile(s0,s1,depth1,0); 14188 arg1 = compile(s0,s1,depth1,0);
14187 - if (_cimg_mp_is_vector(arg1)) { // Coordinates specified as a vector [X,Y,Z,C] 14189 + if (_cimg_mp_is_vector(arg1)) { // Coordinates specified as a vector
14188 p2 = _cimg_mp_vector_size(arg1); // Vector size 14190 p2 = _cimg_mp_vector_size(arg1); // Vector size
14189 - arg1 = arg1 + 1; 14191 + ++arg1;
14190 if (p2>1) { 14192 if (p2>1) {
14191 arg2 = arg1 + 1; 14193 arg2 = arg1 + 1;
14192 if (p2>2) { 14194 if (p2>2) {
@@ -14212,9 +14214,9 @@ namespace cimg_library_suffixed { @@ -14212,9 +14214,9 @@ namespace cimg_library_suffixed {
14212 p3 = (unsigned int)cimg::mod((int)mem[p1],listin.width()); 14214 p3 = (unsigned int)cimg::mod((int)mem[p1],listin.width());
14213 p2 = listin[p3]._spectrum; 14215 p2 = listin[p3]._spectrum;
14214 } 14216 }
14215 - _cimg_mp_check_vector0(p2,s_op); 14217 + _cimg_mp_check_vector0(p2);
14216 } else p2 = 0; 14218 } else p2 = 0;
14217 - _cimg_mp_check_type(arg5,2,s_op,*ss>='i'?1:3,p2); 14219 + _cimg_mp_check_type(arg5,2,*ss>='i'?1:3,p2);
14218 14220
14219 if (p_ref) { 14221 if (p_ref) {
14220 *p_ref = _cimg_mp_is_vector(arg5)?5:3; 14222 *p_ref = _cimg_mp_is_vector(arg5)?5:3;
@@ -14272,7 +14274,7 @@ namespace cimg_library_suffixed { @@ -14272,7 +14274,7 @@ namespace cimg_library_suffixed {
14272 arg1 = ~0U; // Vector slot 14274 arg1 = ~0U; // Vector slot
14273 arg2 = compile(++s0,ve1,depth1,0); // Index 14275 arg2 = compile(++s0,ve1,depth1,0); // Index
14274 arg3 = compile(s + 1,se,depth1,0); // Value to assign 14276 arg3 = compile(s + 1,se,depth1,0); // Value to assign
14275 - _cimg_mp_check_type(arg3,2,s_op,1,0); 14277 + _cimg_mp_check_type(arg3,2,1,0);
14276 14278
14277 if (variable_name[1]) { // Multi-char variable 14279 if (variable_name[1]) { // Multi-char variable
14278 cimglist_for(variable_def,i) if (!std::strcmp(variable_name,variable_def[i])) { 14280 cimglist_for(variable_def,i) if (!std::strcmp(variable_name,variable_def[i])) {
@@ -14307,8 +14309,8 @@ namespace cimg_library_suffixed { @@ -14307,8 +14309,8 @@ namespace cimg_library_suffixed {
14307 } 14309 }
14308 } 14310 }
14309 14311
14310 - // Assign user-defined function.  
14311 - if (l_variable_name>3 && *ve1==')' && *ss!='(') { 14312 + // Assign user-defined macro.
  14313 + if (l_variable_name>2 && *ve1==')' && *ss!='(') {
14312 s0 = ve1; while (s0>ss && *s0!='(') --s0; 14314 s0 = ve1; while (s0>ss && *s0!='(') --s0;
14313 is_sth = std::strncmp(variable_name,"debug(",6) && 14315 is_sth = std::strncmp(variable_name,"debug(",6) &&
14314 std::strncmp(variable_name,"print(",6); // is_valid_function_name? 14316 std::strncmp(variable_name,"print(",6); // is_valid_function_name?
@@ -14454,7 +14456,7 @@ namespace cimg_library_suffixed { @@ -14454,7 +14456,7 @@ namespace cimg_library_suffixed {
14454 } 14456 }
14455 14457
14456 } else { // Variable already exists -> assign a new value 14458 } else { // Variable already exists -> assign a new value
14457 - _cimg_mp_check_type(arg2,2,s_op,_cimg_mp_is_vector(arg1)?3:1,0); 14459 + _cimg_mp_check_type(arg2,2,_cimg_mp_is_vector(arg1)?3:1,_cimg_mp_vector_size(arg1));
14458 if (_cimg_mp_is_vector(arg1)) { // Vector 14460 if (_cimg_mp_is_vector(arg1)) { // Vector
14459 if (_cimg_mp_is_vector(arg2)) // From vector 14461 if (_cimg_mp_is_vector(arg2)) // From vector
14460 CImg<uptrT>::vector((uptrT)mp_vector_copy,arg1,arg2,(uptrT)_cimg_mp_vector_size(arg1)). 14462 CImg<uptrT>::vector((uptrT)mp_vector_copy,arg1,arg2,(uptrT)_cimg_mp_vector_size(arg1)).
@@ -14478,7 +14480,7 @@ namespace cimg_library_suffixed { @@ -14478,7 +14480,7 @@ namespace cimg_library_suffixed {
14478 arg2 = compile(s + 1,se,depth1,0); // Value to assign 14480 arg2 = compile(s + 1,se,depth1,0); // Value to assign
14479 14481
14480 if (*ref==1) { // Vector value (scalar): V[k] = scalar 14482 if (*ref==1) { // Vector value (scalar): V[k] = scalar
14481 - _cimg_mp_check_type(arg2,2,s_op,1,0); 14483 + _cimg_mp_check_type(arg2,2,1,0);
14482 arg3 = ref[1]; // Vector slot 14484 arg3 = ref[1]; // Vector slot
14483 arg4 = ref[2]; // Index 14485 arg4 = ref[2]; // Index
14484 if (p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int)); 14486 if (p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int));
@@ -14488,7 +14490,8 @@ namespace cimg_library_suffixed { @@ -14488,7 +14490,8 @@ namespace cimg_library_suffixed {
14488 } 14490 }
14489 14491
14490 if (*ref==2) { // Image value (scalar): i/j[_#ind,off] = scalar 14492 if (*ref==2) { // Image value (scalar): i/j[_#ind,off] = scalar
14491 - _cimg_mp_check_type(arg2,2,s_op,1,0); 14493 + _cimg_mp_check_type(arg2,2,1,0);
  14494 + is_parallelizable = false;
14492 p1 = ref[1]; // Index 14495 p1 = ref[1]; // Index
14493 is_relative = (bool)ref[2]; 14496 is_relative = (bool)ref[2];
14494 arg3 = ref[3]; // Offset 14497 arg3 = ref[3]; // Offset
@@ -14506,7 +14509,8 @@ namespace cimg_library_suffixed { @@ -14506,7 +14509,8 @@ namespace cimg_library_suffixed {
14506 } 14509 }
14507 14510
14508 if (*ref==3) { // Image value (scalar): i/j(_#ind,_x,_y,_z,_c) = scalar 14511 if (*ref==3) { // Image value (scalar): i/j(_#ind,_x,_y,_z,_c) = scalar
14509 - _cimg_mp_check_type(arg2,2,s_op,1,0); 14512 + _cimg_mp_check_type(arg2,2,1,0);
  14513 + is_parallelizable = false;
14510 p1 = ref[1]; // Index 14514 p1 = ref[1]; // Index
14511 is_relative = (bool)ref[2]; 14515 is_relative = (bool)ref[2];
14512 arg3 = ref[3]; // X 14516 arg3 = ref[3]; // X
@@ -14527,7 +14531,8 @@ namespace cimg_library_suffixed { @@ -14527,7 +14531,8 @@ namespace cimg_library_suffixed {
14527 } 14531 }
14528 14532
14529 if (*ref==4) { // Image value (vector): I/J[_#ind,off] = value 14533 if (*ref==4) { // Image value (vector): I/J[_#ind,off] = value
14530 - _cimg_mp_check_type(arg2,2,s_op,3,_cimg_mp_vector_size(arg1)); 14534 + _cimg_mp_check_type(arg2,2,3,_cimg_mp_vector_size(arg1));
  14535 + is_parallelizable = false;
14531 p1 = ref[1]; // Index 14536 p1 = ref[1]; // Index
14532 is_relative = (bool)ref[2]; 14537 is_relative = (bool)ref[2];
14533 arg3 = ref[3]; // Offset 14538 arg3 = ref[3]; // Offset
@@ -14553,7 +14558,8 @@ namespace cimg_library_suffixed { @@ -14553,7 +14558,8 @@ namespace cimg_library_suffixed {
14553 } 14558 }
14554 14559
14555 if (*ref==5) { // Image value (vector): I/J(_#ind,_x,_y,_z,_c) = value 14560 if (*ref==5) { // Image value (vector): I/J(_#ind,_x,_y,_z,_c) = value
14556 - _cimg_mp_check_type(arg2,2,s_op,3,_cimg_mp_vector_size(arg1)); 14561 + _cimg_mp_check_type(arg2,2,3,_cimg_mp_vector_size(arg1));
  14562 + is_parallelizable = false;
14557 p1 = ref[1]; // Index 14563 p1 = ref[1]; // Index
14558 is_relative = (bool)ref[2]; 14564 is_relative = (bool)ref[2];
14559 arg3 = ref[3]; // X 14565 arg3 = ref[3]; // X
@@ -14581,7 +14587,7 @@ namespace cimg_library_suffixed { @@ -14581,7 +14587,7 @@ namespace cimg_library_suffixed {
14581 } 14587 }
14582 14588
14583 if (_cimg_mp_is_vector(arg1)) { // Vector variable: V = value 14589 if (_cimg_mp_is_vector(arg1)) { // Vector variable: V = value
14584 - _cimg_mp_check_type(arg2,2,s_op,1,0); 14590 + _cimg_mp_check_type(arg2,2,1,0);
14585 if (_cimg_mp_is_vector(arg2)) // From vector 14591 if (_cimg_mp_is_vector(arg2)) // From vector
14586 CImg<uptrT>::vector((uptrT)mp_vector_copy,arg1,arg2,(uptrT)_cimg_mp_vector_size(arg1)). 14592 CImg<uptrT>::vector((uptrT)mp_vector_copy,arg1,arg2,(uptrT)_cimg_mp_vector_size(arg1)).
14587 move_to(code); 14593 move_to(code);
@@ -14592,7 +14598,7 @@ namespace cimg_library_suffixed { @@ -14592,7 +14598,7 @@ namespace cimg_library_suffixed {
14592 } 14598 }
14593 14599
14594 if (_cimg_mp_is_variable(arg1)) { // Scalar variable: s = scalar 14600 if (_cimg_mp_is_variable(arg1)) { // Scalar variable: s = scalar
14595 - _cimg_mp_check_type(arg2,2,s_op,1,0); 14601 + _cimg_mp_check_type(arg2,2,1,0);
14596 CImg<uptrT>::vector((uptrT)mp_copy,arg1,arg2).move_to(code); 14602 CImg<uptrT>::vector((uptrT)mp_copy,arg1,arg2).move_to(code);
14597 _cimg_mp_return(arg1); 14603 _cimg_mp_return(arg1);
14598 14604
@@ -14615,28 +14621,28 @@ namespace cimg_library_suffixed { @@ -14615,28 +14621,28 @@ namespace cimg_library_suffixed {
14615 for (s = se2, ps = se3, ns = ps - 1; s>ss1; --s, --ps, --ns) // Here, ns = ps - 1 14621 for (s = se2, ps = se3, ns = ps - 1; s>ss1; --s, --ps, --ns) // Here, ns = ps - 1
14616 if (*s=='=' && (*ps=='*' || *ps=='/' || *ps=='^') && *ns==*ps && 14622 if (*s=='=' && (*ps=='*' || *ps=='/' || *ps=='^') && *ns==*ps &&
14617 level[s - expr._data]==clevel) { // Self-operators for complex numbers only (**=,//=,^^=) 14623 level[s - expr._data]==clevel) { // Self-operators for complex numbers only (**=,//=,^^=)
14618 - s_op = *ps=='*'?"Operator '**='":*ps=='/'?"Operator '//='":"Operator '^^='"; 14624 + _cimg_mp_op(*ps=='*'?"Operator '**='":*ps=='/'?"Operator '//='":"Operator '^^='");
14619 14625
14620 ref.assign(7); 14626 ref.assign(7);
14621 arg1 = compile(ss,ns,depth1,ref); // Vector slot 14627 arg1 = compile(ss,ns,depth1,ref); // Vector slot
14622 arg2 = compile(s + 1,se,depth1,0); // Right operand 14628 arg2 = compile(s + 1,se,depth1,0); // Right operand
14623 if (*ps!='*') { 14629 if (*ps!='*') {
14624 - _cimg_mp_check_type(arg1,2,s_op,2,2);  
14625 - _cimg_mp_check_type(arg2,2,s_op,2,2); 14630 + _cimg_mp_check_type(arg1,2,2,2);
  14631 + _cimg_mp_check_type(arg2,2,2,2);
14626 } 14632 }
14627 if (_cimg_mp_is_vector(arg2)) { // Complex **= complex or Matrix **= matrix 14633 if (_cimg_mp_is_vector(arg2)) { // Complex **= complex or Matrix **= matrix
14628 if (*ps=='*') { 14634 if (*ps=='*') {
14629 if (_cimg_mp_vector_size(arg1)==2 && _cimg_mp_vector_size(arg2)==2) 14635 if (_cimg_mp_vector_size(arg1)==2 && _cimg_mp_vector_size(arg2)==2)
14630 CImg<uptrT>::vector((uptrT)mp_complex_mul,arg1,arg1,arg2).move_to(code); 14636 CImg<uptrT>::vector((uptrT)mp_complex_mul,arg1,arg1,arg2).move_to(code);
14631 else { 14637 else {
14632 - _cimg_mp_check_matrix_square(arg2,2,s_op); 14638 + _cimg_mp_check_matrix_square(arg2,2);
14633 p3 = _cimg_mp_vector_size(arg1); 14639 p3 = _cimg_mp_vector_size(arg1);
14634 p2 = (unsigned int)std::sqrt((float)_cimg_mp_vector_size(arg2)); 14640 p2 = (unsigned int)std::sqrt((float)_cimg_mp_vector_size(arg2));
14635 p1 = p3/p2; 14641 p1 = p3/p2;
14636 if (p1*p2!=p3) { 14642 if (p1*p2!=p3) {
14637 *se = saved_char; cimg::strellipsize(expr,64); 14643 *se = saved_char; cimg::strellipsize(expr,64);
14638 throw CImgArgumentException("[_cimg_math_parser] " 14644 throw CImgArgumentException("[_cimg_math_parser] "
14639 - "CImg<%s>::%s: %s: Sizes of left-hand and right-hand operands " 14645 + "CImg<%s>::%s: %s: Types of left-hand and right-hand operands "
14640 "('%s' and '%s') do not match, in expression '%s%s%s'.", 14646 "('%s' and '%s') do not match, in expression '%s%s%s'.",
14641 pixel_type(),_cimg_mp_calling_function,s_op, 14647 pixel_type(),_cimg_mp_calling_function,s_op,
14642 s_type(arg1)._data,s_type(arg2)._data, 14648 s_type(arg1)._data,s_type(arg2)._data,
@@ -14651,16 +14657,14 @@ namespace cimg_library_suffixed { @@ -14651,16 +14657,14 @@ namespace cimg_library_suffixed {
14651 else 14657 else
14652 CImg<uptrT>::vector((uptrT)mp_complex_pow_vv,arg1,arg1,arg2).move_to(code); 14658 CImg<uptrT>::vector((uptrT)mp_complex_pow_vv,arg1,arg1,arg2).move_to(code);
14653 } else { // Complex **= scalar 14659 } else { // Complex **= scalar
14654 - if (*ps=='*')  
14655 - CImg<uptrT>::vector((uptrT)mp_self_map_vector_s,arg1,2,(uptrT)mp_self_mul,arg2).move_to(code);  
14656 - else if (*ps=='/')  
14657 - CImg<uptrT>::vector((uptrT)mp_self_map_vector_s,arg1,2,(uptrT)mp_self_div,arg2).move_to(code);  
14658 - else  
14659 - CImg<uptrT>::vector((uptrT)mp_complex_pow_vs,arg1,arg1,arg2).move_to(code); 14660 + if (*ps=='*') self_vector_s(arg1,mp_self_mul,arg2);
  14661 + else if (*ps=='/') self_vector_s(arg1,mp_self_div,arg2);
  14662 + else CImg<uptrT>::vector((uptrT)mp_complex_pow_vs,arg1,arg1,arg2).move_to(code);
14660 } 14663 }
14661 14664
14662 // Write computed value back in image if necessary. 14665 // Write computed value back in image if necessary.
14663 if (*ref==4) { // Image value (vector): I/J[_#ind,off] **= value 14666 if (*ref==4) { // Image value (vector): I/J[_#ind,off] **= value
  14667 + is_parallelizable = false;
14664 p1 = ref[1]; // Index 14668 p1 = ref[1]; // Index
14665 is_relative = (bool)ref[2]; 14669 is_relative = (bool)ref[2];
14666 arg3 = ref[3]; // Offset 14670 arg3 = ref[3]; // Offset
@@ -14676,6 +14680,7 @@ namespace cimg_library_suffixed { @@ -14676,6 +14680,7 @@ namespace cimg_library_suffixed {
14676 } 14680 }
14677 14681
14678 } else if (*ref==5) { // Image value (vector): I/J(_#ind,_x,_y,_z,_c) **= value 14682 } else if (*ref==5) { // Image value (vector): I/J(_#ind,_x,_y,_z,_c) **= value
  14683 + is_parallelizable = false;
14679 p1 = ref[1]; // Index 14684 p1 = ref[1]; // Index
14680 is_relative = (bool)ref[2]; 14685 is_relative = (bool)ref[2];
14681 arg3 = ref[3]; // X 14686 arg3 = ref[3]; // X
@@ -14702,16 +14707,16 @@ namespace cimg_library_suffixed { @@ -14702,16 +14707,16 @@ namespace cimg_library_suffixed {
14702 (*ps=='>' && *ns=='>') || (*ps=='<' && *ns=='<')) && 14707 (*ps=='>' && *ns=='>') || (*ps=='<' && *ns=='<')) &&
14703 level[s - expr._data]==clevel) { // Self-operators (+=,-=,*=,/=,%=,>>=,<<=,&=,^=,|=) 14708 level[s - expr._data]==clevel) { // Self-operators (+=,-=,*=,/=,%=,>>=,<<=,&=,^=,|=)
14704 switch (*ps) { 14709 switch (*ps) {
14705 - case '+' : op = mp_self_add; s_op = "Operator '+='"; break;  
14706 - case '-' : op = mp_self_sub; s_op = "Operator '-='"; break;  
14707 - case '*' : op = mp_self_mul; s_op = "Operator '*='"; break;  
14708 - case '/' : op = mp_self_div; s_op = "Operator '/='"; break;  
14709 - case '%' : op = mp_self_modulo; s_op = "Operator '%='"; break;  
14710 - case '<' : op = mp_self_bitwise_left_shift; s_op = "Operator '<<='"; break;  
14711 - case '>' : op = mp_self_bitwise_right_shift; s_op = "Operator '>=='"; break;  
14712 - case '&' : op = mp_self_bitwise_and; s_op = "Operator '&='"; break;  
14713 - case '|' : op = mp_self_bitwise_or; s_op = "Operator '|='"; break;  
14714 - default : op = mp_self_pow; s_op = "Operator '^='"; break; 14710 + case '+' : op = mp_self_add; _cimg_mp_op("Operator '+='"); break;
  14711 + case '-' : op = mp_self_sub; _cimg_mp_op("Operator '-='"); break;
  14712 + case '*' : op = mp_self_mul; _cimg_mp_op("Operator '*='"); break;
  14713 + case '/' : op = mp_self_div; _cimg_mp_op("Operator '/='"); break;
  14714 + case '%' : op = mp_self_modulo; _cimg_mp_op("Operator '%='"); break;
  14715 + case '<' : op = mp_self_bitwise_left_shift; _cimg_mp_op("Operator '<<='"); break;
  14716 + case '>' : op = mp_self_bitwise_right_shift; _cimg_mp_op("Operator '>=='"); break;
  14717 + case '&' : op = mp_self_bitwise_and; _cimg_mp_op("Operator '&='"); break;
  14718 + case '|' : op = mp_self_bitwise_or; _cimg_mp_op("Operator '|='"); break;
  14719 + default : op = mp_self_pow; _cimg_mp_op("Operator '^='"); break;
14715 } 14720 }
14716 s1 = *ps=='>' || *ps=='<'?ns:ps; 14721 s1 = *ps=='>' || *ps=='<'?ns:ps;
14717 14722
@@ -14725,7 +14730,7 @@ namespace cimg_library_suffixed { @@ -14725,7 +14730,7 @@ namespace cimg_library_suffixed {
14725 } 14730 }
14726 14731
14727 if (*ref==1) { // Vector value (scalar): V[k] += scalar 14732 if (*ref==1) { // Vector value (scalar): V[k] += scalar
14728 - _cimg_mp_check_type(arg2,2,s_op,1,0); 14733 + _cimg_mp_check_type(arg2,2,1,0);
14729 arg3 = ref[1]; // Vector slot 14734 arg3 = ref[1]; // Vector slot
14730 arg4 = ref[2]; // Index 14735 arg4 = ref[2]; // Index
14731 if (p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int)); 14736 if (p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int));
@@ -14736,7 +14741,8 @@ namespace cimg_library_suffixed { @@ -14736,7 +14741,8 @@ namespace cimg_library_suffixed {
14736 } 14741 }
14737 14742
14738 if (*ref==2) { // Image value (scalar): i/j[_#ind,off] += scalar 14743 if (*ref==2) { // Image value (scalar): i/j[_#ind,off] += scalar
14739 - _cimg_mp_check_type(arg2,2,s_op,1,0); 14744 + _cimg_mp_check_type(arg2,2,1,0);
  14745 + is_parallelizable = false;
14740 p1 = ref[1]; // Index 14746 p1 = ref[1]; // Index
14741 is_relative = (bool)ref[2]; 14747 is_relative = (bool)ref[2];
14742 arg3 = ref[3]; // Offset 14748 arg3 = ref[3]; // Offset
@@ -14755,7 +14761,8 @@ namespace cimg_library_suffixed { @@ -14755,7 +14761,8 @@ namespace cimg_library_suffixed {
14755 } 14761 }
14756 14762
14757 if (*ref==3) { // Image value (scalar): i/j(_#ind,_x,_y,_z,_c) += scalar 14763 if (*ref==3) { // Image value (scalar): i/j(_#ind,_x,_y,_z,_c) += scalar
14758 - _cimg_mp_check_type(arg2,2,s_op,1,0); 14764 + _cimg_mp_check_type(arg2,2,1,0);
  14765 + is_parallelizable = false;
14759 p1 = ref[1]; // Index 14766 p1 = ref[1]; // Index
14760 is_relative = (bool)ref[2]; 14767 is_relative = (bool)ref[2];
14761 arg3 = ref[3]; // X 14768 arg3 = ref[3]; // X
@@ -14777,17 +14784,13 @@ namespace cimg_library_suffixed { @@ -14777,17 +14784,13 @@ namespace cimg_library_suffixed {
14777 } 14784 }
14778 14785
14779 if (*ref==4) { // Image value (vector): I/J[_#ind,off] += value 14786 if (*ref==4) { // Image value (vector): I/J[_#ind,off] += value
14780 - _cimg_mp_check_type(arg2,2,s_op,3,_cimg_mp_vector_size(arg1)); 14787 + _cimg_mp_check_type(arg2,2,3,_cimg_mp_vector_size(arg1));
  14788 + is_parallelizable = false;
14781 p1 = ref[1]; // Index 14789 p1 = ref[1]; // Index
14782 is_relative = (bool)ref[2]; 14790 is_relative = (bool)ref[2];
14783 arg3 = ref[3]; // Offset 14791 arg3 = ref[3]; // Offset
14784 if (p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int)); 14792 if (p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int));
14785 - if (_cimg_mp_is_scalar(arg2))  
14786 - CImg<uptrT>::vector((uptrT)mp_self_map_vector_s,arg1,(uptrT)_cimg_mp_vector_size(arg1),(uptrT)op,arg2).  
14787 - move_to(code);  
14788 - else  
14789 - CImg<uptrT>::vector((uptrT)mp_self_map_vector_v,arg1,(uptrT)_cimg_mp_vector_size(arg1),(uptrT)op,arg2).  
14790 - move_to(code); 14793 + if (_cimg_mp_is_scalar(arg2)) self_vector_s(arg1,op,arg2); else self_vector_v(arg1,op,arg2);
14791 if (p1!=~0U) { 14794 if (p1!=~0U) {
14792 if (!listout) _cimg_mp_return(arg1); 14795 if (!listout) _cimg_mp_return(arg1);
14793 CImg<uptrT>::vector((uptrT)(is_relative?mp_list_set_Joff_v:mp_list_set_Ioff_v), 14796 CImg<uptrT>::vector((uptrT)(is_relative?mp_list_set_Joff_v:mp_list_set_Ioff_v),
@@ -14800,20 +14803,16 @@ namespace cimg_library_suffixed { @@ -14800,20 +14803,16 @@ namespace cimg_library_suffixed {
14800 _cimg_mp_return(arg1); 14803 _cimg_mp_return(arg1);
14801 } 14804 }
14802 14805
14803 - if (*ref==5) { // Image value (vector): I/J(_#ind,_x,_y,_z,_c) = value  
14804 - _cimg_mp_check_type(arg2,2,s_op,3,_cimg_mp_vector_size(arg1)); 14806 + if (*ref==5) { // Image value (vector): I/J(_#ind,_x,_y,_z,_c) += value
  14807 + _cimg_mp_check_type(arg2,2,3,_cimg_mp_vector_size(arg1));
  14808 + is_parallelizable = false;
14805 p1 = ref[1]; // Index 14809 p1 = ref[1]; // Index
14806 is_relative = (bool)ref[2]; 14810 is_relative = (bool)ref[2];
14807 arg3 = ref[3]; // X 14811 arg3 = ref[3]; // X
14808 arg4 = ref[4]; // Y 14812 arg4 = ref[4]; // Y
14809 arg5 = ref[5]; // Z 14813 arg5 = ref[5]; // Z
14810 if (p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int)); 14814 if (p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int));
14811 - if (_cimg_mp_is_scalar(arg2))  
14812 - CImg<uptrT>::vector((uptrT)mp_self_map_vector_s,arg1,(uptrT)_cimg_mp_vector_size(arg1),(uptrT)op,arg2).  
14813 - move_to(code);  
14814 - else  
14815 - CImg<uptrT>::vector((uptrT)mp_self_map_vector_v,arg1,(uptrT)_cimg_mp_vector_size(arg1),(uptrT)op,arg2).  
14816 - move_to(code); 14815 + if (_cimg_mp_is_scalar(arg2)) self_vector_s(arg1,op,arg2); else self_vector_v(arg1,op,arg2);
14817 if (p1!=~0U) { 14816 if (p1!=~0U) {
14818 if (!listout) _cimg_mp_return(arg1); 14817 if (!listout) _cimg_mp_return(arg1);
14819 CImg<uptrT>::vector((uptrT)(is_relative?mp_list_set_Jxyz_v:mp_list_set_Ixyz_v), 14818 CImg<uptrT>::vector((uptrT)(is_relative?mp_list_set_Jxyz_v:mp_list_set_Ixyz_v),
@@ -14827,18 +14826,14 @@ namespace cimg_library_suffixed { @@ -14827,18 +14826,14 @@ namespace cimg_library_suffixed {
14827 } 14826 }
14828 14827
14829 if (_cimg_mp_is_vector(arg1)) { // Vector variable: V += value 14828 if (_cimg_mp_is_vector(arg1)) { // Vector variable: V += value
14830 - _cimg_mp_check_type(arg2,2,s_op,3,_cimg_mp_vector_size(arg1));  
14831 - if (_cimg_mp_is_vector(arg2)) // Vector += vector  
14832 - CImg<uptrT>::vector((uptrT)mp_self_map_vector_v,arg1,(uptrT)_cimg_mp_vector_size(arg1),(uptrT)op,arg2).  
14833 - move_to(code);  
14834 - else // Vector += scalar  
14835 - CImg<uptrT>::vector((uptrT)mp_self_map_vector_s,arg1,(uptrT)_cimg_mp_vector_size(arg1),(uptrT)op,arg2).  
14836 - move_to(code); 14829 + _cimg_mp_check_type(arg2,2,3,_cimg_mp_vector_size(arg1));
  14830 + if (_cimg_mp_is_vector(arg2)) self_vector_v(arg1,op,arg2); // Vector += vector
  14831 + else self_vector_s(arg1,op,arg2); // Vector += scalar
14837 _cimg_mp_return(arg1); 14832 _cimg_mp_return(arg1);
14838 } 14833 }
14839 14834
14840 if (_cimg_mp_is_variable(arg1)) { // Scalar variable: s += scalar 14835 if (_cimg_mp_is_variable(arg1)) { // Scalar variable: s += scalar
14841 - _cimg_mp_check_type(arg2,2,s_op,1,0); 14836 + _cimg_mp_check_type(arg2,2,1,0);
14842 CImg<uptrT>::vector((uptrT)op,arg1,arg2).move_to(code); 14837 CImg<uptrT>::vector((uptrT)op,arg1,arg2).move_to(code);
14843 _cimg_mp_return(arg1); 14838 _cimg_mp_return(arg1);
14844 } 14839 }
@@ -14857,17 +14852,19 @@ namespace cimg_library_suffixed { @@ -14857,17 +14852,19 @@ namespace cimg_library_suffixed {
14857 14852
14858 for (s = ss1; s<se1; ++s) 14853 for (s = ss1; s<se1; ++s)
14859 if (*s=='?' && level[s - expr._data]==clevel) { // Ternary operator 'cond?expr1:expr2' 14854 if (*s=='?' && level[s - expr._data]==clevel) { // Ternary operator 'cond?expr1:expr2'
14860 - s_op = "Operator '?:'"; 14855 + _cimg_mp_op("Operator '?:'");
14861 s1 = s + 1; while (s1<se1 && (*s1!=':' || level[s1 - expr._data]!=clevel)) ++s1; 14856 s1 = s + 1; while (s1<se1 && (*s1!=':' || level[s1 - expr._data]!=clevel)) ++s1;
14862 arg1 = compile(ss,s,depth1,0); 14857 arg1 = compile(ss,s,depth1,0);
  14858 + _cimg_mp_check_type(arg1,1,1,0);
  14859 + if (_cimg_mp_is_constant(arg1)) {
  14860 + if ((bool)mem[arg1]) return compile(s + 1,*s1!=':'?se:s1,depth1,0);
  14861 + else return *s1!=':'?0:compile(++s1,se,depth1,0);
  14862 + }
14863 p2 = code._width; 14863 p2 = code._width;
14864 arg2 = compile(s + 1,*s1!=':'?se:s1,depth1,0); 14864 arg2 = compile(s + 1,*s1!=':'?se:s1,depth1,0);
14865 p3 = code._width; 14865 p3 = code._width;
14866 - arg3 = *s1!=':'?0:compile(s1 + 1,se,depth1,0);  
14867 - _cimg_mp_check_type(arg1,1,s_op,1,0);  
14868 - _cimg_mp_check_type(arg3,3,s_op,_cimg_mp_is_vector(arg2)?2:1,_cimg_mp_vector_size(arg2));  
14869 - if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2) && _cimg_mp_is_constant(arg3))  
14870 - _cimg_mp_constant(mem[arg1]?mem[arg2]:mem[arg3]); 14866 + arg3 = *s1==':'?compile(++s1,se,depth1,0):_cimg_mp_is_vector(arg2)?vector(_cimg_mp_vector_size(arg2),0):0;
  14867 + _cimg_mp_check_type(arg3,3,_cimg_mp_is_vector(arg2)?2:1,_cimg_mp_vector_size(arg2));
14871 arg4 = _cimg_mp_is_vector(arg2)?_cimg_mp_vector_size(arg2):0; // Output vector size (or 0 if scalar) 14868 arg4 = _cimg_mp_is_vector(arg2)?_cimg_mp_vector_size(arg2):0; // Output vector size (or 0 if scalar)
14872 if (arg4) pos = vector(arg4); else pos = scalar(); 14869 if (arg4) pos = vector(arg4); else pos = scalar();
14873 CImg<uptrT>::vector((uptrT)mp_if,pos,arg1,arg2,arg3, 14870 CImg<uptrT>::vector((uptrT)mp_if,pos,arg1,arg2,arg3,
@@ -14877,12 +14874,12 @@ namespace cimg_library_suffixed { @@ -14877,12 +14874,12 @@ namespace cimg_library_suffixed {
14877 14874
14878 for (s = se3, ns = se2; s>ss; --s, --ns) 14875 for (s = se3, ns = se2; s>ss; --s, --ns)
14879 if (*s=='|' && *ns=='|' && level[s - expr._data]==clevel) { // Logical or ('||') 14876 if (*s=='|' && *ns=='|' && level[s - expr._data]==clevel) { // Logical or ('||')
14880 - s_op = "Operator '||'"; 14877 + _cimg_mp_op("Operator '||'");
14881 arg1 = compile(ss,s,depth1,0); 14878 arg1 = compile(ss,s,depth1,0);
14882 p2 = code._width; 14879 p2 = code._width;
14883 arg2 = compile(s + 2,se,depth1,0); 14880 arg2 = compile(s + 2,se,depth1,0);
14884 - _cimg_mp_check_type(arg1,1,s_op,1,0);  
14885 - _cimg_mp_check_type(arg2,2,s_op,1,0); 14881 + _cimg_mp_check_type(arg1,1,1,0);
  14882 + _cimg_mp_check_type(arg2,2,1,0);
14886 if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) 14883 if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2))
14887 _cimg_mp_constant(mem[arg1] || mem[arg2]); 14884 _cimg_mp_constant(mem[arg1] || mem[arg2]);
14888 pos = scalar(); 14885 pos = scalar();
@@ -14893,12 +14890,12 @@ namespace cimg_library_suffixed { @@ -14893,12 +14890,12 @@ namespace cimg_library_suffixed {
14893 14890
14894 for (s = se3, ns = se2; s>ss; --s, --ns) 14891 for (s = se3, ns = se2; s>ss; --s, --ns)
14895 if (*s=='&' && *ns=='&' && level[s - expr._data]==clevel) { // Logical and ('&&') 14892 if (*s=='&' && *ns=='&' && level[s - expr._data]==clevel) { // Logical and ('&&')
14896 - s_op = "Operator '&&'"; 14893 + _cimg_mp_op("Operator '&&'");
14897 arg1 = compile(ss,s,depth1,0); 14894 arg1 = compile(ss,s,depth1,0);
14898 p2 = code._width; 14895 p2 = code._width;
14899 arg2 = compile(s + 2,se,depth1,0); 14896 arg2 = compile(s + 2,se,depth1,0);
14900 - _cimg_mp_check_type(arg1,1,s_op,1,0);  
14901 - _cimg_mp_check_type(arg2,2,s_op,1,0); 14897 + _cimg_mp_check_type(arg1,1,1,0);
  14898 + _cimg_mp_check_type(arg2,2,1,0);
14902 if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) 14899 if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2))
14903 _cimg_mp_constant(mem[arg1] && mem[arg2]); 14900 _cimg_mp_constant(mem[arg1] && mem[arg2]);
14904 pos = scalar(); 14901 pos = scalar();
@@ -14909,9 +14906,10 @@ namespace cimg_library_suffixed { @@ -14909,9 +14906,10 @@ namespace cimg_library_suffixed {
14909 14906
14910 for (s = se2; s>ss; --s) 14907 for (s = se2; s>ss; --s)
14911 if (*s=='|' && level[s - expr._data]==clevel) { // Bitwise or ('|') 14908 if (*s=='|' && level[s - expr._data]==clevel) { // Bitwise or ('|')
  14909 + _cimg_mp_op("Operator '|'");
14912 arg1 = compile(ss,s,depth1,0); 14910 arg1 = compile(ss,s,depth1,0);
14913 arg2 = compile(s + 1,se,depth1,0); 14911 arg2 = compile(s + 1,se,depth1,0);
14914 - _cimg_mp_check_type(arg2,2,"operator '|'",3,_cimg_mp_vector_size(arg1)); 14912 + _cimg_mp_check_type(arg2,2,3,_cimg_mp_vector_size(arg1));
14915 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_bitwise_or,arg1,arg2); 14913 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_bitwise_or,arg1,arg2);
14916 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_bitwise_or,arg1,arg2); 14914 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_bitwise_or,arg1,arg2);
14917 if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_bitwise_or,arg1,arg2); 14915 if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_bitwise_or,arg1,arg2);
@@ -14922,9 +14920,10 @@ namespace cimg_library_suffixed { @@ -14922,9 +14920,10 @@ namespace cimg_library_suffixed {
14922 14920
14923 for (s = se2; s>ss; --s) 14921 for (s = se2; s>ss; --s)
14924 if (*s=='&' && level[s - expr._data]==clevel) { // Bitwise and ('&') 14922 if (*s=='&' && level[s - expr._data]==clevel) { // Bitwise and ('&')
  14923 + _cimg_mp_op("Operator '&'");
14925 arg1 = compile(ss,s,depth1,0); 14924 arg1 = compile(ss,s,depth1,0);
14926 arg2 = compile(s + 1,se,depth1,0); 14925 arg2 = compile(s + 1,se,depth1,0);
14927 - _cimg_mp_check_type(arg2,2,"operator '&'",3,_cimg_mp_vector_size(arg1)); 14926 + _cimg_mp_check_type(arg2,2,3,_cimg_mp_vector_size(arg1));
14928 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_bitwise_and,arg1,arg2); 14927 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_bitwise_and,arg1,arg2);
14929 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_bitwise_and,arg1,arg2); 14928 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_bitwise_and,arg1,arg2);
14930 if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_bitwise_and,arg1,arg2); 14929 if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_bitwise_and,arg1,arg2);
@@ -14935,9 +14934,10 @@ namespace cimg_library_suffixed { @@ -14935,9 +14934,10 @@ namespace cimg_library_suffixed {
14935 14934
14936 for (s = se3, ns = se2; s>ss; --s, --ns) 14935 for (s = se3, ns = se2; s>ss; --s, --ns)
14937 if (*s=='!' && *ns=='=' && level[s - expr._data]==clevel) { // Not equal to ('!=') 14936 if (*s=='!' && *ns=='=' && level[s - expr._data]==clevel) { // Not equal to ('!=')
  14937 + _cimg_mp_op("Operator '!='");
14938 arg1 = compile(ss,s,depth1,0); 14938 arg1 = compile(ss,s,depth1,0);
14939 arg2 = compile(s + 2,se,depth1,0); 14939 arg2 = compile(s + 2,se,depth1,0);
14940 - _cimg_mp_check_type(arg2,2,"operator '!='",3,_cimg_mp_vector_size(arg1)); 14940 + _cimg_mp_check_type(arg2,2,3,_cimg_mp_vector_size(arg1));
14941 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_neq,arg1,arg2); 14941 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_neq,arg1,arg2);
14942 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_neq,arg1,arg2); 14942 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_neq,arg1,arg2);
14943 if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_neq,arg1,arg2); 14943 if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_neq,arg1,arg2);
@@ -14947,9 +14947,10 @@ namespace cimg_library_suffixed { @@ -14947,9 +14947,10 @@ namespace cimg_library_suffixed {
14947 14947
14948 for (s = se3, ns = se2; s>ss; --s, --ns) 14948 for (s = se3, ns = se2; s>ss; --s, --ns)
14949 if (*s=='=' && *ns=='=' && level[s - expr._data]==clevel) { // Equal to ('==') 14949 if (*s=='=' && *ns=='=' && level[s - expr._data]==clevel) { // Equal to ('==')
  14950 + _cimg_mp_op("Operator '=='");
14950 arg1 = compile(ss,s,depth1,0); 14951 arg1 = compile(ss,s,depth1,0);
14951 arg2 = compile(s + 2,se,depth1,0); 14952 arg2 = compile(s + 2,se,depth1,0);
14952 - _cimg_mp_check_type(arg2,2,"operator '=='",3,_cimg_mp_vector_size(arg1)); 14953 + _cimg_mp_check_type(arg2,2,3,_cimg_mp_vector_size(arg1));
14953 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_eq,arg1,arg2); 14954 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_eq,arg1,arg2);
14954 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_eq,arg1,arg2); 14955 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_eq,arg1,arg2);
14955 if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_eq,arg1,arg2); 14956 if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_eq,arg1,arg2);
@@ -14959,9 +14960,10 @@ namespace cimg_library_suffixed { @@ -14959,9 +14960,10 @@ namespace cimg_library_suffixed {
14959 14960
14960 for (s = se3, ns = se2; s>ss; --s, --ns) 14961 for (s = se3, ns = se2; s>ss; --s, --ns)
14961 if (*s=='<' && *ns=='=' && level[s - expr._data]==clevel) { // Less or equal than ('<=') 14962 if (*s=='<' && *ns=='=' && level[s - expr._data]==clevel) { // Less or equal than ('<=')
  14963 + _cimg_mp_op("Operator '<='");
14962 arg1 = compile(ss,s,depth1,0); 14964 arg1 = compile(ss,s,depth1,0);
14963 arg2 = compile(s + 2,se,depth1,0); 14965 arg2 = compile(s + 2,se,depth1,0);
14964 - _cimg_mp_check_type(arg2,2,"operator '<='",3,_cimg_mp_vector_size(arg1)); 14966 + _cimg_mp_check_type(arg2,2,3,_cimg_mp_vector_size(arg1));
14965 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_lte,arg1,arg2); 14967 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_lte,arg1,arg2);
14966 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_lte,arg1,arg2); 14968 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_lte,arg1,arg2);
14967 if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_lte,arg1,arg2); 14969 if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_lte,arg1,arg2);
@@ -14971,9 +14973,10 @@ namespace cimg_library_suffixed { @@ -14971,9 +14973,10 @@ namespace cimg_library_suffixed {
14971 14973
14972 for (s = se3, ns = se2; s>ss; --s, --ns) 14974 for (s = se3, ns = se2; s>ss; --s, --ns)
14973 if (*s=='>' && *ns=='=' && level[s - expr._data]==clevel) { // Greater or equal than ('>=') 14975 if (*s=='>' && *ns=='=' && level[s - expr._data]==clevel) { // Greater or equal than ('>=')
  14976 + _cimg_mp_op("Operator '>='");
14974 arg1 = compile(ss,s,depth1,0); 14977 arg1 = compile(ss,s,depth1,0);
14975 arg2 = compile(s + 2,se,depth1,0); 14978 arg2 = compile(s + 2,se,depth1,0);
14976 - _cimg_mp_check_type(arg2,2,"operator '>='",3,_cimg_mp_vector_size(arg1)); 14979 + _cimg_mp_check_type(arg2,2,3,_cimg_mp_vector_size(arg1));
14977 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_gte,arg1,arg2); 14980 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_gte,arg1,arg2);
14978 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_gte,arg1,arg2); 14981 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_gte,arg1,arg2);
14979 if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_gte,arg1,arg2); 14982 if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_gte,arg1,arg2);
@@ -14983,9 +14986,10 @@ namespace cimg_library_suffixed { @@ -14983,9 +14986,10 @@ namespace cimg_library_suffixed {
14983 14986
14984 for (s = se2, ns = se1, ps = se3; s>ss; --s, --ns, --ps) 14987 for (s = se2, ns = se1, ps = se3; s>ss; --s, --ns, --ps)
14985 if (*s=='<' && *ns!='<' && *ps!='<' && level[s - expr._data]==clevel) { // Less than ('<') 14988 if (*s=='<' && *ns!='<' && *ps!='<' && level[s - expr._data]==clevel) { // Less than ('<')
  14989 + _cimg_mp_op("Operator '<'");
14986 arg1 = compile(ss,s,depth1,0); 14990 arg1 = compile(ss,s,depth1,0);
14987 arg2 = compile(s + 1,se,depth1,0); 14991 arg2 = compile(s + 1,se,depth1,0);
14988 - _cimg_mp_check_type(arg2,2,"operator '<'",3,_cimg_mp_vector_size(arg1)); 14992 + _cimg_mp_check_type(arg2,2,3,_cimg_mp_vector_size(arg1));
14989 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_lt,arg1,arg2); 14993 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_lt,arg1,arg2);
14990 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_lt,arg1,arg2); 14994 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_lt,arg1,arg2);
14991 if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_lt,arg1,arg2); 14995 if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_lt,arg1,arg2);
@@ -14995,9 +14999,10 @@ namespace cimg_library_suffixed { @@ -14995,9 +14999,10 @@ namespace cimg_library_suffixed {
14995 14999
14996 for (s = se2, ns = se1, ps = se3; s>ss; --s, --ns, --ps) 15000 for (s = se2, ns = se1, ps = se3; s>ss; --s, --ns, --ps)
14997 if (*s=='>' && *ns!='>' && *ps!='>' && level[s - expr._data]==clevel) { // Greather than ('>') 15001 if (*s=='>' && *ns!='>' && *ps!='>' && level[s - expr._data]==clevel) { // Greather than ('>')
  15002 + _cimg_mp_op("Operator '>'");
14998 arg1 = compile(ss,s,depth1,0); 15003 arg1 = compile(ss,s,depth1,0);
14999 arg2 = compile(s + 1,se,depth1,0); 15004 arg2 = compile(s + 1,se,depth1,0);
15000 - _cimg_mp_check_type(arg2,2,"operator '>'",3,_cimg_mp_vector_size(arg1)); 15005 + _cimg_mp_check_type(arg2,2,3,_cimg_mp_vector_size(arg1));
15001 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_gt,arg1,arg2); 15006 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_gt,arg1,arg2);
15002 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_gt,arg1,arg2); 15007 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_gt,arg1,arg2);
15003 if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_gt,arg1,arg2); 15008 if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_gt,arg1,arg2);
@@ -15007,9 +15012,10 @@ namespace cimg_library_suffixed { @@ -15007,9 +15012,10 @@ namespace cimg_library_suffixed {
15007 15012
15008 for (s = se3, ns = se2; s>ss; --s, --ns) 15013 for (s = se3, ns = se2; s>ss; --s, --ns)
15009 if (*s=='<' && *ns=='<' && level[s - expr._data]==clevel) { // Left bit shift ('<<') 15014 if (*s=='<' && *ns=='<' && level[s - expr._data]==clevel) { // Left bit shift ('<<')
  15015 + _cimg_mp_op("Operator '<<'");
15010 arg1 = compile(ss,s,depth1,0); 15016 arg1 = compile(ss,s,depth1,0);
15011 arg2 = compile(s + 2,se,depth1,0); 15017 arg2 = compile(s + 2,se,depth1,0);
15012 - _cimg_mp_check_type(arg2,2,"operator '<<'",3,_cimg_mp_vector_size(arg1)); 15018 + _cimg_mp_check_type(arg2,2,3,_cimg_mp_vector_size(arg1));
15013 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) 15019 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2))
15014 _cimg_mp_vector2_vv(mp_bitwise_left_shift,arg1,arg2); 15020 _cimg_mp_vector2_vv(mp_bitwise_left_shift,arg1,arg2);
15015 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) 15021 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2))
@@ -15023,9 +15029,10 @@ namespace cimg_library_suffixed { @@ -15023,9 +15029,10 @@ namespace cimg_library_suffixed {
15023 15029
15024 for (s = se3, ns = se2; s>ss; --s, --ns) 15030 for (s = se3, ns = se2; s>ss; --s, --ns)
15025 if (*s=='>' && *ns=='>' && level[s - expr._data]==clevel) { // Right bit shift ('>>') 15031 if (*s=='>' && *ns=='>' && level[s - expr._data]==clevel) { // Right bit shift ('>>')
  15032 + _cimg_mp_op("Operator '>>'");
15026 arg1 = compile(ss,s,depth1,0); 15033 arg1 = compile(ss,s,depth1,0);
15027 arg2 = compile(s + 2,se,depth1,0); 15034 arg2 = compile(s + 2,se,depth1,0);
15028 - _cimg_mp_check_type(arg2,2,"operator '>>'",3,_cimg_mp_vector_size(arg1)); 15035 + _cimg_mp_check_type(arg2,2,3,_cimg_mp_vector_size(arg1));
15029 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) 15036 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2))
15030 _cimg_mp_vector2_vv(mp_bitwise_right_shift,arg1,arg2); 15037 _cimg_mp_vector2_vv(mp_bitwise_right_shift,arg1,arg2);
15031 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) 15038 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2))
@@ -15043,9 +15050,10 @@ namespace cimg_library_suffixed { @@ -15043,9 +15050,10 @@ namespace cimg_library_suffixed {
15043 (*ps!='e' || !(ps - pexpr._data>ss - expr._data && (*(ps - 1)=='.' || (*(ps - 1)>='0' && 15050 (*ps!='e' || !(ps - pexpr._data>ss - expr._data && (*(ps - 1)=='.' || (*(ps - 1)>='0' &&
15044 *(ps - 1)<='9')))) && 15051 *(ps - 1)<='9')))) &&
15045 level[s - expr._data]==clevel) { // Addition ('+') 15052 level[s - expr._data]==clevel) { // Addition ('+')
  15053 + _cimg_mp_op("Operator '+'");
15046 arg1 = compile(ss,s,depth1,0); 15054 arg1 = compile(ss,s,depth1,0);
15047 arg2 = compile(s + 1,se,depth1,0); 15055 arg2 = compile(s + 1,se,depth1,0);
15048 - _cimg_mp_check_type(arg2,2,"operator '+'",3,_cimg_mp_vector_size(arg1)); 15056 + _cimg_mp_check_type(arg2,2,3,_cimg_mp_vector_size(arg1));
15049 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_add,arg1,arg2); 15057 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_add,arg1,arg2);
15050 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_add,arg1,arg2); 15058 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_add,arg1,arg2);
15051 if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_add,arg1,arg2); 15059 if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_add,arg1,arg2);
@@ -15061,9 +15069,10 @@ namespace cimg_library_suffixed { @@ -15061,9 +15069,10 @@ namespace cimg_library_suffixed {
15061 (*ps!='e' || !(ps - pexpr._data>ss - expr._data && (*(ps - 1)=='.' || (*(ps - 1)>='0' && 15069 (*ps!='e' || !(ps - pexpr._data>ss - expr._data && (*(ps - 1)=='.' || (*(ps - 1)>='0' &&
15062 *(ps - 1)<='9')))) && 15070 *(ps - 1)<='9')))) &&
15063 level[s - expr._data]==clevel) { // Subtraction ('-') 15071 level[s - expr._data]==clevel) { // Subtraction ('-')
  15072 + _cimg_mp_op("Operator '-'");
15064 arg1 = compile(ss,s,depth1,0); 15073 arg1 = compile(ss,s,depth1,0);
15065 arg2 = compile(s + 1,se,depth1,0); 15074 arg2 = compile(s + 1,se,depth1,0);
15066 - _cimg_mp_check_type(arg2,2,"operator '-'",3,_cimg_mp_vector_size(arg1)); 15075 + _cimg_mp_check_type(arg2,2,3,_cimg_mp_vector_size(arg1));
15067 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_sub,arg1,arg2); 15076 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_sub,arg1,arg2);
15068 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_sub,arg1,arg2); 15077 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_sub,arg1,arg2);
15069 if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_sub,arg1,arg2); 15078 if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_sub,arg1,arg2);
@@ -15074,7 +15083,7 @@ namespace cimg_library_suffixed { @@ -15074,7 +15083,7 @@ namespace cimg_library_suffixed {
15074 15083
15075 for (s = se3, ns = se2; s>ss; --s, --ns) 15084 for (s = se3, ns = se2; s>ss; --s, --ns)
15076 if (*s=='*' && *ns=='*' && level[s - expr._data]==clevel) { // Complex/matrix multiplication ('**') 15085 if (*s=='*' && *ns=='*' && level[s - expr._data]==clevel) { // Complex/matrix multiplication ('**')
15077 - s_op = "Operator '**'"; 15086 + _cimg_mp_op("Operator '**'");
15078 arg1 = compile(ss,s,depth1,0); 15087 arg1 = compile(ss,s,depth1,0);
15079 arg2 = compile(s + 2,se,depth1,0); 15088 arg2 = compile(s + 2,se,depth1,0);
15080 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) { 15089 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) {
@@ -15089,7 +15098,7 @@ namespace cimg_library_suffixed { @@ -15089,7 +15098,7 @@ namespace cimg_library_suffixed {
15089 if (arg4*p2!=p1) { 15098 if (arg4*p2!=p1) {
15090 *se = saved_char; cimg::strellipsize(expr,64); 15099 *se = saved_char; cimg::strellipsize(expr,64);
15091 throw CImgArgumentException("[_cimg_math_parser] " 15100 throw CImgArgumentException("[_cimg_math_parser] "
15092 - "CImg<%s>::%s: %s: Sizes of left-hand and right-hand operands " 15101 + "CImg<%s>::%s: %s: Types of left-hand and right-hand operands "
15093 "('%s' and '%s') do not match, in expression '%s%s%s'.", 15102 "('%s' and '%s') do not match, in expression '%s%s%s'.",
15094 pixel_type(),_cimg_mp_calling_function,s_op, 15103 pixel_type(),_cimg_mp_calling_function,s_op,
15095 s_type(arg1)._data,s_type(arg2)._data, 15104 s_type(arg1)._data,s_type(arg2)._data,
@@ -15110,11 +15119,11 @@ namespace cimg_library_suffixed { @@ -15110,11 +15119,11 @@ namespace cimg_library_suffixed {
15110 15119
15111 for (s = se3, ns = se2; s>ss; --s, --ns) 15120 for (s = se3, ns = se2; s>ss; --s, --ns)
15112 if (*s=='/' && *ns=='/' && level[s - expr._data]==clevel) { // Complex division ('//') 15121 if (*s=='/' && *ns=='/' && level[s - expr._data]==clevel) { // Complex division ('//')
15113 - s_op = "Operator '//'"; 15122 + _cimg_mp_op("Operator '//'");
15114 arg1 = compile(ss,s,depth1,0); 15123 arg1 = compile(ss,s,depth1,0);
15115 arg2 = compile(s + 2,se,depth1,0); 15124 arg2 = compile(s + 2,se,depth1,0);
15116 - _cimg_mp_check_type(arg1,1,s_op,3,2);  
15117 - _cimg_mp_check_type(arg2,2,s_op,3,2); 15125 + _cimg_mp_check_type(arg1,1,3,2);
  15126 + _cimg_mp_check_type(arg2,2,3,2);
15118 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) { 15127 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) {
15119 pos = vector(2); 15128 pos = vector(2);
15120 CImg<uptrT>::vector((uptrT)mp_complex_div_vv,pos,arg1,arg2).move_to(code); 15129 CImg<uptrT>::vector((uptrT)mp_complex_div_vv,pos,arg1,arg2).move_to(code);
@@ -15131,9 +15140,10 @@ namespace cimg_library_suffixed { @@ -15131,9 +15140,10 @@ namespace cimg_library_suffixed {
15131 } 15140 }
15132 15141
15133 for (s = se2; s>ss; --s) if (*s=='*' && level[s - expr._data]==clevel) { // Multiplication ('*') 15142 for (s = se2; s>ss; --s) if (*s=='*' && level[s - expr._data]==clevel) { // Multiplication ('*')
  15143 + _cimg_mp_op("Operator '*'");
15134 arg1 = compile(ss,s,depth1,0); 15144 arg1 = compile(ss,s,depth1,0);
15135 arg2 = compile(s + 1,se,depth1,0); 15145 arg2 = compile(s + 1,se,depth1,0);
15136 - _cimg_mp_check_type(arg2,2,"operator '*'",3,_cimg_mp_vector_size(arg1)); 15146 + _cimg_mp_check_type(arg2,2,3,_cimg_mp_vector_size(arg1));
15137 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_mul,arg1,arg2); 15147 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_mul,arg1,arg2);
15138 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_mul,arg1,arg2); 15148 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_mul,arg1,arg2);
15139 if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_mul,arg1,arg2); 15149 if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_mul,arg1,arg2);
@@ -15143,9 +15153,10 @@ namespace cimg_library_suffixed { @@ -15143,9 +15153,10 @@ namespace cimg_library_suffixed {
15143 15153
15144 15154
15145 for (s = se2; s>ss; --s) if (*s=='/' && level[s - expr._data]==clevel) { // Division ('/') 15155 for (s = se2; s>ss; --s) if (*s=='/' && level[s - expr._data]==clevel) { // Division ('/')
  15156 + _cimg_mp_op("Operator '/'");
15146 arg1 = compile(ss,s,depth1,0); 15157 arg1 = compile(ss,s,depth1,0);
15147 arg2 = compile(s + 1,se,depth1,0); 15158 arg2 = compile(s + 1,se,depth1,0);
15148 - _cimg_mp_check_type(arg2,2,"operator '/'",3,_cimg_mp_vector_size(arg1)); 15159 + _cimg_mp_check_type(arg2,2,3,_cimg_mp_vector_size(arg1));
15149 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_div,arg1,arg2); 15160 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_div,arg1,arg2);
15150 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_div,arg1,arg2); 15161 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_div,arg1,arg2);
15151 if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_div,arg1,arg2); 15162 if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_div,arg1,arg2);
@@ -15155,9 +15166,10 @@ namespace cimg_library_suffixed { @@ -15155,9 +15166,10 @@ namespace cimg_library_suffixed {
15155 15166
15156 for (s = se2, ns = se1; s>ss; --s, --ns) 15167 for (s = se2, ns = se1; s>ss; --s, --ns)
15157 if (*s=='%' && *ns!='^' && level[s - expr._data]==clevel) { // Modulo ('%') 15168 if (*s=='%' && *ns!='^' && level[s - expr._data]==clevel) { // Modulo ('%')
  15169 + _cimg_mp_op("Operator '%'");
15158 arg1 = compile(ss,s,depth1,0); 15170 arg1 = compile(ss,s,depth1,0);
15159 arg2 = compile(s + 1,se,depth1,0); 15171 arg2 = compile(s + 1,se,depth1,0);
15160 - _cimg_mp_check_type(arg2,2,"operator '%'",3,_cimg_mp_vector_size(arg1)); 15172 + _cimg_mp_check_type(arg2,2,3,_cimg_mp_vector_size(arg1));
15161 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_modulo,arg1,arg2); 15173 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_modulo,arg1,arg2);
15162 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_modulo,arg1,arg2); 15174 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_modulo,arg1,arg2);
15163 if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_modulo,arg1,arg2); 15175 if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_modulo,arg1,arg2);
@@ -15167,10 +15179,13 @@ namespace cimg_library_suffixed { @@ -15167,10 +15179,13 @@ namespace cimg_library_suffixed {
15167 } 15179 }
15168 15180
15169 if (se1>ss) { 15181 if (se1>ss) {
15170 - if (*ss=='+' && (*ss1!='+' || (ss2<se && *ss2>='0' && *ss2<='9'))) // Unary plus ('+') 15182 + if (*ss=='+' && (*ss1!='+' || (ss2<se && *ss2>='0' && *ss2<='9'))) { // Unary plus ('+')
  15183 + _cimg_mp_op("Operator '+'");
15171 _cimg_mp_return(compile(ss1,se,depth1,0)); 15184 _cimg_mp_return(compile(ss1,se,depth1,0));
  15185 + }
15172 15186
15173 if (*ss=='-' && (*ss1!='-' || (ss2<se && *ss2>='0' && *ss2<='9'))) { // Unary minus ('-') 15187 if (*ss=='-' && (*ss1!='-' || (ss2<se && *ss2>='0' && *ss2<='9'))) { // Unary minus ('-')
  15188 + _cimg_mp_op("Operator '-'");
15174 arg1 = compile(ss1,se,depth1,0); 15189 arg1 = compile(ss1,se,depth1,0);
15175 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_minus,arg1); 15190 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_minus,arg1);
15176 if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(-mem[arg1]); 15191 if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(-mem[arg1]);
@@ -15178,6 +15193,7 @@ namespace cimg_library_suffixed { @@ -15178,6 +15193,7 @@ namespace cimg_library_suffixed {
15178 } 15193 }
15179 15194
15180 if (*ss=='!') { // Logical not ('!') 15195 if (*ss=='!') { // Logical not ('!')
  15196 + _cimg_mp_op("Operator '!'");
15181 arg1 = compile(ss1,se,depth1,0); 15197 arg1 = compile(ss1,se,depth1,0);
15182 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_logical_not,arg1); 15198 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_logical_not,arg1);
15183 if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(!mem[arg1]); 15199 if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(!mem[arg1]);
@@ -15185,6 +15201,7 @@ namespace cimg_library_suffixed { @@ -15185,6 +15201,7 @@ namespace cimg_library_suffixed {
15185 } 15201 }
15186 15202
15187 if (*ss=='~') { // Bitwise not ('~') 15203 if (*ss=='~') { // Bitwise not ('~')
  15204 + _cimg_mp_op("Operator '~'");
15188 arg1 = compile(ss1,se,depth1,0); 15205 arg1 = compile(ss1,se,depth1,0);
15189 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_bitwise_not,arg1); 15206 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_bitwise_not,arg1);
15190 if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(~(unsigned long)mem[arg1]); 15207 if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(~(unsigned long)mem[arg1]);
@@ -15194,11 +15211,11 @@ namespace cimg_library_suffixed { @@ -15194,11 +15211,11 @@ namespace cimg_library_suffixed {
15194 15211
15195 for (s = se3, ns = se2; s>ss; --s, --ns) 15212 for (s = se3, ns = se2; s>ss; --s, --ns)
15196 if (*s=='^' && *ns=='^' && level[s - expr._data]==clevel) { // Complex power ('^^') 15213 if (*s=='^' && *ns=='^' && level[s - expr._data]==clevel) { // Complex power ('^^')
15197 - s_op = "Operator '^^'"; 15214 + _cimg_mp_op("Operator '^^'");
15198 arg1 = compile(ss,s,depth1,0); 15215 arg1 = compile(ss,s,depth1,0);
15199 arg2 = compile(s + 2,se,depth1,0); 15216 arg2 = compile(s + 2,se,depth1,0);
15200 - _cimg_mp_check_type(arg1,1,s_op,3,2);  
15201 - _cimg_mp_check_type(arg2,2,s_op,3,2); 15217 + _cimg_mp_check_type(arg1,1,3,2);
  15218 + _cimg_mp_check_type(arg2,2,3,2);
15202 pos = (_cimg_mp_is_vector(arg1) || _cimg_mp_is_vector(arg2))?vector(2):0; 15219 pos = (_cimg_mp_is_vector(arg1) || _cimg_mp_is_vector(arg2))?vector(2):0;
15203 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) { 15220 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) {
15204 CImg<uptrT>::vector((uptrT)mp_complex_pow_vv,pos,arg1,arg2).move_to(code); 15221 CImg<uptrT>::vector((uptrT)mp_complex_pow_vv,pos,arg1,arg2).move_to(code);
@@ -15226,9 +15243,10 @@ namespace cimg_library_suffixed { @@ -15226,9 +15243,10 @@ namespace cimg_library_suffixed {
15226 15243
15227 for (s = se2; s>ss; --s) 15244 for (s = se2; s>ss; --s)
15228 if (*s=='^' && level[s - expr._data]==clevel) { // Power ('^') 15245 if (*s=='^' && level[s - expr._data]==clevel) { // Power ('^')
  15246 + _cimg_mp_op("Operator '^'");
15229 arg1 = compile(ss,s,depth1,0); 15247 arg1 = compile(ss,s,depth1,0);
15230 arg2 = compile(s + 1,se,depth1,0); 15248 arg2 = compile(s + 1,se,depth1,0);
15231 - _cimg_mp_check_type(arg2,2,"operator '^'",3,_cimg_mp_vector_size(arg1)); 15249 + _cimg_mp_check_type(arg2,2,3,_cimg_mp_vector_size(arg1));
15232 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_pow,arg1,arg2); 15250 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_pow,arg1,arg2);
15233 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_pow,arg1,arg2); 15251 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_pow,arg1,arg2);
15234 if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_pow,arg1,arg2); 15252 if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_pow,arg1,arg2);
@@ -15246,9 +15264,13 @@ namespace cimg_library_suffixed { @@ -15246,9 +15264,13 @@ namespace cimg_library_suffixed {
15246 15264
15247 is_sth = ss1<se1 && (*ss=='+' || *ss=='-') && *ss1==*ss; // is pre-? 15265 is_sth = ss1<se1 && (*ss=='+' || *ss=='-') && *ss1==*ss; // is pre-?
15248 if (is_sth || (se2>ss && (*se1=='+' || *se1=='-') && *se2==*se1)) { // Pre/post-decrement and increment 15266 if (is_sth || (se2>ss && (*se1=='+' || *se1=='-') && *se2==*se1)) { // Pre/post-decrement and increment
15249 - if ((is_sth && *ss=='+') || (!is_sth && *se1=='+')) { op = mp_self_increment; s_op = "Operator '++'"; }  
15250 - else { op = mp_self_decrement; s_op = "Operator '--'"; }  
15251 - 15267 + if ((is_sth && *ss=='+') || (!is_sth && *se1=='+')) {
  15268 + _cimg_mp_op("Operator '++'");
  15269 + op = mp_self_increment;
  15270 + } else {
  15271 + _cimg_mp_op("Operator '--'");
  15272 + op = mp_self_decrement;
  15273 + }
15252 ref.assign(7); 15274 ref.assign(7);
15253 arg1 = is_sth?compile(ss2,se,depth1,ref):compile(ss,se2,depth1,ref); // Variable slot 15275 arg1 = is_sth?compile(ss2,se,depth1,ref):compile(ss,se2,depth1,ref); // Variable slot
15254 15276
@@ -15274,6 +15296,7 @@ namespace cimg_library_suffixed { @@ -15274,6 +15296,7 @@ namespace cimg_library_suffixed {
15274 } 15296 }
15275 15297
15276 if (*ref==2) { // Image value (scalar): i/j[_#ind,off]++ 15298 if (*ref==2) { // Image value (scalar): i/j[_#ind,off]++
  15299 + is_parallelizable = false;
15277 p1 = ref[1]; // Index 15300 p1 = ref[1]; // Index
15278 is_relative = (bool)ref[2]; 15301 is_relative = (bool)ref[2];
15279 arg3 = ref[3]; // Offset 15302 arg3 = ref[3]; // Offset
@@ -15292,6 +15315,7 @@ namespace cimg_library_suffixed { @@ -15292,6 +15315,7 @@ namespace cimg_library_suffixed {
15292 } 15315 }
15293 15316
15294 if (*ref==3) { // Image value (scalar): i/j(_#ind,_x,_y,_z,_c)++ 15317 if (*ref==3) { // Image value (scalar): i/j(_#ind,_x,_y,_z,_c)++
  15318 + is_parallelizable = false;
15295 p1 = ref[1]; // Index 15319 p1 = ref[1]; // Index
15296 is_relative = (bool)ref[2]; 15320 is_relative = (bool)ref[2];
15297 arg3 = ref[3]; // X 15321 arg3 = ref[3]; // X
@@ -15313,13 +15337,12 @@ namespace cimg_library_suffixed { @@ -15313,13 +15337,12 @@ namespace cimg_library_suffixed {
15313 } 15337 }
15314 15338
15315 if (*ref==4) { // Image value (vector): I/J[_#ind,off]++ 15339 if (*ref==4) { // Image value (vector): I/J[_#ind,off]++
  15340 + is_parallelizable = false;
15316 p1 = ref[1]; // Index 15341 p1 = ref[1]; // Index
15317 is_relative = (bool)ref[2]; 15342 is_relative = (bool)ref[2];
15318 arg3 = ref[3]; // Offset 15343 arg3 = ref[3]; // Offset
15319 if (p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int)); 15344 if (p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int));
15320 - CImg<uptrT>::vector((uptrT)mp_self_map_vector_s,arg1,(uptrT)_cimg_mp_vector_size(arg1),  
15321 - (uptrT)(op==mp_self_increment?mp_self_add:mp_self_sub),1).  
15322 - move_to(code); 15345 + self_vector_s(arg1,op==mp_self_increment?mp_self_add:mp_self_sub,1);
15323 if (p1!=~0U) { 15346 if (p1!=~0U) {
15324 if (!listout) _cimg_mp_return(pos); 15347 if (!listout) _cimg_mp_return(pos);
15325 CImg<uptrT>::vector((uptrT)(is_relative?mp_list_set_Joff_v:mp_list_set_Ioff_v), 15348 CImg<uptrT>::vector((uptrT)(is_relative?mp_list_set_Joff_v:mp_list_set_Ioff_v),
@@ -15333,15 +15356,14 @@ namespace cimg_library_suffixed { @@ -15333,15 +15356,14 @@ namespace cimg_library_suffixed {
15333 } 15356 }
15334 15357
15335 if (*ref==5) { // Image value (vector): I/J(_#ind,_x,_y,_z,_c)++ 15358 if (*ref==5) { // Image value (vector): I/J(_#ind,_x,_y,_z,_c)++
  15359 + is_parallelizable = false;
15336 p1 = ref[1]; // Index 15360 p1 = ref[1]; // Index
15337 is_relative = (bool)ref[2]; 15361 is_relative = (bool)ref[2];
15338 arg3 = ref[3]; // X 15362 arg3 = ref[3]; // X
15339 arg4 = ref[4]; // Y 15363 arg4 = ref[4]; // Y
15340 arg5 = ref[5]; // Z 15364 arg5 = ref[5]; // Z
15341 if (p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int)); 15365 if (p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int));
15342 - CImg<uptrT>::vector((uptrT)mp_self_map_vector_s,arg1,(uptrT)_cimg_mp_vector_size(arg1),  
15343 - (uptrT)(op==mp_self_increment?mp_self_add:mp_self_sub),1).  
15344 - move_to(code); 15366 + self_vector_s(arg1,op==mp_self_increment?mp_self_add:mp_self_sub,1);
15345 if (p1!=~0U) { 15367 if (p1!=~0U) {
15346 if (!listout) _cimg_mp_return(pos); 15368 if (!listout) _cimg_mp_return(pos);
15347 CImg<uptrT>::vector((uptrT)(is_relative?mp_list_set_Jxyz_v:mp_list_set_Ixyz_v), 15369 CImg<uptrT>::vector((uptrT)(is_relative?mp_list_set_Jxyz_v:mp_list_set_Ixyz_v),
@@ -15355,9 +15377,7 @@ namespace cimg_library_suffixed { @@ -15355,9 +15377,7 @@ namespace cimg_library_suffixed {
15355 } 15377 }
15356 15378
15357 if (_cimg_mp_is_vector(arg1)) { // Vector variable: V++ 15379 if (_cimg_mp_is_vector(arg1)) { // Vector variable: V++
15358 - CImg<uptrT>::vector((uptrT)mp_self_map_vector_s,arg1,(uptrT)_cimg_mp_vector_size(arg1),  
15359 - (uptrT)(op==mp_self_increment?mp_self_add:mp_self_sub),1).  
15360 - move_to(code); 15380 + self_vector_s(arg1,op==mp_self_increment?mp_self_add:mp_self_sub,1);
15361 _cimg_mp_return(pos); 15381 _cimg_mp_return(pos);
15362 } 15382 }
15363 15383
@@ -15382,7 +15402,7 @@ namespace cimg_library_suffixed { @@ -15382,7 +15402,7 @@ namespace cimg_library_suffixed {
15382 15402
15383 // Array-like access to vectors and image values 'i/j[_#ind,offset,_boundary]' and 'vector[offset]'. 15403 // Array-like access to vectors and image values 'i/j[_#ind,offset,_boundary]' and 'vector[offset]'.
15384 if (*se1==']' && *ss!='[') { 15404 if (*se1==']' && *ss!='[') {
15385 - s_op = "Operator '[]'"; 15405 + _cimg_mp_op("Operator '[]'");
15386 is_relative = *ss=='j' || *ss=='J'; 15406 is_relative = *ss=='j' || *ss=='J';
15387 15407
15388 if ((*ss=='I' || *ss=='J') && *ss1=='[' && 15408 if ((*ss=='I' || *ss=='J') && *ss1=='[' &&
@@ -15390,10 +15410,11 @@ namespace cimg_library_suffixed { @@ -15390,10 +15410,11 @@ namespace cimg_library_suffixed {
15390 if (*ss2=='#') { // Index specified 15410 if (*ss2=='#') { // Index specified
15391 s0 = ss3; while (s0<se1 && (*s0!=',' || level[s0 - expr._data]!=clevel1)) ++s0; 15411 s0 = ss3; while (s0<se1 && (*s0!=',' || level[s0 - expr._data]!=clevel1)) ++s0;
15392 p1 = compile(ss3,s0++,depth1,0); 15412 p1 = compile(ss3,s0++,depth1,0);
  15413 + _cimg_mp_check_list(false);
15393 } else { p1 = ~0U; s0 = ss2; } 15414 } else { p1 = ~0U; s0 = ss2; }
15394 s1 = s0; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1; 15415 s1 = s0; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
15395 arg1 = compile(s0,s1,depth1,0); // Offset 15416 arg1 = compile(s0,s1,depth1,0); // Offset
15396 - arg2 = s1<se1?compile(s1 + 1,se1,depth1,0):~0U; // Boundary 15417 + arg2 = s1<se1?compile(++s1,se1,depth1,0):~0U; // Boundary
15397 if (p_ref && arg2==~0U) { 15418 if (p_ref && arg2==~0U) {
15398 *p_ref = 4; 15419 *p_ref = 4;
15399 p_ref[1] = p1; 15420 p_ref[1] = p1;
@@ -15408,12 +15429,13 @@ namespace cimg_library_suffixed { @@ -15408,12 +15429,13 @@ namespace cimg_library_suffixed {
15408 p3 = (unsigned int)cimg::mod((int)mem[p1],listin.width()); 15429 p3 = (unsigned int)cimg::mod((int)mem[p1],listin.width());
15409 p2 = listin[p3]._spectrum; 15430 p2 = listin[p3]._spectrum;
15410 } 15431 }
15411 - _cimg_mp_check_vector0(p2,s_op); 15432 + _cimg_mp_check_vector0(p2);
15412 pos = vector(p2); 15433 pos = vector(p2);
15413 if (p1!=~0U) { 15434 if (p1!=~0U) {
15414 CImg<uptrT>::vector((uptrT)(is_relative?mp_list_Joff:mp_list_Ioff), 15435 CImg<uptrT>::vector((uptrT)(is_relative?mp_list_Joff:mp_list_Ioff),
15415 pos,p1,arg1,arg2==~0U?reserved_label[30]:arg2).move_to(code); 15436 pos,p1,arg1,arg2==~0U?reserved_label[30]:arg2).move_to(code);
15416 } else { 15437 } else {
  15438 + need_input_copy = true;
15417 CImg<uptrT>::vector((uptrT)(is_relative?mp_Joff:mp_Ioff), 15439 CImg<uptrT>::vector((uptrT)(is_relative?mp_Joff:mp_Ioff),
15418 pos,arg1,arg2==~0U?reserved_label[30]:arg2).move_to(code); 15440 pos,arg1,arg2==~0U?reserved_label[30]:arg2).move_to(code);
15419 } 15441 }
@@ -15428,7 +15450,7 @@ namespace cimg_library_suffixed { @@ -15428,7 +15450,7 @@ namespace cimg_library_suffixed {
15428 } else { p1 = ~0U; s0 = ss2; } 15450 } else { p1 = ~0U; s0 = ss2; }
15429 s1 = s0; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1; 15451 s1 = s0; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
15430 arg1 = compile(s0,s1,depth1,0); // Offset 15452 arg1 = compile(s0,s1,depth1,0); // Offset
15431 - arg2 = s1<se1?compile(s1 + 1,se1,depth1,0):~0U; // Boundary 15453 + arg2 = s1<se1?compile(++s1,se1,depth1,0):~0U; // Boundary
15432 if (p_ref && arg2==~0U) { 15454 if (p_ref && arg2==~0U) {
15433 *p_ref = 2; 15455 *p_ref = 2;
15434 p_ref[1] = p1; 15456 p_ref[1] = p1;
@@ -15442,6 +15464,7 @@ namespace cimg_library_suffixed { @@ -15442,6 +15464,7 @@ namespace cimg_library_suffixed {
15442 pos = scalar3(is_relative?mp_list_joff:mp_list_ioff,p1,arg1,arg2==~0U?reserved_label[30]:arg2); 15464 pos = scalar3(is_relative?mp_list_joff:mp_list_ioff,p1,arg1,arg2==~0U?reserved_label[30]:arg2);
15443 } else { 15465 } else {
15444 if (!imgin) _cimg_mp_return(0); 15466 if (!imgin) _cimg_mp_return(0);
  15467 + need_input_copy = true;
15445 pos = scalar2(is_relative?mp_joff:mp_ioff,arg1,arg2==~0U?reserved_label[30]:arg2); 15468 pos = scalar2(is_relative?mp_joff:mp_ioff,arg1,arg2==~0U?reserved_label[30]:arg2);
15446 } 15469 }
15447 memtype[pos] = -1; // Create it as a variable to prevent from being used in further optimization 15470 memtype[pos] = -1; // Create it as a variable to prevent from being used in further optimization
@@ -15456,8 +15479,8 @@ namespace cimg_library_suffixed { @@ -15456,8 +15479,8 @@ namespace cimg_library_suffixed {
15456 if (s1<se1) { // Two arguments -> sub-vector extraction 15479 if (s1<se1) { // Two arguments -> sub-vector extraction
15457 arg2 = compile(++s0,s1,depth1,0); 15480 arg2 = compile(++s0,s1,depth1,0);
15458 arg3 = compile(++s1,se1,depth1,0); 15481 arg3 = compile(++s1,se1,depth1,0);
15459 - _cimg_mp_check_constant(arg2,1,s_op,false);  
15460 - _cimg_mp_check_constant(arg3,2,s_op,false); 15482 + _cimg_mp_check_constant(arg2,1,false);
  15483 + _cimg_mp_check_constant(arg3,2,false);
15461 p1 = (unsigned int)mem[arg2]; 15484 p1 = (unsigned int)mem[arg2];
15462 p2 = (unsigned int)mem[arg3]; 15485 p2 = (unsigned int)mem[arg3];
15463 p3 = _cimg_mp_vector_size(arg1); 15486 p3 = _cimg_mp_vector_size(arg1);
@@ -15527,12 +15550,14 @@ namespace cimg_library_suffixed { @@ -15527,12 +15550,14 @@ namespace cimg_library_suffixed {
15527 if (*se1==')') { 15550 if (*se1==')') {
15528 if (*ss=='(') _cimg_mp_return(compile(ss1,se1,depth1,p_ref)); // Simple parentheses 15551 if (*ss=='(') _cimg_mp_return(compile(ss1,se1,depth1,p_ref)); // Simple parentheses
15529 is_relative = *ss=='j' || *ss=='J'; 15552 is_relative = *ss=='j' || *ss=='J';
  15553 + _cimg_mp_op("Operator '()'");
15530 15554
15531 - // I/J(_#ind,_x,_y,_z,_c,_interpolation,_boundary) 15555 + // I/J(_#ind,_x,_y,_z,_interpolation,_boundary)
15532 if ((*ss=='I' || *ss=='J') && *ss1=='(') { // Image value as scalar 15556 if ((*ss=='I' || *ss=='J') && *ss1=='(') { // Image value as scalar
15533 if (*ss2=='#') { // Index specified 15557 if (*ss2=='#') { // Index specified
15534 s0 = ss3; while (s0<se1 && (*s0!=',' || level[s0 - expr._data]!=clevel1)) ++s0; 15558 s0 = ss3; while (s0<se1 && (*s0!=',' || level[s0 - expr._data]!=clevel1)) ++s0;
15535 p1 = compile(ss3,s0++,depth1,0); 15559 p1 = compile(ss3,s0++,depth1,0);
  15560 + _cimg_mp_check_list(false);
15536 } else { p1 = ~0U; s0 = ss2; } 15561 } else { p1 = ~0U; s0 = ss2; }
15537 arg1 = is_relative?0U:(unsigned int)_cimg_mp_x; 15562 arg1 = is_relative?0U:(unsigned int)_cimg_mp_x;
15538 arg2 = is_relative?0U:(unsigned int)_cimg_mp_y; 15563 arg2 = is_relative?0U:(unsigned int)_cimg_mp_y;
@@ -15541,9 +15566,9 @@ namespace cimg_library_suffixed { @@ -15541,9 +15566,9 @@ namespace cimg_library_suffixed {
15541 if (s0<se1) { 15566 if (s0<se1) {
15542 s1 = s0; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1; 15567 s1 = s0; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
15543 arg1 = compile(s0,s1,depth1,0); 15568 arg1 = compile(s0,s1,depth1,0);
15544 - if (_cimg_mp_is_vector(arg1)) { // Coordinates specified as a vector [X,Y,Z] 15569 + if (_cimg_mp_is_vector(arg1)) { // Coordinates specified as a vector
15545 p2 = _cimg_mp_vector_size(arg1); 15570 p2 = _cimg_mp_vector_size(arg1);
15546 - arg1 = arg1 + 1; 15571 + ++arg1;
15547 if (p2>1) { 15572 if (p2>1) {
15548 arg2 = arg1 + 1; 15573 arg2 = arg1 + 1;
15549 if (p2>2) arg3 = arg2 + 1; 15574 if (p2>2) arg3 = arg2 + 1;
@@ -15551,7 +15576,7 @@ namespace cimg_library_suffixed { @@ -15551,7 +15576,7 @@ namespace cimg_library_suffixed {
15551 if (s1<se1) { 15576 if (s1<se1) {
15552 s2 = ++s1; while (s2<se1 && (*s2!=',' || level[s2 - expr._data]!=clevel1)) ++s2; 15577 s2 = ++s1; while (s2<se1 && (*s2!=',' || level[s2 - expr._data]!=clevel1)) ++s2;
15553 arg4 = compile(s1,s2,depth1,0); 15578 arg4 = compile(s1,s2,depth1,0);
15554 - if (s2<se1) arg5 = compile(++s2,se1,depth1,0); 15579 + arg5 = s2<se1?compile(++s2,se1,depth1,0):~0U;
15555 } 15580 }
15556 } else if (s1<se1) { 15581 } else if (s1<se1) {
15557 s2 = ++s1; while (s2<se1 && (*s2!=',' || level[s2 - expr._data]!=clevel1)) ++s2; 15582 s2 = ++s1; while (s2<se1 && (*s2!=',' || level[s2 - expr._data]!=clevel1)) ++s2;
@@ -15562,7 +15587,7 @@ namespace cimg_library_suffixed { @@ -15562,7 +15587,7 @@ namespace cimg_library_suffixed {
15562 if (s3<se1) { 15587 if (s3<se1) {
15563 s2 = ++s3; while (s2<se1 && (*s2!=',' || level[s2 - expr._data]!=clevel1)) ++s2; 15588 s2 = ++s3; while (s2<se1 && (*s2!=',' || level[s2 - expr._data]!=clevel1)) ++s2;
15564 arg4 = compile(s3,s2,depth1,0); 15589 arg4 = compile(s3,s2,depth1,0);
15565 - if (s2<se1) arg5 = compile(++s2,se1,depth1,0); 15590 + arg5 = s2<se1?compile(++s2,se1,depth1,0):~0U;
15566 } 15591 }
15567 } 15592 }
15568 } 15593 }
@@ -15585,18 +15610,20 @@ namespace cimg_library_suffixed { @@ -15585,18 +15610,20 @@ namespace cimg_library_suffixed {
15585 p3 = (unsigned int)cimg::mod((int)mem[p1],listin.width()); 15610 p3 = (unsigned int)cimg::mod((int)mem[p1],listin.width());
15586 p2 = listin[p3]._spectrum; 15611 p2 = listin[p3]._spectrum;
15587 } 15612 }
15588 - _cimg_mp_check_vector0(p2,"operator '()'"); 15613 + _cimg_mp_check_vector0(p2);
15589 pos = vector(p2); 15614 pos = vector(p2);
15590 if (p1!=~0U) 15615 if (p1!=~0U)
15591 CImg<uptrT>::vector((uptrT)(is_relative?mp_list_Jxyz:mp_list_Ixyz), 15616 CImg<uptrT>::vector((uptrT)(is_relative?mp_list_Jxyz:mp_list_Ixyz),
15592 pos,p1,arg1,arg2,arg3, 15617 pos,p1,arg1,arg2,arg3,
15593 arg4==~0U?reserved_label[29]:arg4, 15618 arg4==~0U?reserved_label[29]:arg4,
15594 arg5==~0U?reserved_label[30]:arg5).move_to(code); 15619 arg5==~0U?reserved_label[30]:arg5).move_to(code);
15595 - else 15620 + else {
  15621 + need_input_copy = true;
15596 CImg<uptrT>::vector((uptrT)(is_relative?mp_Jxyz:mp_Ixyz), 15622 CImg<uptrT>::vector((uptrT)(is_relative?mp_Jxyz:mp_Ixyz),
15597 pos,arg1,arg2,arg3, 15623 pos,arg1,arg2,arg3,
15598 arg4==~0U?reserved_label[29]:arg4, 15624 arg4==~0U?reserved_label[29]:arg4,
15599 arg5==~0U?reserved_label[30]:arg5).move_to(code); 15625 arg5==~0U?reserved_label[30]:arg5).move_to(code);
  15626 + }
15600 _cimg_mp_return(pos); 15627 _cimg_mp_return(pos);
15601 } 15628 }
15602 15629
@@ -15614,9 +15641,9 @@ namespace cimg_library_suffixed { @@ -15614,9 +15641,9 @@ namespace cimg_library_suffixed {
15614 if (s0<se1) { 15641 if (s0<se1) {
15615 s1 = s0; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1; 15642 s1 = s0; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
15616 arg1 = compile(s0,s1,depth1,0); 15643 arg1 = compile(s0,s1,depth1,0);
15617 - if (_cimg_mp_is_vector(arg1)) { // Coordinates specified as a vector [X,Y,Z,C] 15644 + if (_cimg_mp_is_vector(arg1)) { // Coordinates specified as a vector
15618 p2 = _cimg_mp_vector_size(arg1); 15645 p2 = _cimg_mp_vector_size(arg1);
15619 - arg1 = arg1 + 1; 15646 + ++arg1;
15620 if (p2>1) { 15647 if (p2>1) {
15621 arg2 = arg1 + 1; 15648 arg2 = arg1 + 1;
15622 if (p2>2) { 15649 if (p2>2) {
@@ -15627,7 +15654,7 @@ namespace cimg_library_suffixed { @@ -15627,7 +15654,7 @@ namespace cimg_library_suffixed {
15627 if (s1<se1) { 15654 if (s1<se1) {
15628 s2 = ++s1; while (s2<se1 && (*s2!=',' || level[s2 - expr._data]!=clevel1)) ++s2; 15655 s2 = ++s1; while (s2<se1 && (*s2!=',' || level[s2 - expr._data]!=clevel1)) ++s2;
15629 arg5 = compile(s1,s2,depth1,0); 15656 arg5 = compile(s1,s2,depth1,0);
15630 - if (s2<se1) arg6 = compile(++s2,se1,depth1,0); 15657 + arg6 = s2<se1?compile(++s2,se1,depth1,0):~0U;
15631 } 15658 }
15632 } else if (s1<se1) { 15659 } else if (s1<se1) {
15633 s2 = ++s1; while (s2<se1 && (*s2!=',' || level[s2 - expr._data]!=clevel1)) ++s2; 15660 s2 = ++s1; while (s2<se1 && (*s2!=',' || level[s2 - expr._data]!=clevel1)) ++s2;
@@ -15641,7 +15668,7 @@ namespace cimg_library_suffixed { @@ -15641,7 +15668,7 @@ namespace cimg_library_suffixed {
15641 if (s2<se1) { 15668 if (s2<se1) {
15642 s3 = ++s2; while (s3<se1 && (*s3!=',' || level[s3 - expr._data]!=clevel1)) ++s3; 15669 s3 = ++s2; while (s3<se1 && (*s3!=',' || level[s3 - expr._data]!=clevel1)) ++s3;
15643 arg5 = compile(s2,s3,depth1,0); 15670 arg5 = compile(s2,s3,depth1,0);
15644 - if (s3<se1) arg6 = compile(++s3,se1,depth1,0); 15671 + arg6 = s3<se1?compile(++s3,se1,depth1,0):~0U;
15645 } 15672 }
15646 } 15673 }
15647 } 15674 }
@@ -15670,6 +15697,7 @@ namespace cimg_library_suffixed { @@ -15670,6 +15697,7 @@ namespace cimg_library_suffixed {
15670 arg6==~0U?reserved_label[30]:arg6); 15697 arg6==~0U?reserved_label[30]:arg6);
15671 } else { 15698 } else {
15672 if (!imgin) _cimg_mp_return(0); 15699 if (!imgin) _cimg_mp_return(0);
  15700 + need_input_copy = true;
15673 pos = scalar6(is_relative?mp_jxyzc:mp_ixyzc, 15701 pos = scalar6(is_relative?mp_jxyzc:mp_ixyzc,
15674 arg1,arg2,arg3,arg4, 15702 arg1,arg2,arg3,arg4,
15675 arg5==~0U?reserved_label[29]:arg5, 15703 arg5==~0U?reserved_label[29]:arg5,
@@ -15683,6 +15711,7 @@ namespace cimg_library_suffixed { @@ -15683,6 +15711,7 @@ namespace cimg_library_suffixed {
15683 switch (*ss) { 15711 switch (*ss) {
15684 case 'a' : 15712 case 'a' :
15685 if (!std::strncmp(ss,"abs(",4)) { // Absolute value 15713 if (!std::strncmp(ss,"abs(",4)) { // Absolute value
  15714 + _cimg_mp_op("Function 'abs()'");
15686 arg1 = compile(ss4,se1,depth1,0); 15715 arg1 = compile(ss4,se1,depth1,0);
15687 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_abs,arg1); 15716 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_abs,arg1);
15688 if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(cimg::abs(mem[arg1])); 15717 if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(cimg::abs(mem[arg1]));
@@ -15690,6 +15719,7 @@ namespace cimg_library_suffixed { @@ -15690,6 +15719,7 @@ namespace cimg_library_suffixed {
15690 } 15719 }
15691 15720
15692 if (!std::strncmp(ss,"acos(",5)) { // Arccos 15721 if (!std::strncmp(ss,"acos(",5)) { // Arccos
  15722 + _cimg_mp_op("Function 'acos()'");
15693 arg1 = compile(ss5,se1,depth1,0); 15723 arg1 = compile(ss5,se1,depth1,0);
15694 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_acos,arg1); 15724 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_acos,arg1);
15695 if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::acos(mem[arg1])); 15725 if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::acos(mem[arg1]));
@@ -15697,6 +15727,7 @@ namespace cimg_library_suffixed { @@ -15697,6 +15727,7 @@ namespace cimg_library_suffixed {
15697 } 15727 }
15698 15728
15699 if (!std::strncmp(ss,"asin(",5)) { // Arcsin 15729 if (!std::strncmp(ss,"asin(",5)) { // Arcsin
  15730 + _cimg_mp_op("Function 'asin()'");
15700 arg1 = compile(ss5,se1,depth1,0); 15731 arg1 = compile(ss5,se1,depth1,0);
15701 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_asin,arg1); 15732 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_asin,arg1);
15702 if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::asin(mem[arg1])); 15733 if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::asin(mem[arg1]));
@@ -15704,6 +15735,7 @@ namespace cimg_library_suffixed { @@ -15704,6 +15735,7 @@ namespace cimg_library_suffixed {
15704 } 15735 }
15705 15736
15706 if (!std::strncmp(ss,"atan(",5)) { // Arctan 15737 if (!std::strncmp(ss,"atan(",5)) { // Arctan
  15738 + _cimg_mp_op("Function 'atan()'");
15707 arg1 = compile(ss5,se1,depth1,0); 15739 arg1 = compile(ss5,se1,depth1,0);
15708 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_atan,arg1); 15740 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_atan,arg1);
15709 if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::atan(mem[arg1])); 15741 if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::atan(mem[arg1]));
@@ -15711,10 +15743,11 @@ namespace cimg_library_suffixed { @@ -15711,10 +15743,11 @@ namespace cimg_library_suffixed {
15711 } 15743 }
15712 15744
15713 if (!std::strncmp(ss,"atan2(",6)) { // Arctan2 15745 if (!std::strncmp(ss,"atan2(",6)) { // Arctan2
  15746 + _cimg_mp_op("Function 'atan2()'");
15714 s1 = ss6; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1; 15747 s1 = ss6; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
15715 arg1 = compile(ss6,s1,depth1,0); 15748 arg1 = compile(ss6,s1,depth1,0);
15716 - arg2 = compile(s1 + 1,se1,depth1,0);  
15717 - _cimg_mp_check_type(arg2,2,"Function 'atan2()'",3,_cimg_mp_vector_size(arg1)); 15749 + arg2 = compile(++s1,se1,depth1,0);
  15750 + _cimg_mp_check_type(arg2,2,3,_cimg_mp_vector_size(arg1));
15718 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_atan2,arg1,arg2); 15751 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_atan2,arg1,arg2);
15719 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_atan2,arg1,arg2); 15752 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_atan2,arg1,arg2);
15720 if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_atan2,arg1,arg2); 15753 if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_atan2,arg1,arg2);
@@ -15726,18 +15759,21 @@ namespace cimg_library_suffixed { @@ -15726,18 +15759,21 @@ namespace cimg_library_suffixed {
15726 15759
15727 case 'c' : 15760 case 'c' :
15728 if (!std::strncmp(ss,"cabs(",5)) { // Complex absolute value 15761 if (!std::strncmp(ss,"cabs(",5)) { // Complex absolute value
  15762 + _cimg_mp_op("Function 'cabs()'");
15729 arg1 = compile(ss5,se1,depth1,0); 15763 arg1 = compile(ss5,se1,depth1,0);
15730 - _cimg_mp_check_type(arg1,0,"Function 'cabs()'",2,2); 15764 + _cimg_mp_check_type(arg1,0,2,2);
15731 _cimg_mp_scalar2(mp_hypot,arg1 + 1,arg1 + 2); 15765 _cimg_mp_scalar2(mp_hypot,arg1 + 1,arg1 + 2);
15732 } 15766 }
15733 15767
15734 if (!std::strncmp(ss,"carg(",5)) { // Complex argument 15768 if (!std::strncmp(ss,"carg(",5)) { // Complex argument
  15769 + _cimg_mp_op("Function 'carg()'");
15735 arg1 = compile(ss5,se1,depth1,0); 15770 arg1 = compile(ss5,se1,depth1,0);
15736 - _cimg_mp_check_type(arg1,0,"Function 'carg()'",2,2); 15771 + _cimg_mp_check_type(arg1,0,2,2);
15737 _cimg_mp_scalar2(mp_atan2,arg1 + 2,arg1 + 1); 15772 _cimg_mp_scalar2(mp_atan2,arg1 + 2,arg1 + 1);
15738 } 15773 }
15739 15774
15740 if (!std::strncmp(ss,"cbrt(",5)) { // Cubic root 15775 if (!std::strncmp(ss,"cbrt(",5)) { // Cubic root
  15776 + _cimg_mp_op("Function 'cbrt()'");
15741 arg1 = compile(ss5,se1,depth1,0); 15777 arg1 = compile(ss5,se1,depth1,0);
15742 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_cbrt,arg1); 15778 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_cbrt,arg1);
15743 if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::pow(mem[arg1],1.0/3)); 15779 if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::pow(mem[arg1],1.0/3));
@@ -15745,30 +15781,66 @@ namespace cimg_library_suffixed { @@ -15745,30 +15781,66 @@ namespace cimg_library_suffixed {
15745 } 15781 }
15746 15782
15747 if (!std::strncmp(ss,"cconj(",6)) { // Complex conjugate 15783 if (!std::strncmp(ss,"cconj(",6)) { // Complex conjugate
  15784 + _cimg_mp_op("Function 'cconj()'");
15748 arg1 = compile(ss6,se1,depth1,0); 15785 arg1 = compile(ss6,se1,depth1,0);
15749 - _cimg_mp_check_type(arg1,0,"Function 'cconj()'",2,2); 15786 + _cimg_mp_check_type(arg1,0,2,2);
15750 pos = vector(2); 15787 pos = vector(2);
15751 CImg<uptrT>::vector((uptrT)mp_complex_conj,pos,arg1).move_to(code); 15788 CImg<uptrT>::vector((uptrT)mp_complex_conj,pos,arg1).move_to(code);
15752 _cimg_mp_return(pos); 15789 _cimg_mp_return(pos);
15753 } 15790 }
15754 15791
15755 if (!std::strncmp(ss,"cexp(",5)) { // Complex exponential 15792 if (!std::strncmp(ss,"cexp(",5)) { // Complex exponential
  15793 + _cimg_mp_op("Function 'cexp()'");
15756 arg1 = compile(ss5,se1,depth1,0); 15794 arg1 = compile(ss5,se1,depth1,0);
15757 - _cimg_mp_check_type(arg1,0,"Function 'cexp()'",2,2); 15795 + _cimg_mp_check_type(arg1,0,2,2);
15758 pos = vector(2); 15796 pos = vector(2);
15759 CImg<uptrT>::vector((uptrT)mp_complex_exp,pos,arg1).move_to(code); 15797 CImg<uptrT>::vector((uptrT)mp_complex_exp,pos,arg1).move_to(code);
15760 _cimg_mp_return(pos); 15798 _cimg_mp_return(pos);
15761 } 15799 }
15762 15800
15763 if (!std::strncmp(ss,"clog(",5)) { // Complex logarithm 15801 if (!std::strncmp(ss,"clog(",5)) { // Complex logarithm
  15802 + _cimg_mp_op("Function 'clog()'");
15764 arg1 = compile(ss5,se1,depth1,0); 15803 arg1 = compile(ss5,se1,depth1,0);
15765 - _cimg_mp_check_type(arg1,0,"Function 'clog()'",2,2); 15804 + _cimg_mp_check_type(arg1,0,2,2);
15766 pos = vector(2); 15805 pos = vector(2);
15767 CImg<uptrT>::vector((uptrT)mp_complex_log,pos,arg1).move_to(code); 15806 CImg<uptrT>::vector((uptrT)mp_complex_log,pos,arg1).move_to(code);
15768 _cimg_mp_return(pos); 15807 _cimg_mp_return(pos);
15769 } 15808 }
15770 15809
  15810 + if (!std::strncmp(ss,"copy(",5)) { // Memory copy
  15811 + _cimg_mp_op("Function 'copy()'");
  15812 + ref.assign(14);
  15813 + s1 = ss5; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
  15814 + arg1 = p1 = compile(ss5,s1,depth1,ref);
  15815 + s2 = ++s1; while (s2<se1 && (*s2!=',' || level[s2 - expr._data]!=clevel1)) ++s2;
  15816 + arg2 = compile(s1,s2,depth1,ref._data + 7);
  15817 + arg3 = ~0U; arg4 = arg5 = 1;
  15818 + if (s2<se1) {
  15819 + s3 = ++s2; while (s3<se1 && (*s3!=',' || level[s3 - expr._data]!=clevel1)) ++s3;
  15820 + arg3 = compile(s2,s3,depth1,0);
  15821 + if (s3<se1) {
  15822 + s1 = ++s3; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
  15823 + arg4 = compile(s3,s1,depth1,0);
  15824 + arg5 = s1<se1?compile(++s1,se1,depth1,0):1;
  15825 + }
  15826 + }
  15827 + if (_cimg_mp_is_vector(arg1) && !ref[0]) ++arg1;
  15828 + if (_cimg_mp_is_vector(arg2)) {
  15829 + if (arg3==~0U) arg3 = _cimg_mp_vector_size(arg2);
  15830 + if (!ref[7]) ++arg2;
  15831 + }
  15832 + if (arg3==~0U) arg3 = 1;
  15833 + _cimg_mp_check_type(arg3,3,1,0);
  15834 + _cimg_mp_check_type(arg4,4,1,0);
  15835 + _cimg_mp_check_type(arg5,5,1,0);
  15836 + CImg<uptrT>(1,21).move_to(code);
  15837 + code.back().get_shared_rows(0,6).fill((uptrT)mp_memcopy,p1,arg1,arg2,arg3,arg4,arg5);
  15838 + code.back().get_shared_rows(7,20).fill(ref);
  15839 + _cimg_mp_return(p1);
  15840 + }
  15841 +
15771 if (!std::strncmp(ss,"cos(",4)) { // Cosine 15842 if (!std::strncmp(ss,"cos(",4)) { // Cosine
  15843 + _cimg_mp_op("Function 'cos()'");
15772 arg1 = compile(ss4,se1,depth1,0); 15844 arg1 = compile(ss4,se1,depth1,0);
15773 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_cos,arg1); 15845 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_cos,arg1);
15774 if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::cos(mem[arg1])); 15846 if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::cos(mem[arg1]));
@@ -15776,30 +15848,161 @@ namespace cimg_library_suffixed { @@ -15776,30 +15848,161 @@ namespace cimg_library_suffixed {
15776 } 15848 }
15777 15849
15778 if (!std::strncmp(ss,"cosh(",5)) { // Hyperbolic cosine 15850 if (!std::strncmp(ss,"cosh(",5)) { // Hyperbolic cosine
  15851 + _cimg_mp_op("Function 'cosh()'");
15779 arg1 = compile(ss5,se1,depth1,0); 15852 arg1 = compile(ss5,se1,depth1,0);
15780 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_cosh,arg1); 15853 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_cosh,arg1);
15781 if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::cosh(mem[arg1])); 15854 if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::cosh(mem[arg1]));
15782 _cimg_mp_scalar1(mp_cosh,arg1); 15855 _cimg_mp_scalar1(mp_cosh,arg1);
15783 } 15856 }
15784 15857
  15858 + if (!std::strncmp(ss,"crop(",5)) { // Image crop
  15859 + _cimg_mp_op("Function 'crop()'");
  15860 + if (*ss5=='#') { // Index specified
  15861 + s0 = ss6; while (s0<se1 && (*s0!=',' || level[s0 - expr._data]!=clevel1)) ++s0;
  15862 + p1 = compile(ss6,s0++,depth1,0);
  15863 + _cimg_mp_check_list(false);
  15864 + } else { p1 = ~0U; s0 = ss5; need_input_copy = true; }
  15865 + pos = 0;
  15866 + is_sth = false; // Coordinates specified as a vector?
  15867 + if (ss5<se1) for (s = s0; s<se; ++s, ++pos) {
  15868 + ns = s; while (ns<se && (*ns!=',' || level[ns - expr._data]!=clevel1) &&
  15869 + (*ns!=')' || level[ns - expr._data]!=clevel)) ++ns;
  15870 + arg1 = compile(s,ns,depth1,0);
  15871 + if (!pos && _cimg_mp_is_vector(arg1)) { // Coordinates specified as a vector
  15872 + opcode = CImg<uptrT>::sequence((uptrT)_cimg_mp_vector_size(arg1),arg1 + 1,
  15873 + arg1 + (uptrT)_cimg_mp_vector_size(arg1));
  15874 + opcode.resize(1,cimg::min(opcode._height,4U),1,1,0).move_to(_opcode);
  15875 + is_sth = true;
  15876 + } else {
  15877 + _cimg_mp_check_type(arg1,pos + 1,1,0);
  15878 + CImg<uptrT>::vector(arg1).move_to(_opcode);
  15879 + }
  15880 + s = ns;
  15881 + }
  15882 + (_opcode>'y').move_to(opcode);
  15883 +
  15884 + arg1 = 0; arg2 = p1!=~0U?1:0;
  15885 + switch (opcode._height) {
  15886 + case 0 : case 1 :
  15887 + CImg<uptrT>::vector(0,0,0,0,~0U,~0U,~0U,~0U,0).move_to(opcode);
  15888 + break;
  15889 + case 2 :
  15890 + CImg<uptrT>::vector(*opcode,0,0,0,opcode[1],~0U,~0U,~0U,reserved_label[30]).move_to(opcode);
  15891 + arg1 = arg2?3:2;
  15892 + break;
  15893 + case 3 :
  15894 + CImg<uptrT>::vector(*opcode,0,0,0,opcode[1],~0U,~0U,~0U,opcode[2]).move_to(opcode);
  15895 + arg1 = arg2?3:2;
  15896 + break;
  15897 + case 4 :
  15898 + CImg<uptrT>::vector(*opcode,opcode[1],0,0,opcode[2],opcode[3],~0U,~0U,reserved_label[30]).
  15899 + move_to(opcode);
  15900 + arg1 = (is_sth?2:1) + arg2;
  15901 + break;
  15902 + case 5 :
  15903 + CImg<uptrT>::vector(*opcode,opcode[1],0,0,opcode[2],opcode[3],~0U,~0U,opcode[4]).
  15904 + move_to(opcode);
  15905 + arg1 = (is_sth?2:1) + arg2;
  15906 + break;
  15907 + case 6 :
  15908 + CImg<uptrT>::vector(*opcode,opcode[1],opcode[2],0,opcode[3],opcode[4],opcode[5],~0U,
  15909 + reserved_label[30]).move_to(opcode);
  15910 + arg1 = (is_sth?2:4) + arg2;
  15911 + break;
  15912 + case 7 :
  15913 + CImg<uptrT>::vector(*opcode,opcode[1],opcode[2],0,opcode[3],opcode[4],opcode[5],~0U,
  15914 + opcode[6]).move_to(opcode);
  15915 + arg1 = (is_sth?2:4) + arg2;
  15916 + break;
  15917 + case 8 :
  15918 + CImg<uptrT>::vector(*opcode,opcode[1],opcode[2],opcode[3],opcode[4],opcode[5],opcode[6],
  15919 + opcode[7],reserved_label[30]).move_to(opcode);
  15920 + arg1 = (is_sth?2:5) + arg2;
  15921 + break;
  15922 + case 9 :
  15923 + arg1 = (is_sth?2:5) + arg2;
  15924 + break;
  15925 + default : // Error -> too much arguments
  15926 + throw CImgArgumentException("[_cimg_math_parser] "
  15927 + "CImg<%s>::%s: %s: Too much arguments specified, "
  15928 + "in expression '%s%s%s'.",
  15929 + pixel_type(),_cimg_mp_calling_function,s_op,
  15930 + (ss - 4)>expr._data?"...":"",
  15931 + (ss - 4)>expr._data?ss - 4:expr._data,
  15932 + se<&expr.back()?"...":"");
  15933 + }
  15934 + _cimg_mp_check_type(*opcode,arg2 + 1,1,0);
  15935 + _cimg_mp_check_type(opcode[1],arg2 + (is_sth?0:1),1,0);
  15936 + _cimg_mp_check_type(opcode[2],arg2 + (is_sth?0:2),1,0);
  15937 + _cimg_mp_check_type(opcode[3],arg2 + (is_sth?0:3),1,0);
  15938 +
  15939 + if (opcode[4]!=(uptrT)~0U) {
  15940 + _cimg_mp_check_constant(opcode[4],arg1,true);
  15941 + opcode[4] = (uptrT)mem[opcode[4]];
  15942 + }
  15943 + if (opcode[5]!=(uptrT)~0U) {
  15944 + _cimg_mp_check_constant(opcode[5],arg1 + 1,true);
  15945 + opcode[5] = (uptrT)mem[opcode[5]];
  15946 + }
  15947 + if (opcode[6]!=(uptrT)~0U) {
  15948 + _cimg_mp_check_constant(opcode[6],arg1 + 2,true);
  15949 + opcode[6] = (uptrT)mem[opcode[6]];
  15950 + }
  15951 + if (opcode[7]!=(uptrT)~0U) {
  15952 + _cimg_mp_check_constant(opcode[7],arg1 + 3,true);
  15953 + opcode[7] = (uptrT)mem[opcode[7]];
  15954 + }
  15955 + _cimg_mp_check_type(opcode[8],arg1 + 4,1,0);
  15956 +
  15957 + if (opcode[4]==(uptrT)~0U || opcode[5]==(uptrT)~0U ||
  15958 + opcode[6]==(uptrT)~0U || opcode[7]==(uptrT)~0U) {
  15959 + if (p1!=~0U) {
  15960 + _cimg_mp_check_constant(p1,1,false);
  15961 + p1 = (unsigned int)cimg::mod((int)mem[p1],listin.width());
  15962 + }
  15963 + const CImg<T> &img = p1!=~0U?listin[p1]:imgin;
  15964 + if (!img)
  15965 + throw CImgArgumentException("[_cimg_math_parser] "
  15966 + "CImg<%s>::%s: %s: Cannot crop empty image when "
  15967 + "some xyzc-coordinates are unspecified, in expression '%s%s%s'.",
  15968 + pixel_type(),_cimg_mp_calling_function,s_op,
  15969 + (ss - 4)>expr._data?"...":"",
  15970 + (ss - 4)>expr._data?ss - 4:expr._data,
  15971 + se<&expr.back()?"...":"");
  15972 + if (opcode[4]==(uptrT)~0U) opcode[4] = (uptrT)img._width;
  15973 + if (opcode[5]==(uptrT)~0U) opcode[5] = (uptrT)img._height;
  15974 + if (opcode[6]==(uptrT)~0U) opcode[6] = (uptrT)img._depth;
  15975 + if (opcode[7]==(uptrT)~0U) opcode[7] = (uptrT)img._spectrum;
  15976 + }
  15977 +
  15978 + pos = vector(opcode[4]*opcode[5]*opcode[6]*opcode[7]);
  15979 + CImg<uptrT>::vector((uptrT)mp_crop,
  15980 + pos,p1,
  15981 + *opcode,opcode[1],opcode[2],opcode[3],
  15982 + opcode[4],opcode[5],opcode[6],opcode[7],
  15983 + opcode[8]).move_to(code);
  15984 + _cimg_mp_return(pos);
  15985 + }
  15986 +
15785 if (!std::strncmp(ss,"cross(",6)) { // Cross product 15987 if (!std::strncmp(ss,"cross(",6)) { // Cross product
15786 - s_op = "Function 'cross()"; 15988 + _cimg_mp_op("Function 'cross()'");
15787 s1 = ss6; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1; 15989 s1 = ss6; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
15788 arg1 = compile(ss6,s1,depth1,0); 15990 arg1 = compile(ss6,s1,depth1,0);
15789 - arg2 = compile(s1 + 1,se1,depth1,0);  
15790 - _cimg_mp_check_type(arg1,1,s_op,2,3);  
15791 - _cimg_mp_check_type(arg2,2,s_op,2,3); 15991 + arg2 = compile(++s1,se1,depth1,0);
  15992 + _cimg_mp_check_type(arg1,1,2,3);
  15993 + _cimg_mp_check_type(arg2,2,2,3);
15792 pos = vector(3); 15994 pos = vector(3);
15793 CImg<uptrT>::vector((uptrT)mp_cross,pos,arg1,arg2).move_to(code); 15995 CImg<uptrT>::vector((uptrT)mp_cross,pos,arg1,arg2).move_to(code);
15794 _cimg_mp_return(pos); 15996 _cimg_mp_return(pos);
15795 } 15997 }
15796 15998
15797 if (!std::strncmp(ss,"cut(",4)) { // Cut 15999 if (!std::strncmp(ss,"cut(",4)) { // Cut
  16000 + _cimg_mp_op("Function 'cut()'");
15798 s1 = ss4; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1; 16001 s1 = ss4; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
15799 - arg1 = compile(ss4,s1==se2?++s1:s1,depth1,0); 16002 + arg1 = compile(ss4,s1,depth1,0);
15800 s2 = s1 + 1; while (s2<se1 && (*s2!=',' || level[s2 - expr._data]!=clevel1)) ++s2; 16003 s2 = s1 + 1; while (s2<se1 && (*s2!=',' || level[s2 - expr._data]!=clevel1)) ++s2;
15801 - arg2 = compile(s1 + 1,s2==se2?++s2:s2,depth1,0);  
15802 - arg3 = compile(s2 + 1,se1,depth1,0); 16004 + arg2 = compile(++s1,s2,depth1,0);
  16005 + arg3 = compile(++s2,se1,depth1,0);
15803 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector3_vss(mp_cut,arg1,arg2,arg3); 16006 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector3_vss(mp_cut,arg1,arg2,arg3);
15804 if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2) && _cimg_mp_is_constant(arg3)) { 16007 if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2) && _cimg_mp_is_constant(arg3)) {
15805 val = mem[arg1]; 16008 val = mem[arg1];
@@ -15813,6 +16016,7 @@ namespace cimg_library_suffixed { @@ -15813,6 +16016,7 @@ namespace cimg_library_suffixed {
15813 16016
15814 case 'd' : 16017 case 'd' :
15815 if (!std::strncmp(ss,"date(",5)) { // Date and file date 16018 if (!std::strncmp(ss,"date(",5)) { // Date and file date
  16019 + _cimg_mp_op("Function 'date()'");
15816 s1 = ss5; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1; 16020 s1 = ss5; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
15817 arg1 = 0; 16021 arg1 = 0;
15818 is_sth = s1!=se1; // is_fdate 16022 is_sth = s1!=se1; // is_fdate
@@ -15820,12 +16024,13 @@ namespace cimg_library_suffixed { @@ -15820,12 +16024,13 @@ namespace cimg_library_suffixed {
15820 (cimg_sscanf(ss5,"%u%c",&arg1,&sep)!=2 || sep!=')')) is_sth = true; 16024 (cimg_sscanf(ss5,"%u%c",&arg1,&sep)!=2 || sep!=')')) is_sth = true;
15821 if (is_sth) { 16025 if (is_sth) {
15822 if (cimg_sscanf(ss5,"%u%c",&arg1,&sep)!=2 || sep!=',') { arg1 = 0; s1 = ss4; } 16026 if (cimg_sscanf(ss5,"%u%c",&arg1,&sep)!=2 || sep!=',') { arg1 = 0; s1 = ss4; }
15823 - *se1 = 0; val = (double)cimg::fdate(s1 + 1,arg1); *se1 = ')'; 16027 + *se1 = 0; val = (double)cimg::fdate(++s1,arg1); *se1 = ')';
15824 } else val = (double)cimg::date(arg1); 16028 } else val = (double)cimg::date(arg1);
15825 _cimg_mp_constant(val); 16029 _cimg_mp_constant(val);
15826 } 16030 }
15827 16031
15828 if (!std::strncmp(ss,"debug(",6)) { // Print debug info 16032 if (!std::strncmp(ss,"debug(",6)) { // Print debug info
  16033 + _cimg_mp_op("Function 'debug()'");
15829 p1 = code._width; 16034 p1 = code._width;
15830 arg1 = compile(ss6,se1,depth1,p_ref); 16035 arg1 = compile(ss6,se1,depth1,p_ref);
15831 *se1 = 0; 16036 *se1 = 0;
@@ -15835,52 +16040,233 @@ namespace cimg_library_suffixed { @@ -15835,52 +16040,233 @@ namespace cimg_library_suffixed {
15835 _cimg_mp_return(arg1); 16040 _cimg_mp_return(arg1);
15836 } 16041 }
15837 16042
  16043 + if (!std::strncmp(ss,"det(",4)) { // Matrix determinant
  16044 + _cimg_mp_op("Function 'det()'");
  16045 + arg1 = compile(ss4,se1,depth1,0);
  16046 + _cimg_mp_check_matrix_square(arg1,1);
  16047 + p1 = (unsigned int)std::sqrt((float)_cimg_mp_vector_size(arg1));
  16048 + _cimg_mp_scalar2(mp_det,arg1,p1);
  16049 + }
  16050 +
  16051 + if (!std::strncmp(ss,"diag(",5)) { // Diagonal matrix
  16052 + _cimg_mp_op("Function 'diag()'");
  16053 + arg1 = compile(ss5,se1,depth1,0);
  16054 + _cimg_mp_check_type(arg1,1,2,0);
  16055 + p1 = _cimg_mp_vector_size(arg1);
  16056 + pos = vector(p1*p1);
  16057 + CImg<uptrT>::vector((uptrT)mp_diag,pos,arg1,p1).move_to(code);
  16058 + _cimg_mp_return(pos);
  16059 + }
  16060 +
15838 if (!std::strncmp(ss,"dot(",4)) { // Dot product 16061 if (!std::strncmp(ss,"dot(",4)) { // Dot product
15839 - s_op = "Function 'dot()'"; 16062 + _cimg_mp_op("Function 'dot()'");
15840 s1 = ss4; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1; 16063 s1 = ss4; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
15841 arg1 = compile(ss4,s1,depth1,0); 16064 arg1 = compile(ss4,s1,depth1,0);
15842 - arg2 = compile(s1 + 1,se1,depth1,0);  
15843 - _cimg_mp_check_type(arg1,1,s_op,2,0);  
15844 - _cimg_mp_check_type(arg2,2,s_op,2,0); 16065 + arg2 = compile(++s1,se1,depth1,0);
  16066 + _cimg_mp_check_type(arg1,1,2,0);
  16067 + _cimg_mp_check_type(arg2,2,2,0);
15845 if (_cimg_mp_is_vector(arg1)) _cimg_mp_scalar3(mp_dot,arg1,arg2,_cimg_mp_vector_size(arg1)); 16068 if (_cimg_mp_is_vector(arg1)) _cimg_mp_scalar3(mp_dot,arg1,arg2,_cimg_mp_vector_size(arg1));
15846 _cimg_mp_scalar2(mp_mul,arg1,arg2); 16069 _cimg_mp_scalar2(mp_mul,arg1,arg2);
15847 } 16070 }
15848 16071
15849 if (!std::strncmp(ss,"dowhile",7) && (*ss7=='(' || (*ss7 && *ss7<=' ' && *ss8=='('))) { // Do..while 16072 if (!std::strncmp(ss,"dowhile",7) && (*ss7=='(' || (*ss7 && *ss7<=' ' && *ss8=='('))) { // Do..while
  16073 + _cimg_mp_op("Function 'dowhile()'");
15850 if (*ss7<=' ') cimg::swap(*ss7,*ss8); // Allow space before opening brace 16074 if (*ss7<=' ') cimg::swap(*ss7,*ss8); // Allow space before opening brace
15851 s1 = ss8; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1; 16075 s1 = ss8; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
15852 p1 = code._width; 16076 p1 = code._width;
15853 arg1 = compile(ss8,s1,depth1,0); 16077 arg1 = compile(ss8,s1,depth1,0);
15854 - if (s1<se1) arg2 = compile(s1 + 1,se1,depth1,0);  
15855 - else arg2 = arg1;  
15856 - _cimg_mp_check_type(arg2,2,"Function 'dowhile()'",1,0); 16078 + arg2 = s1<se1?compile(++s1,se1,depth1,0):arg1;
  16079 + _cimg_mp_check_type(arg2,2,1,0);
15857 CImg<uptrT>::vector((uptrT)mp_dowhile,arg1,arg2,code._width - p1).move_to(code,p1); 16080 CImg<uptrT>::vector((uptrT)mp_dowhile,arg1,arg2,code._width - p1).move_to(code,p1);
15858 _cimg_mp_return(arg1); 16081 _cimg_mp_return(arg1);
15859 } 16082 }
  16083 +
  16084 + if (!std::strncmp(ss,"draw(",5)) { // Draw image
  16085 + _cimg_mp_op("Function 'draw()'");
  16086 + is_parallelizable = false;
  16087 + if (*ss5=='#') { // Index specified
  16088 + s0 = ss6; while (s0<se1 && (*s0!=',' || level[s0 - expr._data]!=clevel1)) ++s0;
  16089 + p1 = compile(ss6,s0++,depth1,0);
  16090 + _cimg_mp_check_list(true);
  16091 + } else { p1 = ~0U; s0 = ss5; }
  16092 + s1 = s0; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
  16093 + arg1 = compile(s0,s1,depth1,0);
  16094 + arg2 = is_relative?0U:(unsigned int)_cimg_mp_x;
  16095 + arg3 = is_relative?0U:(unsigned int)_cimg_mp_y;
  16096 + arg4 = is_relative?0U:(unsigned int)_cimg_mp_z;
  16097 + arg5 = is_relative?0U:(unsigned int)_cimg_mp_c;
  16098 + if (s1<se1) {
  16099 + s0 = s1 + 1; while (s0<se1 && (*s0!=',' || level[s0 - expr._data]!=clevel1)) ++s0;
  16100 + arg2 = compile(++s1,s0,depth1,0);
  16101 + if (_cimg_mp_is_vector(arg2)) { // Coordinates specified as a vector
  16102 + p2 = _cimg_mp_vector_size(arg2);
  16103 + ++arg2;
  16104 + if (p2>1) {
  16105 + arg3 = arg2 + 1;
  16106 + if (p2>2) {
  16107 + arg4 = arg3 + 1;
  16108 + if (p2>3) arg5 = arg4 + 1;
  16109 + }
  16110 + }
  16111 + ++s0;
  16112 + is_sth = true;
  16113 + } else {
  16114 + if (s0<se1) {
  16115 + is_sth = p1!=~0U;
  16116 + s1 = s0 + 1; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
  16117 + arg3 = compile(++s0,s1,depth1,0);
  16118 + _cimg_mp_check_type(arg3,is_sth?4:3,1,0);
  16119 + if (s1<se1) {
  16120 + s0 = s1 + 1; while (s0<se1 && (*s0!=',' || level[s0 - expr._data]!=clevel1)) ++s0;
  16121 + arg4 = compile(++s1,s0,depth1,0);
  16122 + _cimg_mp_check_type(arg4,is_sth?5:4,1,0);
  16123 + if (s0<se1) {
  16124 + s1 = s0 + 1; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
  16125 + arg5 = compile(++s0,s1,depth1,0);
  16126 + _cimg_mp_check_type(arg5,is_sth?6:5,1,0);
  16127 + s0 = ++s1;
  16128 + }
  16129 + }
  16130 + }
  16131 + is_sth = false;
  16132 + }
  16133 + }
  16134 +
  16135 + CImg<uptrT>::vector((uptrT)mp_draw,arg1,p1,arg2,arg3,arg4,arg5,0,0,0,0,1,(uptrT)-1,0,1).
  16136 + move_to(opcode);
  16137 +
  16138 + arg2 = arg3 = arg4 = arg5 = ~0U;
  16139 + p2 = p1!=~0U?0:1;
  16140 + if (s0<se1) {
  16141 + s1 = s0; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
  16142 + arg2 = compile(s0,s1,depth1,0);
  16143 + _cimg_mp_check_constant(arg2,p2 + (is_sth?3:6),true);
  16144 + arg2 = (unsigned int)mem[arg2];
  16145 + if (s1<se1) {
  16146 + s0 = s1 + 1; while (s0<se1 && (*s0!=',' || level[s0 - expr._data]!=clevel1)) ++s0;
  16147 + arg3 = compile(++s1,s0,depth1,0);
  16148 + _cimg_mp_check_constant(arg3,p2 + (is_sth?4:7),true);
  16149 + arg3 = (unsigned int)mem[arg3];
  16150 + if (s0<se1) {
  16151 + s1 = s0 + 1; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
  16152 + arg4 = compile(++s0,s1,depth1,0);
  16153 + _cimg_mp_check_constant(arg4,p2 + (is_sth?5:8),true);
  16154 + arg4 = (unsigned int)mem[arg4];
  16155 + if (s1<se1) {
  16156 + s0 = s1 + 1; while (s0<se1 && (*s0!=',' || level[s0 - expr._data]!=clevel1)) ++s0;
  16157 + arg5 = compile(++s1,s0,depth1,0);
  16158 + _cimg_mp_check_constant(arg5,p2 + (is_sth?6:9),true);
  16159 + arg5 = (unsigned int)mem[arg5];
  16160 + }
  16161 + }
  16162 + }
  16163 + }
  16164 + if (s0<s1) s0 = s1;
  16165 + if (arg2==~0U || arg3==~0U || arg4==~0U || arg5==~0U) {
  16166 + if (p1!=~0U) {
  16167 + _cimg_mp_check_constant(p1,1,false);
  16168 + p1 = (unsigned int)cimg::mod((int)mem[p1],listout.width());
  16169 + }
  16170 + const CImg<T> &img = p1!=~0U?listout[p1]:imgout;
  16171 + if (arg2==~0U) arg2 = img._width;
  16172 + if (arg3==~0U) arg3 = img._height;
  16173 + if (arg4==~0U) arg4 = img._depth;
  16174 + if (arg5==~0U) arg5 = img._spectrum;
  16175 + }
  16176 + if (arg2*arg3*arg4*arg5!=_cimg_mp_vector_size(arg1)) {
  16177 + *se = saved_char; cimg::strellipsize(expr,64);
  16178 + throw CImgArgumentException("[_cimg_math_parser] "
  16179 + "CImg<%s>::%s: %s: Type of %s argument ('%s') and specified size "
  16180 + "(%u,%u,%u,%u) do not match, in expression '%s%s%s'.",
  16181 + pixel_type(),_cimg_mp_calling_function,s_op,
  16182 + p1==~0U?"first":"second",s_type(arg1)._data,
  16183 + arg2,arg3,arg4,arg5,
  16184 + (ss - 4)>expr._data?"...":"",
  16185 + (ss - 4)>expr._data?ss - 4:expr._data,
  16186 + se<&expr.back()?"...":"");
  16187 + }
  16188 + opcode[7] = (uptrT)arg2;
  16189 + opcode[8] = (uptrT)arg3;
  16190 + opcode[9] = (uptrT)arg4;
  16191 + opcode[10] = (uptrT)arg5;
  16192 +
  16193 + if (s0<se1) {
  16194 + s1 = s0 + 1; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
  16195 + arg6 = compile(++s0,s1,depth1,0);
  16196 + _cimg_mp_check_type(arg6,0,1,0);
  16197 + opcode[11] = arg6;
  16198 + if (s1<se1) {
  16199 + s0 = s1 + 1; while (s0<se1 && (*s0!=',' || level[s0 - expr._data]!=clevel1)) ++s0;
  16200 + p2 = compile(++s1,s0,depth1,0);
  16201 + _cimg_mp_check_type(p2,0,2,0);
  16202 + if (arg2*arg3*arg4%_cimg_mp_vector_size(p2)) {
  16203 + *se = saved_char; cimg::strellipsize(expr,64);
  16204 + throw CImgArgumentException("[_cimg_math_parser] "
  16205 + "CImg<%s>::%s: %s: Type of opacity mask ('%s') and specified size "
  16206 + "(%u,%u,%u,%u) do not match, in expression '%s%s%s'.",
  16207 + pixel_type(),_cimg_mp_calling_function,s_op,
  16208 + s_type(p2)._data,
  16209 + arg2,arg3,arg4,arg5,
  16210 + (ss - 4)>expr._data?"...":"",
  16211 + (ss - 4)>expr._data?ss - 4:expr._data,
  16212 + se<&expr.back()?"...":"");
  16213 + }
  16214 + opcode[12] = p2;
  16215 + opcode[13] = _cimg_mp_vector_size(p2)/(arg2*arg3*arg4);
  16216 + p3 = s0<se1?compile(++s0,se1,depth1,0):1;
  16217 + _cimg_mp_check_type(p3,0,1,0);
  16218 + opcode[14] = p3;
  16219 + }
  16220 + }
  16221 + opcode.move_to(code);
  16222 + _cimg_mp_return(arg1);
  16223 + }
15860 break; 16224 break;
15861 16225
15862 case 'e' : 16226 case 'e' :
  16227 + if (!std::strncmp(ss,"eig(",4)) { // Matrix eigenvalues/eigenvector
  16228 + _cimg_mp_op("Function 'eig()'");
  16229 + arg1 = compile(ss4,se1,depth1,0);
  16230 + _cimg_mp_check_matrix_square(arg1,1);
  16231 + p1 = (unsigned int)std::sqrt((float)_cimg_mp_vector_size(arg1));
  16232 + pos = vector((p1 + 1)*p1);
  16233 + CImg<uptrT>::vector((uptrT)mp_eig,pos,arg1,p1).move_to(code);
  16234 + _cimg_mp_return(pos);
  16235 + }
  16236 +
15863 if (!std::strncmp(ss,"exp(",4)) { // Exponential 16237 if (!std::strncmp(ss,"exp(",4)) { // Exponential
  16238 + _cimg_mp_op("Function 'exp()'");
15864 arg1 = compile(ss4,se1,depth1,0); 16239 arg1 = compile(ss4,se1,depth1,0);
15865 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_exp,arg1); 16240 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_exp,arg1);
15866 if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::exp(mem[arg1])); 16241 if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::exp(mem[arg1]));
15867 _cimg_mp_scalar1(mp_exp,arg1); 16242 _cimg_mp_scalar1(mp_exp,arg1);
15868 } 16243 }
  16244 +
  16245 + if (!std::strncmp(ss,"eye(",4)) { // Identity matrix
  16246 + _cimg_mp_op("Function 'eye()'");
  16247 + arg1 = compile(ss4,se1,depth1,0);
  16248 + _cimg_mp_check_constant(arg1,1,true);
  16249 + p1 = (unsigned int)mem[arg1];
  16250 + pos = vector(p1*p1);
  16251 + CImg<uptrT>::vector((uptrT)mp_eye,pos,p1).move_to(code);
  16252 + _cimg_mp_return(pos);
  16253 + }
15869 break; 16254 break;
15870 16255
15871 case 'f' : 16256 case 'f' :
15872 if (*ss1=='o' && *ss2=='r' && (*ss3=='(' || (*ss3 && *ss3<=' ' && *ss4=='('))) { // For loop 16257 if (*ss1=='o' && *ss2=='r' && (*ss3=='(' || (*ss3 && *ss3<=' ' && *ss4=='('))) { // For loop
  16258 + _cimg_mp_op("Function 'for()'");
15873 if (*ss3<=' ') cimg::swap(*ss3,*ss4); // Allow space before opening brace 16259 if (*ss3<=' ') cimg::swap(*ss3,*ss4); // Allow space before opening brace
15874 s1 = ss4; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1; 16260 s1 = ss4; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
15875 s2 = s1 + 1; while (s2<se1 && (*s2!=',' || level[s2 - expr._data]!=clevel1)) ++s2; 16261 s2 = s1 + 1; while (s2<se1 && (*s2!=',' || level[s2 - expr._data]!=clevel1)) ++s2;
15876 s3 = s2 + 1; while (s3<se1 && (*s3!=',' || level[s3 - expr._data]!=clevel1)) ++s3; 16262 s3 = s2 + 1; while (s3<se1 && (*s3!=',' || level[s3 - expr._data]!=clevel1)) ++s3;
15877 compile(ss4,s1,depth1,0); 16263 compile(ss4,s1,depth1,0);
15878 p1 = code._width; 16264 p1 = code._width;
15879 - arg1 = compile(s1 + 1,s2,depth1,0); 16265 + arg1 = compile(++s1,s2,depth1,0);
15880 p2 = code._width; 16266 p2 = code._width;
15881 - if (s3<se1) { pos = compile(s3 + 1,se1,depth1,0); compile(s2 + 1,s3,depth1,0); } // Body + proc  
15882 - else pos = compile(s2 + 1,se1,depth1,0); // Proc only  
15883 - _cimg_mp_check_type(arg1,2,"Function 'for()'",1,0); 16267 + if (s3<se1) { pos = compile(s3 + 1,se1,depth1,0); compile(++s2,s3,depth1,0); } // Body + proc
  16268 + else pos = compile(++s2,se1,depth1,0); // Proc only
  16269 + _cimg_mp_check_type(arg1,2,1,0);
15884 arg2 = _cimg_mp_is_vector(pos)?_cimg_mp_vector_size(pos):0; // Output vector size (or 0 if scalar) 16270 arg2 = _cimg_mp_is_vector(pos)?_cimg_mp_vector_size(pos):0; // Output vector size (or 0 if scalar)
15885 CImg<uptrT>::vector((uptrT)mp_whiledo,pos,arg1,p2 - p1,code._width - p2,arg2).move_to(code,p1); 16271 CImg<uptrT>::vector((uptrT)mp_whiledo,pos,arg1,p2 - p1,code._width - p2,arg2).move_to(code,p1);
15886 _cimg_mp_return(pos); 16272 _cimg_mp_return(pos);
@@ -15889,14 +16275,11 @@ namespace cimg_library_suffixed { @@ -15889,14 +16275,11 @@ namespace cimg_library_suffixed {
15889 16275
15890 case 'g' : 16276 case 'g' :
15891 if (!std::strncmp(ss,"gauss(",6)) { // Gaussian function 16277 if (!std::strncmp(ss,"gauss(",6)) { // Gaussian function
  16278 + _cimg_mp_op("Function 'gauss()'");
15892 s1 = ss6; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1; 16279 s1 = ss6; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
15893 arg1 = compile(ss6,s1,depth1,0); 16280 arg1 = compile(ss6,s1,depth1,0);
15894 - arg2 = 1;  
15895 - if (s1<se1) {  
15896 - s2 = s1 + 1; while (s2<se1 && (*s2!=',' || level[s2 - expr._data]!=clevel1)) ++s2;  
15897 - arg2 = compile(s1 + 1,s2==se2?++s2:s2,depth1,0);  
15898 - }  
15899 - _cimg_mp_check_type(arg2,2,"Function 'gauss()'",1,0); 16281 + arg2 = s1<se1?compile(++s1,se1,depth1,0):1;
  16282 + _cimg_mp_check_type(arg2,2,1,0);
15900 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector2_vs(mp_gauss,arg1,arg2); 16283 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector2_vs(mp_gauss,arg1,arg2);
15901 if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) { 16284 if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) {
15902 val1 = mem[arg1]; 16285 val1 = mem[arg1];
@@ -15909,12 +16292,12 @@ namespace cimg_library_suffixed { @@ -15909,12 +16292,12 @@ namespace cimg_library_suffixed {
15909 16292
15910 case 'h' : 16293 case 'h' :
15911 if (!std::strncmp(ss,"hypot(",6)) { // Hypothenuse 16294 if (!std::strncmp(ss,"hypot(",6)) { // Hypothenuse
15912 - s_op = "Function 'hypot()'"; 16295 + _cimg_mp_op("Function 'hypot()'");
15913 s1 = ss6; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1; 16296 s1 = ss6; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
15914 arg1 = compile(ss6,s1,depth1,0); 16297 arg1 = compile(ss6,s1,depth1,0);
15915 - arg2 = compile(s1 + 1,se1,depth1,0);  
15916 - _cimg_mp_check_type(arg1,1,s_op,1,0);  
15917 - _cimg_mp_check_type(arg2,2,s_op,1,0); 16298 + arg2 = compile(++s1,se1,depth1,0);
  16299 + _cimg_mp_check_type(arg1,1,1,0);
  16300 + _cimg_mp_check_type(arg2,2,1,0);
15918 if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) { 16301 if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) {
15919 val1 = cimg::abs(mem[arg1]); 16302 val1 = cimg::abs(mem[arg1]);
15920 val2 = cimg::abs(mem[arg2]); 16303 val2 = cimg::abs(mem[arg2]);
@@ -15928,19 +16311,21 @@ namespace cimg_library_suffixed { @@ -15928,19 +16311,21 @@ namespace cimg_library_suffixed {
15928 16311
15929 case 'i' : 16312 case 'i' :
15930 if (*ss1=='f' && (*ss2=='(' || (*ss2 && *ss2<=' ' && *ss3=='('))) { // If..then[..else.] 16313 if (*ss1=='f' && (*ss2=='(' || (*ss2 && *ss2<=' ' && *ss3=='('))) { // If..then[..else.]
15931 - s_op = "Function 'if()'"; 16314 + _cimg_mp_op("Function 'if()'");
15932 if (*ss2<=' ') cimg::swap(*ss2,*ss3); // Allow space before opening brace 16315 if (*ss2<=' ') cimg::swap(*ss2,*ss3); // Allow space before opening brace
15933 s1 = ss3; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1; 16316 s1 = ss3; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
15934 s2 = s1 + 1; while (s2<se1 && (*s2!=',' || level[s2 - expr._data]!=clevel1)) ++s2; 16317 s2 = s1 + 1; while (s2<se1 && (*s2!=',' || level[s2 - expr._data]!=clevel1)) ++s2;
15935 arg1 = compile(ss3,s1,depth1,0); 16318 arg1 = compile(ss3,s1,depth1,0);
  16319 + _cimg_mp_check_type(arg1,1,1,0);
  16320 + if (_cimg_mp_is_constant(arg1)) {
  16321 + if ((bool)mem[arg1]) return compile(++s1,s2,depth1,0);
  16322 + else return s2<se1?compile(++s2,se1,depth1,0):0;
  16323 + }
15936 p2 = code._width; 16324 p2 = code._width;
15937 - arg2 = compile(s1 + 1,s2,depth1,0); 16325 + arg2 = compile(++s1,s2,depth1,0);
15938 p3 = code._width; 16326 p3 = code._width;
15939 - arg3 = s2>=se1?0:compile(s2 + 1,se1,depth1,0);  
15940 - _cimg_mp_check_type(arg1,1,s_op,1,0);  
15941 - _cimg_mp_check_type(arg3,3,s_op,3,_cimg_mp_vector_size(arg2));  
15942 - if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2) && _cimg_mp_is_constant(arg3))  
15943 - _cimg_mp_constant(mem[arg1]?mem[arg2]:mem[arg3]); 16327 + arg3 = s2<se1?compile(++s2,se1,depth1,0):_cimg_mp_is_vector(arg2)?vector(_cimg_mp_vector_size(arg2),0):0;
  16328 + _cimg_mp_check_type(arg3,3,_cimg_mp_is_vector(arg2)?2:1,_cimg_mp_vector_size(arg2));
15944 arg4 = _cimg_mp_is_vector(arg2)?_cimg_mp_vector_size(arg2):0; // Output vector size (or 0 if scalar) 16329 arg4 = _cimg_mp_is_vector(arg2)?_cimg_mp_vector_size(arg2):0; // Output vector size (or 0 if scalar)
15945 if (arg4) pos = vector(arg4); else pos = scalar(); 16330 if (arg4) pos = vector(arg4); else pos = scalar();
15946 CImg<uptrT>::vector((uptrT)mp_if,pos,arg1,arg2,arg3, 16331 CImg<uptrT>::vector((uptrT)mp_if,pos,arg1,arg2,arg3,
@@ -15949,12 +16334,13 @@ namespace cimg_library_suffixed { @@ -15949,12 +16334,13 @@ namespace cimg_library_suffixed {
15949 } 16334 }
15950 16335
15951 if (!std::strncmp(ss,"init(",5)) { // Init 16336 if (!std::strncmp(ss,"init(",5)) { // Init
  16337 + _cimg_mp_op("Function 'init()'");
15952 if (ss0!=expr._data || code.width()) { // (only allowed as the first instruction) 16338 if (ss0!=expr._data || code.width()) { // (only allowed as the first instruction)
15953 *se = saved_char; cimg::strellipsize(expr,64); 16339 *se = saved_char; cimg::strellipsize(expr,64);
15954 throw CImgArgumentException("[_cimg_math_parser] " 16340 throw CImgArgumentException("[_cimg_math_parser] "
15955 - "CImg<%s>::%s: Function 'init()': Init invokation not done at the " 16341 + "CImg<%s>::%s: %s: Init invokation not done at the "
15956 "beginning of expression '%s%s%s'.", 16342 "beginning of expression '%s%s%s'.",
15957 - pixel_type(),_cimg_mp_calling_function, 16343 + pixel_type(),_cimg_mp_calling_function,s_op,
15958 (ss - 4)>expr._data?"...":"", 16344 (ss - 4)>expr._data?"...":"",
15959 (ss - 4)>expr._data?ss - 4:expr._data, 16345 (ss - 4)>expr._data?ss - 4:expr._data,
15960 se<&expr.back()?"...":""); 16346 se<&expr.back()?"...":"");
@@ -15965,15 +16351,27 @@ namespace cimg_library_suffixed { @@ -15965,15 +16351,27 @@ namespace cimg_library_suffixed {
15965 } 16351 }
15966 16352
15967 if (!std::strncmp(ss,"int(",4)) { // Integer cast 16353 if (!std::strncmp(ss,"int(",4)) { // Integer cast
  16354 + _cimg_mp_op("Function 'int()'");
15968 arg1 = compile(ss4,se1,depth1,0); 16355 arg1 = compile(ss4,se1,depth1,0);
15969 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_int,arg1); 16356 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_int,arg1);
15970 if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant((long)mem[arg1]); 16357 if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant((long)mem[arg1]);
15971 _cimg_mp_scalar1(mp_int,arg1); 16358 _cimg_mp_scalar1(mp_int,arg1);
15972 } 16359 }
15973 16360
  16361 + if (!std::strncmp(ss,"inv(",4)) { // Matrix/scalar inversion
  16362 + _cimg_mp_op("Function 'inv()'");
  16363 + arg1 = compile(ss4,se1,depth1,0);
  16364 + _cimg_mp_check_matrix_square(arg1,1);
  16365 + p1 = (unsigned int)std::sqrt((float)_cimg_mp_vector_size(arg1));
  16366 + pos = vector(p1*p1);
  16367 + CImg<uptrT>::vector((uptrT)mp_inv,pos,arg1,p1).move_to(code);
  16368 + _cimg_mp_return(pos);
  16369 + }
  16370 +
15974 if (*ss1=='s') { // Family of 'is_?()' functions 16371 if (*ss1=='s') { // Family of 'is_?()' functions
15975 16372
15976 if (!std::strncmp(ss,"isbool(",7)) { // Is boolean? 16373 if (!std::strncmp(ss,"isbool(",7)) { // Is boolean?
  16374 + _cimg_mp_op("Function 'isbool()'");
15977 if (ss7==se1) _cimg_mp_return(0); 16375 if (ss7==se1) _cimg_mp_return(0);
15978 arg1 = compile(ss7,se1,depth1,0); 16376 arg1 = compile(ss7,se1,depth1,0);
15979 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_isbool,arg1); 16377 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_isbool,arg1);
@@ -15982,6 +16380,7 @@ namespace cimg_library_suffixed { @@ -15982,6 +16380,7 @@ namespace cimg_library_suffixed {
15982 } 16380 }
15983 16381
15984 if (!std::strncmp(ss,"isdir(",6)) { // Is directory? 16382 if (!std::strncmp(ss,"isdir(",6)) { // Is directory?
  16383 + _cimg_mp_op("Function 'isdir()'");
15985 *se1 = 0; 16384 *se1 = 0;
15986 is_sth = cimg::is_directory(ss6); 16385 is_sth = cimg::is_directory(ss6);
15987 *se1 = ')'; 16386 *se1 = ')';
@@ -15989,6 +16388,7 @@ namespace cimg_library_suffixed { @@ -15989,6 +16388,7 @@ namespace cimg_library_suffixed {
15989 } 16388 }
15990 16389
15991 if (!std::strncmp(ss,"isfile(",7)) { // Is file? 16390 if (!std::strncmp(ss,"isfile(",7)) { // Is file?
  16391 + _cimg_mp_op("Function 'isfile()'");
15992 *se1 = 0; 16392 *se1 = 0;
15993 is_sth = cimg::is_file(ss7); 16393 is_sth = cimg::is_file(ss7);
15994 *se1 = ')'; 16394 *se1 = ')';
@@ -15996,6 +16396,8 @@ namespace cimg_library_suffixed { @@ -15996,6 +16396,8 @@ namespace cimg_library_suffixed {
15996 } 16396 }
15997 16397
15998 if (!std::strncmp(ss,"isin(",5)) { // Is in sequence/vector? 16398 if (!std::strncmp(ss,"isin(",5)) { // Is in sequence/vector?
  16399 + if (ss5>=se1) _cimg_mp_return(0);
  16400 + _cimg_mp_op("Function 'isin()'");
15999 pos = scalar(); 16401 pos = scalar();
16000 CImg<uptrT>::vector((uptrT)mp_isin,pos).move_to(_opcode); 16402 CImg<uptrT>::vector((uptrT)mp_isin,pos).move_to(_opcode);
16001 for (s = ss5; s<se; ++s) { 16403 for (s = ss5; s<se; ++s) {
@@ -16014,6 +16416,7 @@ namespace cimg_library_suffixed { @@ -16014,6 +16416,7 @@ namespace cimg_library_suffixed {
16014 } 16416 }
16015 16417
16016 if (!std::strncmp(ss,"isinf(",6)) { // Is infinite? 16418 if (!std::strncmp(ss,"isinf(",6)) { // Is infinite?
  16419 + _cimg_mp_op("Function 'isinf()'");
16017 if (ss6==se1) _cimg_mp_return(0); 16420 if (ss6==se1) _cimg_mp_return(0);
16018 arg1 = compile(ss6,se1,depth1,0); 16421 arg1 = compile(ss6,se1,depth1,0);
16019 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_isinf,arg1); 16422 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_isinf,arg1);
@@ -16022,6 +16425,7 @@ namespace cimg_library_suffixed { @@ -16022,6 +16425,7 @@ namespace cimg_library_suffixed {
16022 } 16425 }
16023 16426
16024 if (!std::strncmp(ss,"isint(",6)) { // Is integer? 16427 if (!std::strncmp(ss,"isint(",6)) { // Is integer?
  16428 + _cimg_mp_op("Function 'isint()'");
16025 if (ss6==se1) _cimg_mp_return(0); 16429 if (ss6==se1) _cimg_mp_return(0);
16026 arg1 = compile(ss6,se1,depth1,0); 16430 arg1 = compile(ss6,se1,depth1,0);
16027 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_isint,arg1); 16431 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_isint,arg1);
@@ -16030,6 +16434,7 @@ namespace cimg_library_suffixed { @@ -16030,6 +16434,7 @@ namespace cimg_library_suffixed {
16030 } 16434 }
16031 16435
16032 if (!std::strncmp(ss,"isnan(",6)) { // Is NaN? 16436 if (!std::strncmp(ss,"isnan(",6)) { // Is NaN?
  16437 + _cimg_mp_op("Function 'isnan()'");
16033 if (ss6==se1) _cimg_mp_return(0); 16438 if (ss6==se1) _cimg_mp_return(0);
16034 arg1 = compile(ss6,se1,depth1,0); 16439 arg1 = compile(ss6,se1,depth1,0);
16035 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_isnan,arg1); 16440 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_isnan,arg1);
@@ -16038,6 +16443,7 @@ namespace cimg_library_suffixed { @@ -16038,6 +16443,7 @@ namespace cimg_library_suffixed {
16038 } 16443 }
16039 16444
16040 if (!std::strncmp(ss,"isval(",6)) { // Is value? 16445 if (!std::strncmp(ss,"isval(",6)) { // Is value?
  16446 + _cimg_mp_op("Function 'isval()'");
16041 val = 0; 16447 val = 0;
16042 if (cimg_sscanf(ss6,"%lf%c%c",&val,&sep,&end)==2 && sep==')') _cimg_mp_return(1); 16448 if (cimg_sscanf(ss6,"%lf%c%c",&val,&sep,&end)==2 && sep==')') _cimg_mp_return(1);
16043 _cimg_mp_return(0); 16449 _cimg_mp_return(0);
@@ -16048,6 +16454,7 @@ namespace cimg_library_suffixed { @@ -16048,6 +16454,7 @@ namespace cimg_library_suffixed {
16048 16454
16049 case 'l' : 16455 case 'l' :
16050 if (!std::strncmp(ss,"log(",4)) { // Natural logarithm 16456 if (!std::strncmp(ss,"log(",4)) { // Natural logarithm
  16457 + _cimg_mp_op("Function 'log()'");
16051 arg1 = compile(ss4,se1,depth1,0); 16458 arg1 = compile(ss4,se1,depth1,0);
16052 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_log,arg1); 16459 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_log,arg1);
16053 if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::log(mem[arg1])); 16460 if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::log(mem[arg1]));
@@ -16055,6 +16462,7 @@ namespace cimg_library_suffixed { @@ -16055,6 +16462,7 @@ namespace cimg_library_suffixed {
16055 } 16462 }
16056 16463
16057 if (!std::strncmp(ss,"log2(",5)) { // Base-2 logarithm 16464 if (!std::strncmp(ss,"log2(",5)) { // Base-2 logarithm
  16465 + _cimg_mp_op("Function 'log2()'");
16058 arg1 = compile(ss5,se1,depth1,0); 16466 arg1 = compile(ss5,se1,depth1,0);
16059 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_log2,arg1); 16467 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_log2,arg1);
16060 if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(cimg::log2(mem[arg1])); 16468 if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(cimg::log2(mem[arg1]));
@@ -16062,6 +16470,7 @@ namespace cimg_library_suffixed { @@ -16062,6 +16470,7 @@ namespace cimg_library_suffixed {
16062 } 16470 }
16063 16471
16064 if (!std::strncmp(ss,"log10(",6)) { // Base-10 logarithm 16472 if (!std::strncmp(ss,"log10(",6)) { // Base-10 logarithm
  16473 + _cimg_mp_op("Function 'log10()'");
16065 arg1 = compile(ss6,se1,depth1,0); 16474 arg1 = compile(ss6,se1,depth1,0);
16066 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_log10,arg1); 16475 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_log10,arg1);
16067 if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::log10(mem[arg1])); 16476 if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::log10(mem[arg1]));
@@ -16070,59 +16479,16 @@ namespace cimg_library_suffixed { @@ -16070,59 +16479,16 @@ namespace cimg_library_suffixed {
16070 break; 16479 break;
16071 16480
16072 case 'm' : 16481 case 'm' :
16073 - if (!std::strncmp(ss,"mdet(",5)) { // Matrix determinant  
16074 - arg1 = compile(ss5,se1,depth1,0);  
16075 - _cimg_mp_check_matrix_square(arg1,1,"Function 'mdet()'");  
16076 - p1 = (unsigned int)std::sqrt((float)_cimg_mp_vector_size(arg1));  
16077 - _cimg_mp_scalar2(mp_matrix_det,arg1,p1);  
16078 - }  
16079 -  
16080 - if (!std::strncmp(ss,"mdiag(",5)) { // Diagonal matrix  
16081 - arg1 = compile(ss6,se1,depth1,0);  
16082 - _cimg_mp_check_type(arg1,1,"Function 'mdiag()'",2,0);  
16083 - p1 = _cimg_mp_vector_size(arg1);  
16084 - pos = vector(p1*p1);  
16085 - CImg<uptrT>::vector((uptrT)mp_matrix_diag,pos,arg1,p1).move_to(code);  
16086 - _cimg_mp_return(pos);  
16087 - }  
16088 -  
16089 - if (!std::strncmp(ss,"meig(",5)) { // Matrix eigenvalues/eigenvector  
16090 - arg1 = compile(ss5,se1,depth1,0);  
16091 - _cimg_mp_check_matrix_square(arg1,1,"Function 'meig()'");  
16092 - p1 = (unsigned int)std::sqrt((float)_cimg_mp_vector_size(arg1));  
16093 - pos = vector((p1 + 1)*p1);  
16094 - CImg<uptrT>::vector((uptrT)mp_matrix_eig,pos,arg1,p1).move_to(code);  
16095 - _cimg_mp_return(pos);  
16096 - }  
16097 -  
16098 - if (!std::strncmp(ss,"meye(",5)) { // Matrix eigenvalues/eigenvector  
16099 - arg1 = compile(ss5,se1,depth1,0);  
16100 - _cimg_mp_check_constant(arg1,1,"Function 'meye()'",true);  
16101 - p1 = (unsigned int)mem[arg1];  
16102 - pos = vector(p1*p1);  
16103 - CImg<uptrT>::vector((uptrT)mp_matrix_eye,pos,p1).move_to(code);  
16104 - _cimg_mp_return(pos);  
16105 - }  
16106 -  
16107 - if (!std::strncmp(ss,"minv(",5)) { // Matrix inversion  
16108 - arg1 = compile(ss5,se1,depth1,0);  
16109 - _cimg_mp_check_matrix_square(arg1,1,"Function 'minv()'");  
16110 - p1 = (unsigned int)std::sqrt((float)_cimg_mp_vector_size(arg1));  
16111 - pos = vector(p1*p1);  
16112 - CImg<uptrT>::vector((uptrT)mp_matrix_inv,pos,arg1,p1).move_to(code);  
16113 - _cimg_mp_return(pos);  
16114 - }  
16115 -  
16116 - if (!std::strncmp(ss,"mmul(",5)) { // Matrix multiplication  
16117 - s_op = "Function 'mmul()'";  
16118 - s1 = ss5; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;  
16119 - arg1 = compile(ss5,s1==se2?++s1:s1,depth1,0); 16482 + if (!std::strncmp(ss,"mul(",4)) { // Matrix multiplication
  16483 + _cimg_mp_op("Function 'mul()'");
  16484 + s1 = ss4; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
  16485 + arg1 = compile(ss4,s1,depth1,0);
16120 s2 = s1 + 1; while (s2<se1 && (*s2!=',' || level[s2 - expr._data]!=clevel1)) ++s2; 16486 s2 = s1 + 1; while (s2<se1 && (*s2!=',' || level[s2 - expr._data]!=clevel1)) ++s2;
16121 - arg2 = compile(s1 + 1,s2==se2?++s2:s2,depth1,0);  
16122 - if (s2<se1) arg3 = compile(++s2,se1,depth1,0); else arg3 = 1;  
16123 - _cimg_mp_check_type(arg1,1,s_op,2,0);  
16124 - _cimg_mp_check_type(arg2,2,s_op,2,0);  
16125 - _cimg_mp_check_constant(arg3,3,s_op,true); 16487 + arg2 = compile(++s1,s2,depth1,0);
  16488 + arg3 = s2<se1?compile(++s2,se1,depth1,0):1;
  16489 + _cimg_mp_check_type(arg1,1,2,0);
  16490 + _cimg_mp_check_type(arg2,2,2,0);
  16491 + _cimg_mp_check_constant(arg3,3,true);
16126 p1 = _cimg_mp_vector_size(arg1); 16492 p1 = _cimg_mp_vector_size(arg1);
16127 p2 = _cimg_mp_vector_size(arg2); 16493 p2 = _cimg_mp_vector_size(arg2);
16128 p3 = (unsigned int)mem[arg3]; 16494 p3 = (unsigned int)mem[arg3];
@@ -16131,7 +16497,7 @@ namespace cimg_library_suffixed { @@ -16131,7 +16497,7 @@ namespace cimg_library_suffixed {
16131 if (arg4*arg5!=p1 || arg5*p3!=p2) { 16497 if (arg4*arg5!=p1 || arg5*p3!=p2) {
16132 *se = saved_char; cimg::strellipsize(expr,64); 16498 *se = saved_char; cimg::strellipsize(expr,64);
16133 throw CImgArgumentException("[_cimg_math_parser] " 16499 throw CImgArgumentException("[_cimg_math_parser] "
16134 - "CImg<%s>::%s: %s: Sizes of first and second arguments ('%s' and '%s') " 16500 + "CImg<%s>::%s: %s: Types of first and second arguments ('%s' and '%s') "
16135 "do not match for third argument 'nb_colsB=%u', " 16501 "do not match for third argument 'nb_colsB=%u', "
16136 "in expression '%s%s%s'.", 16502 "in expression '%s%s%s'.",
16137 pixel_type(),_cimg_mp_calling_function,s_op, 16503 pixel_type(),_cimg_mp_calling_function,s_op,
@@ -16144,95 +16510,12 @@ namespace cimg_library_suffixed { @@ -16144,95 +16510,12 @@ namespace cimg_library_suffixed {
16144 CImg<uptrT>::vector((uptrT)mp_matrix_mul,pos,arg1,arg2,arg4,arg5,p3).move_to(code); 16510 CImg<uptrT>::vector((uptrT)mp_matrix_mul,pos,arg1,arg2,arg4,arg5,p3).move_to(code);
16145 _cimg_mp_return(pos); 16511 _cimg_mp_return(pos);
16146 } 16512 }
16147 -  
16148 - if (!std::strncmp(ss,"mrot(",5)) { // Rotation matrix  
16149 - s_op = "Function 'mrot()'";  
16150 - s1 = ss5; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;  
16151 - arg1 = compile(ss5,s1==se2?++s1:s1,depth1,0);  
16152 - s2 = s1 + 1; while (s2<se1 && (*s2!=',' || level[s2 - expr._data]!=clevel1)) ++s2;  
16153 - arg2 = compile(s1 + 1,s2==se2?++s2:s2,depth1,0);  
16154 - s3 = s2 + 1; while (s3<se1 && (*s3!=',' || level[s3 - expr._data]!=clevel1)) ++s3;  
16155 - arg3 = compile(s2 + 1,s3==se2?++s3:s3,depth1,0);  
16156 - arg4 = compile(++s3,se1,depth1,0);  
16157 - _cimg_mp_check_type(arg1,1,s_op,1,0);  
16158 - _cimg_mp_check_type(arg2,2,s_op,1,0);  
16159 - _cimg_mp_check_type(arg3,3,s_op,1,0);  
16160 - _cimg_mp_check_type(arg4,4,s_op,1,0);  
16161 - pos = vector(9);  
16162 - CImg<uptrT>::vector((uptrT)mp_matrix_rot,pos,arg1,arg2,arg3,arg4).move_to(code);  
16163 - _cimg_mp_return(pos);  
16164 - }  
16165 -  
16166 - if (!std::strncmp(ss,"msolve(",7)) { // Solve linear system  
16167 - s_op = "Function 'msolve()'";  
16168 - s1 = ss7; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;  
16169 - arg1 = compile(ss7,s1==se2?++s1:s1,depth1,0);  
16170 - s2 = s1 + 1; while (s2<se1 && (*s2!=',' || level[s2 - expr._data]!=clevel1)) ++s2;  
16171 - arg2 = compile(s1 + 1,s2==se2?++s2:s2,depth1,0);  
16172 - if (s2<se1) arg3 = compile(++s2,se1,depth1,0); else arg3 = 1;  
16173 - _cimg_mp_check_type(arg1,1,s_op,2,0);  
16174 - _cimg_mp_check_type(arg2,2,s_op,2,0);  
16175 - _cimg_mp_check_constant(arg3,3,s_op,true);  
16176 - p1 = _cimg_mp_vector_size(arg1);  
16177 - p2 = _cimg_mp_vector_size(arg2);  
16178 - p3 = (unsigned int)mem[arg3];  
16179 - arg5 = p2/p3;  
16180 - arg4 = p1/arg5;  
16181 - if (arg4*arg5!=p1 || arg4*p3!=p2) {  
16182 - *se = saved_char; cimg::strellipsize(expr,64);  
16183 - throw CImgArgumentException("[_cimg_math_parser] "  
16184 - "CImg<%s>::%s: %s: Sizes of first and second arguments ('%s' and '%s') "  
16185 - "do not match for third argument 'nb_colsB=%u', "  
16186 - "in expression '%s%s%s'.",  
16187 - pixel_type(),_cimg_mp_calling_function,s_op,  
16188 - s_type(arg1)._data,s_type(arg2)._data,p3,  
16189 - (ss - 4)>expr._data?"...":"",  
16190 - (ss - 4)>expr._data?ss - 4:expr._data,  
16191 - se<&expr.back()?"...":"");  
16192 - }  
16193 - pos = vector(arg5*p3);  
16194 - CImg<uptrT>::vector((uptrT)mp_matrix_solve,pos,arg1,arg2,arg4,arg5,p3).move_to(code);  
16195 - _cimg_mp_return(pos);  
16196 - }  
16197 -  
16198 - if (!std::strncmp(ss,"mtrace(",7)) { // Matrix trace  
16199 - arg1 = compile(ss7,se1,depth1,0);  
16200 - _cimg_mp_check_matrix_square(arg1,1,"Function 'mtrace()'");  
16201 - p1 = (unsigned int)std::sqrt((float)_cimg_mp_vector_size(arg1));  
16202 - _cimg_mp_scalar2(mp_matrix_trace,arg1,p1);  
16203 - }  
16204 -  
16205 - if (!std::strncmp(ss,"mtrans(",7)) { // Matrix transpose  
16206 - s_op = "Function 'mtrans()'";  
16207 - s1 = ss7; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;  
16208 - arg1 = compile(ss7,s1==se2?++s1:s1,depth1,0);  
16209 - arg2 = compile(++s1,se1,depth1,0);  
16210 - _cimg_mp_check_type(arg1,1,s_op,2,0);  
16211 - _cimg_mp_check_constant(arg2,2,s_op,true);  
16212 - p1 = _cimg_mp_vector_size(arg1);  
16213 - p2 = (unsigned int)mem[arg2];  
16214 - p3 = p1/p2;  
16215 - if (p2*p3!=p1) {  
16216 - *se = saved_char; cimg::strellipsize(expr,64);  
16217 - throw CImgArgumentException("[_cimg_math_parser] "  
16218 - "CImg<%s>::%s: %s: Size of first argument ('%s') does not match"  
16219 - "for second specified argument 'nb_cols=%u', "  
16220 - "in expression '%s%s%s'.",  
16221 - pixel_type(),_cimg_mp_calling_function,s_op,  
16222 - s_type(arg1)._data,p2,  
16223 - (ss - 4)>expr._data?"...":"",  
16224 - (ss - 4)>expr._data?ss - 4:expr._data,  
16225 - se<&expr.back()?"...":"");  
16226 - }  
16227 - pos = vector(p3*p2);  
16228 - CImg<uptrT>::vector((uptrT)mp_matrix_trans,pos,arg1,p2,p3).move_to(code);  
16229 - _cimg_mp_return(pos);  
16230 - }  
16231 break; 16513 break;
16232 16514
16233 case 'n' : 16515 case 'n' :
16234 if (!std::strncmp(ss,"narg(",5)) { // Number of arguments 16516 if (!std::strncmp(ss,"narg(",5)) { // Number of arguments
16235 - if (*ss5==')') _cimg_mp_return(0); 16517 + _cimg_mp_op("Function 'narg()'");
  16518 + if (ss5>=se1) _cimg_mp_return(0);
16236 arg1 = 0; 16519 arg1 = 0;
16237 for (s = ss5; s<se; ++s) { 16520 for (s = ss5; s<se; ++s) {
16238 ns = s; while (ns<se && (*ns!=',' || level[ns - expr._data]!=clevel1) && 16521 ns = s; while (ns<se && (*ns!=',' || level[ns - expr._data]!=clevel1) &&
@@ -16244,6 +16527,7 @@ namespace cimg_library_suffixed { @@ -16244,6 +16527,7 @@ namespace cimg_library_suffixed {
16244 16527
16245 if ((cimg_sscanf(ss,"norm%u%c",&(arg1=~0U),&sep)==2 && sep=='(') || 16528 if ((cimg_sscanf(ss,"norm%u%c",&(arg1=~0U),&sep)==2 && sep=='(') ||
16246 !std::strncmp(ss,"norminf(",8)) { // Lp norm 16529 !std::strncmp(ss,"norminf(",8)) { // Lp norm
  16530 + _cimg_mp_op("Function 'normP()'");
16247 pos = scalar(); 16531 pos = scalar();
16248 switch (arg1) { 16532 switch (arg1) {
16249 case 0 : CImg<uptrT>::vector((uptrT)mp_norm0,pos).move_to(_opcode); break; 16533 case 0 : CImg<uptrT>::vector((uptrT)mp_norm0,pos).move_to(_opcode); break;
@@ -16272,6 +16556,7 @@ namespace cimg_library_suffixed { @@ -16272,6 +16556,7 @@ namespace cimg_library_suffixed {
16272 16556
16273 case 'p' : 16557 case 'p' :
16274 if (!std::strncmp(ss,"print(",6)) { // Print expression 16558 if (!std::strncmp(ss,"print(",6)) { // Print expression
  16559 + _cimg_mp_op("Function 'print()'");
16275 pos = compile(ss6,se1,depth1,p_ref); 16560 pos = compile(ss6,se1,depth1,p_ref);
16276 *se1 = 0; 16561 *se1 = 0;
16277 if (_cimg_mp_is_vector(pos)) // Vector 16562 if (_cimg_mp_is_vector(pos)) // Vector
@@ -16287,14 +16572,11 @@ namespace cimg_library_suffixed { @@ -16287,14 +16572,11 @@ namespace cimg_library_suffixed {
16287 16572
16288 case 'r' : 16573 case 'r' :
16289 if (!std::strncmp(ss,"rol(",4) || !std::strncmp(ss,"ror(",4)) { // Bitwise rotation 16574 if (!std::strncmp(ss,"rol(",4) || !std::strncmp(ss,"ror(",4)) { // Bitwise rotation
  16575 + _cimg_mp_op(ss[2]=='l'?"Function 'rol()'":"Function 'ror()'");
16290 s1 = ss4; while (s1<se1 && (*s1!=',' || level[s1-expr._data]!=clevel1)) ++s1; 16576 s1 = ss4; while (s1<se1 && (*s1!=',' || level[s1-expr._data]!=clevel1)) ++s1;
16291 - arg1 = compile(ss4,s1==se2?++s1:s1,depth1,0);  
16292 - arg2 = 1;  
16293 - if (s1<se1) {  
16294 - s2 = s1 + 1; while (s2<se1 && (*s2!=',' || level[s2-expr._data]!=clevel1)) ++s2;  
16295 - arg2 = compile(s1 + 1,se1,depth1,0);  
16296 - }  
16297 - _cimg_mp_check_type(arg2,2,"Function 'rol()'",1,0); 16577 + arg1 = compile(ss4,s1,depth1,0);
  16578 + arg2 = s1<se1?compile(++s1,se1,depth1,0):1;
  16579 + _cimg_mp_check_type(arg2,2,1,0);
16298 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector2_vs(*ss2=='l'?mp_rol:mp_ror,arg1,arg2); 16580 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector2_vs(*ss2=='l'?mp_rol:mp_ror,arg1,arg2);
16299 if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) 16581 if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2))
16300 _cimg_mp_constant(*ss2=='l'?cimg::rol(mem[arg1],(unsigned int)mem[arg2]): 16582 _cimg_mp_constant(*ss2=='l'?cimg::rol(mem[arg1],(unsigned int)mem[arg2]):
@@ -16302,19 +16584,56 @@ namespace cimg_library_suffixed { @@ -16302,19 +16584,56 @@ namespace cimg_library_suffixed {
16302 _cimg_mp_scalar2(*ss2=='l'?mp_rol:mp_ror,arg1,arg2); 16584 _cimg_mp_scalar2(*ss2=='l'?mp_rol:mp_ror,arg1,arg2);
16303 } 16585 }
16304 16586
  16587 + if (!std::strncmp(ss,"rot(",4)) { // 2d/3d rotation matrix
  16588 + _cimg_mp_op("Function 'rot()'");
  16589 + s1 = ss4; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
  16590 + arg1 = compile(ss4,s1,depth1,0);
  16591 + if (s1<se1) { // 3d rotation
  16592 + _cimg_mp_check_type(arg1,1,3,3);
  16593 + is_sth = false; // Is coordinates as vector?
  16594 + if (_cimg_mp_is_vector(arg1)) { // Coordinates specified as a vector
  16595 + is_sth = true;
  16596 + p2 = _cimg_mp_vector_size(arg1);
  16597 + ++arg1;
  16598 + arg2 = arg3 = 0;
  16599 + if (p2>1) {
  16600 + arg2 = arg1 + 1;
  16601 + if (p2>2) arg3 = arg2 + 1;
  16602 + }
  16603 + arg4 = compile(++s1,se1,depth1,0);
  16604 + } else {
  16605 + s2 = s1 + 1; while (s2<se1 && (*s2!=',' || level[s2 - expr._data]!=clevel1)) ++s2;
  16606 + arg2 = compile(++s1,s2,depth1,0);
  16607 + s3 = s2 + 1; while (s3<se1 && (*s3!=',' || level[s3 - expr._data]!=clevel1)) ++s3;
  16608 + arg3 = compile(++s2,s3,depth1,0);
  16609 + arg4 = compile(++s3,se1,depth1,0);
  16610 + _cimg_mp_check_type(arg2,2,1,0);
  16611 + _cimg_mp_check_type(arg3,3,1,0);
  16612 + }
  16613 + _cimg_mp_check_type(arg4,is_sth?2:4,1,0);
  16614 + pos = vector(9);
  16615 + CImg<uptrT>::vector((uptrT)mp_rot3d,pos,arg1,arg2,arg3,arg4).move_to(code);
  16616 + } else { // 2d rotation
  16617 + _cimg_mp_check_type(arg1,1,1,0);
  16618 + pos = vector(4);
  16619 + CImg<uptrT>::vector((uptrT)mp_rot2d,pos,arg1).move_to(code);
  16620 + }
  16621 + _cimg_mp_return(pos);
  16622 + }
  16623 +
16305 if (!std::strncmp(ss,"round(",6)) { // Value rounding 16624 if (!std::strncmp(ss,"round(",6)) { // Value rounding
16306 - s_op = "Function 'round()'"; 16625 + _cimg_mp_op("Function 'round()'");
16307 s1 = ss6; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1; 16626 s1 = ss6; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
16308 - arg1 = compile(ss6,s1==se2?++s1:s1,depth1,0); 16627 + arg1 = compile(ss6,s1,depth1,0);
16309 arg2 = 1; 16628 arg2 = 1;
16310 arg3 = 0; 16629 arg3 = 0;
16311 if (s1<se1) { 16630 if (s1<se1) {
16312 s2 = s1 + 1; while (s2<se1 && (*s2!=',' || level[s2 - expr._data]!=clevel1)) ++s2; 16631 s2 = s1 + 1; while (s2<se1 && (*s2!=',' || level[s2 - expr._data]!=clevel1)) ++s2;
16313 - arg2 = compile(s1 + 1,s2==se2?++s2:s2,depth1,0);  
16314 - if (s2<se1) arg3 = compile(s2 + 1,se1,depth1,0); 16632 + arg2 = compile(++s1,s2,depth1,0);
  16633 + arg3 = s2<se1?compile(++s2,se1,depth1,0):0;
16315 } 16634 }
16316 - _cimg_mp_check_type(arg2,2,s_op,1,0);  
16317 - _cimg_mp_check_type(arg3,3,s_op,1,0); 16635 + _cimg_mp_check_type(arg2,2,1,0);
  16636 + _cimg_mp_check_type(arg3,3,1,0);
16318 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector3_vss(mp_round,arg1,arg2,arg3); 16637 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector3_vss(mp_round,arg1,arg2,arg3);
16319 if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2) && _cimg_mp_is_constant(arg3)) 16638 if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2) && _cimg_mp_is_constant(arg3))
16320 _cimg_mp_constant(cimg::round(mem[arg1],mem[arg2],(int)mem[arg3])); 16639 _cimg_mp_constant(cimg::round(mem[arg1],mem[arg2],(int)mem[arg3]));
@@ -16324,6 +16643,7 @@ namespace cimg_library_suffixed { @@ -16324,6 +16643,7 @@ namespace cimg_library_suffixed {
16324 16643
16325 case 's' : 16644 case 's' :
16326 if (!std::strncmp(ss,"sign(",5)) { // Sign 16645 if (!std::strncmp(ss,"sign(",5)) { // Sign
  16646 + _cimg_mp_op("Function 'sign()'");
16327 arg1 = compile(ss5,se1,depth1,0); 16647 arg1 = compile(ss5,se1,depth1,0);
16328 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_sign,arg1); 16648 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_sign,arg1);
16329 if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(cimg::sign(mem[arg1])); 16649 if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(cimg::sign(mem[arg1]));
@@ -16331,6 +16651,7 @@ namespace cimg_library_suffixed { @@ -16331,6 +16651,7 @@ namespace cimg_library_suffixed {
16331 } 16651 }
16332 16652
16333 if (!std::strncmp(ss,"sin(",4)) { // Sine 16653 if (!std::strncmp(ss,"sin(",4)) { // Sine
  16654 + _cimg_mp_op("Function 'sin()'");
16334 arg1 = compile(ss4,se1,depth1,0); 16655 arg1 = compile(ss4,se1,depth1,0);
16335 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_sin,arg1); 16656 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_sin,arg1);
16336 if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::sin(mem[arg1])); 16657 if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::sin(mem[arg1]));
@@ -16338,13 +16659,23 @@ namespace cimg_library_suffixed { @@ -16338,13 +16659,23 @@ namespace cimg_library_suffixed {
16338 } 16659 }
16339 16660
16340 if (!std::strncmp(ss,"sinc(",5)) { // Sine cardinal 16661 if (!std::strncmp(ss,"sinc(",5)) { // Sine cardinal
  16662 + _cimg_mp_op("Function 'sinc()'");
16341 arg1 = compile(ss5,se1,depth1,0); 16663 arg1 = compile(ss5,se1,depth1,0);
16342 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_sinc,arg1); 16664 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_sinc,arg1);
16343 if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(cimg::sinc(mem[arg1])); 16665 if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(cimg::sinc(mem[arg1]));
16344 _cimg_mp_scalar1(mp_sinc,arg1); 16666 _cimg_mp_scalar1(mp_sinc,arg1);
16345 } 16667 }
16346 16668
  16669 + if (!std::strncmp(ss,"single(",7)) { // Force single thread execution
  16670 + _cimg_mp_op("Function 'single()'");
  16671 + p1 = code._width;
  16672 + arg1 = compile(ss7,se1,depth1,p_ref);
  16673 + CImg<uptrT>::vector((uptrT)mp_single,arg1,code._width - p1).move_to(code,p1);
  16674 + _cimg_mp_return(arg1);
  16675 + }
  16676 +
16347 if (!std::strncmp(ss,"sinh(",5)) { // Hyperbolic sine 16677 if (!std::strncmp(ss,"sinh(",5)) { // Hyperbolic sine
  16678 + _cimg_mp_op("Function 'sinh()'");
16348 arg1 = compile(ss5,se1,depth1,0); 16679 arg1 = compile(ss5,se1,depth1,0);
16349 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_sinh,arg1); 16680 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_sinh,arg1);
16350 if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::sinh(mem[arg1])); 16681 if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::sinh(mem[arg1]));
@@ -16352,24 +16683,76 @@ namespace cimg_library_suffixed { @@ -16352,24 +16683,76 @@ namespace cimg_library_suffixed {
16352 } 16683 }
16353 16684
16354 if (!std::strncmp(ss,"size(",5)) { // Vector size. 16685 if (!std::strncmp(ss,"size(",5)) { // Vector size.
  16686 + _cimg_mp_op("Function 'size()'");
16355 arg1 = compile(ss5,se1,depth1,0); 16687 arg1 = compile(ss5,se1,depth1,0);
16356 _cimg_mp_constant(_cimg_mp_is_scalar(arg1)?0:_cimg_mp_vector_size(arg1)); 16688 _cimg_mp_constant(_cimg_mp_is_scalar(arg1)?0:_cimg_mp_vector_size(arg1));
16357 } 16689 }
16358 16690
  16691 + if (!std::strncmp(ss,"solve(",6)) { // Solve linear system
  16692 + _cimg_mp_op("Function 'solve()'");
  16693 + s1 = ss6; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
  16694 + arg1 = compile(ss6,s1,depth1,0);
  16695 + s2 = s1 + 1; while (s2<se1 && (*s2!=',' || level[s2 - expr._data]!=clevel1)) ++s2;
  16696 + arg2 = compile(++s1,s2,depth1,0);
  16697 + arg3 = s2<se1?compile(++s2,se1,depth1,0):1;
  16698 + _cimg_mp_check_type(arg1,1,2,0);
  16699 + _cimg_mp_check_type(arg2,2,2,0);
  16700 + _cimg_mp_check_constant(arg3,3,true);
  16701 + p1 = _cimg_mp_vector_size(arg1);
  16702 + p2 = _cimg_mp_vector_size(arg2);
  16703 + p3 = (unsigned int)mem[arg3];
  16704 + arg5 = p2/p3;
  16705 + arg4 = p1/arg5;
  16706 + if (arg4*arg5!=p1 || arg5*p3!=p2) {
  16707 + *se = saved_char; cimg::strellipsize(expr,64);
  16708 + throw CImgArgumentException("[_cimg_math_parser] "
  16709 + "CImg<%s>::%s: %s: Types of first and second arguments ('%s' and '%s') "
  16710 + "do not match for third argument 'nb_colsB=%u', "
  16711 + "in expression '%s%s%s'.",
  16712 + pixel_type(),_cimg_mp_calling_function,s_op,
  16713 + s_type(arg1)._data,s_type(arg2)._data,p3,
  16714 + (ss - 4)>expr._data?"...":"",
  16715 + (ss - 4)>expr._data?ss - 4:expr._data,
  16716 + se<&expr.back()?"...":"");
  16717 + }
  16718 + pos = vector(arg4*p3);
  16719 + CImg<uptrT>::vector((uptrT)mp_solve,pos,arg1,arg2,arg4,arg5,p3).move_to(code);
  16720 + _cimg_mp_return(pos);
  16721 + }
  16722 +
16359 if (!std::strncmp(ss,"sort(",5)) { // Sort vector 16723 if (!std::strncmp(ss,"sort(",5)) { // Sort vector
16360 - s_op = "Function 'sort()'"; 16724 + _cimg_mp_op("Function 'sort()'");
16361 s1 = ss6; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1; 16725 s1 = ss6; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
16362 arg1 = compile(ss5,s1,depth1,0); 16726 arg1 = compile(ss5,s1,depth1,0);
16363 - if (s1<se1) arg2 = compile(++s1,se1,depth1,0); else arg2 = 1;  
16364 - _cimg_mp_check_type(arg1,1,s_op,2,0);  
16365 - _cimg_mp_check_type(arg2,2,s_op,1,0); 16727 + arg2 = arg3 = 1;
  16728 + if (s1<se1) {
  16729 + s0 = ++s1; while (s0<se1 && (*s0!=',' || level[s0 - expr._data]!=clevel1)) ++s0;
  16730 + arg2 = compile(s1,s0,depth1,0);
  16731 + arg3 = s0<se1?compile(++s0,se1,depth1,0):1;
  16732 + }
  16733 + _cimg_mp_check_type(arg1,1,2,0);
  16734 + _cimg_mp_check_type(arg2,2,1,0);
  16735 + _cimg_mp_check_constant(arg3,3,true);
  16736 + arg3 = (unsigned int)mem[arg3];
16366 p1 = _cimg_mp_vector_size(arg1); 16737 p1 = _cimg_mp_vector_size(arg1);
  16738 + if (p1%arg3) {
  16739 + *se = saved_char; cimg::strellipsize(expr,64);
  16740 + throw CImgArgumentException("[_cimg_math_parser] "
  16741 + "CImg<%s>::%s: %s: Invalid specified chunk size (%u) for first argument "
  16742 + "('%s'), in expression '%s%s%s'.",
  16743 + pixel_type(),_cimg_mp_calling_function,s_op,
  16744 + arg3,s_type(arg1)._data,
  16745 + (ss - 4)>expr._data?"...":"",
  16746 + (ss - 4)>expr._data?ss - 4:expr._data,
  16747 + se<&expr.back()?"...":"");
  16748 + }
16367 pos = vector(p1); 16749 pos = vector(p1);
16368 - CImg<uptrT>::vector((uptrT)mp_vector_sort,pos,arg1,p1,arg2).move_to(code); 16750 + CImg<uptrT>::vector((uptrT)mp_sort,pos,arg1,p1,arg2,arg3).move_to(code);
16369 _cimg_mp_return(pos); 16751 _cimg_mp_return(pos);
16370 } 16752 }
16371 16753
16372 if (!std::strncmp(ss,"sqr(",4)) { // Square 16754 if (!std::strncmp(ss,"sqr(",4)) { // Square
  16755 + _cimg_mp_op("Function 'sqr()'");
16373 arg1 = compile(ss4,se1,depth1,0); 16756 arg1 = compile(ss4,se1,depth1,0);
16374 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_sqr,arg1); 16757 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_sqr,arg1);
16375 if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(cimg::sqr(mem[arg1])); 16758 if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(cimg::sqr(mem[arg1]));
@@ -16377,6 +16760,7 @@ namespace cimg_library_suffixed { @@ -16377,6 +16760,7 @@ namespace cimg_library_suffixed {
16377 } 16760 }
16378 16761
16379 if (!std::strncmp(ss,"sqrt(",5)) { // Square root 16762 if (!std::strncmp(ss,"sqrt(",5)) { // Square root
  16763 + _cimg_mp_op("Function 'sqrt()'");
16380 arg1 = compile(ss5,se1,depth1,0); 16764 arg1 = compile(ss5,se1,depth1,0);
16381 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_sqrt,arg1); 16765 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_sqrt,arg1);
16382 if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::sqrt(mem[arg1])); 16766 if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::sqrt(mem[arg1]));
@@ -16386,6 +16770,7 @@ namespace cimg_library_suffixed { @@ -16386,6 +16770,7 @@ namespace cimg_library_suffixed {
16386 16770
16387 case 't' : 16771 case 't' :
16388 if (!std::strncmp(ss,"tan(",4)) { // Tangent 16772 if (!std::strncmp(ss,"tan(",4)) { // Tangent
  16773 + _cimg_mp_op("Function 'tan()'");
16389 arg1 = compile(ss4,se1,depth1,0); 16774 arg1 = compile(ss4,se1,depth1,0);
16390 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_tan,arg1); 16775 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_tan,arg1);
16391 if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::tan(mem[arg1])); 16776 if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::tan(mem[arg1]));
@@ -16393,20 +16778,57 @@ namespace cimg_library_suffixed { @@ -16393,20 +16778,57 @@ namespace cimg_library_suffixed {
16393 } 16778 }
16394 16779
16395 if (!std::strncmp(ss,"tanh(",5)) { // Hyperbolic tangent 16780 if (!std::strncmp(ss,"tanh(",5)) { // Hyperbolic tangent
  16781 + _cimg_mp_op("Function 'tanh()'");
16396 arg1 = compile(ss5,se1,depth1,0); 16782 arg1 = compile(ss5,se1,depth1,0);
16397 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_tanh,arg1); 16783 if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_tanh,arg1);
16398 if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::tanh(mem[arg1])); 16784 if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::tanh(mem[arg1]));
16399 _cimg_mp_scalar1(mp_tanh,arg1); 16785 _cimg_mp_scalar1(mp_tanh,arg1);
16400 } 16786 }
  16787 +
  16788 + if (!std::strncmp(ss,"trace(",6)) { // Matrix trace
  16789 + _cimg_mp_op("Function 'trace()'");
  16790 + arg1 = compile(ss6,se1,depth1,0);
  16791 + _cimg_mp_check_matrix_square(arg1,1);
  16792 + p1 = (unsigned int)std::sqrt((float)_cimg_mp_vector_size(arg1));
  16793 + _cimg_mp_scalar2(mp_trace,arg1,p1);
  16794 + }
  16795 +
  16796 + if (!std::strncmp(ss,"transp(",7)) { // Matrix transpose
  16797 + _cimg_mp_op("Function 'transp()'");
  16798 + s1 = ss7; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
  16799 + arg1 = compile(ss7,s1,depth1,0);
  16800 + arg2 = compile(++s1,se1,depth1,0);
  16801 + _cimg_mp_check_type(arg1,1,2,0);
  16802 + _cimg_mp_check_constant(arg2,2,true);
  16803 + p1 = _cimg_mp_vector_size(arg1);
  16804 + p2 = (unsigned int)mem[arg2];
  16805 + p3 = p1/p2;
  16806 + if (p2*p3!=p1) {
  16807 + *se = saved_char; cimg::strellipsize(expr,64);
  16808 + throw CImgArgumentException("[_cimg_math_parser] "
  16809 + "CImg<%s>::%s: %s: Size of first argument ('%s') does not match"
  16810 + "for second specified argument 'nb_cols=%u', "
  16811 + "in expression '%s%s%s'.",
  16812 + pixel_type(),_cimg_mp_calling_function,s_op,
  16813 + s_type(arg1)._data,p2,
  16814 + (ss - 4)>expr._data?"...":"",
  16815 + (ss - 4)>expr._data?ss - 4:expr._data,
  16816 + se<&expr.back()?"...":"");
  16817 + }
  16818 + pos = vector(p3*p2);
  16819 + CImg<uptrT>::vector((uptrT)mp_transp,pos,arg1,p2,p3).move_to(code);
  16820 + _cimg_mp_return(pos);
  16821 + }
16401 break; 16822 break;
16402 16823
16403 case 'u' : 16824 case 'u' :
16404 if (*ss1=='(') { // Random value with uniform distribution 16825 if (*ss1=='(') { // Random value with uniform distribution
  16826 + _cimg_mp_op("Function 'u()'");
16405 if (*ss2==')') _cimg_mp_scalar2(mp_u,0,1); 16827 if (*ss2==')') _cimg_mp_scalar2(mp_u,0,1);
16406 s1 = ss2; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1; 16828 s1 = ss2; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
16407 arg1 = compile(ss2,s1,depth1,0); 16829 arg1 = compile(ss2,s1,depth1,0);
16408 - if (s1<se1) arg2 = compile(s1 + 1,se1,depth1,0); else { arg2 = arg1; arg1 = 0; }  
16409 - _cimg_mp_check_type(arg2,2,"Function 'u()'",3,_cimg_mp_vector_size(arg1)); 16830 + if (s1<se1) arg2 = compile(++s1,se1,depth1,0); else { arg2 = arg1; arg1 = 0; }
  16831 + _cimg_mp_check_type(arg2,2,3,_cimg_mp_vector_size(arg1));
16410 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_u,arg1,arg2); 16832 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_u,arg1,arg2);
16411 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_u,arg1,arg2); 16833 if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_u,arg1,arg2);
16412 if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_u,arg1,arg2); 16834 if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_u,arg1,arg2);
@@ -16417,9 +16839,10 @@ namespace cimg_library_suffixed { @@ -16417,9 +16839,10 @@ namespace cimg_library_suffixed {
16417 case 'v' : 16839 case 'v' :
16418 if ((cimg_sscanf(ss,"vector%u%c",&(arg1=~0U),&sep)==2 && sep=='(' && arg1>0) || 16840 if ((cimg_sscanf(ss,"vector%u%c",&(arg1=~0U),&sep)==2 && sep=='(' && arg1>0) ||
16419 !std::strncmp(ss,"vector(",7)) { // Vector 16841 !std::strncmp(ss,"vector(",7)) { // Vector
  16842 + _cimg_mp_op("Function 'vector()'");
16420 arg2 = 0; // Number of specified values. 16843 arg2 = 0; // Number of specified values.
16421 s = std::strchr(ss6,'(') + 1; 16844 s = std::strchr(ss6,'(') + 1;
16422 - if (*s!=')' || arg1==~0U) for (; s<se; ++s) { 16845 + if (s<se1 || arg1==~0U) for (; s<se; ++s) {
16423 ns = s; while (ns<se && (*ns!=',' || level[ns - expr._data]!=clevel1) && 16846 ns = s; while (ns<se && (*ns!=',' || level[ns - expr._data]!=clevel1) &&
16424 (*ns!=')' || level[ns - expr._data]!=clevel)) ++ns; 16847 (*ns!=')' || level[ns - expr._data]!=clevel)) ++ns;
16425 arg3 = compile(s,ns,depth1,0); 16848 arg3 = compile(s,ns,depth1,0);
@@ -16431,7 +16854,7 @@ namespace cimg_library_suffixed { @@ -16431,7 +16854,7 @@ namespace cimg_library_suffixed {
16431 s = ns; 16854 s = ns;
16432 } 16855 }
16433 if (arg1==~0U) arg1 = arg2; 16856 if (arg1==~0U) arg1 = arg2;
16434 - _cimg_mp_check_vector0(arg1,"Function 'vector()'"); 16857 + _cimg_mp_check_vector0(arg1);
16435 pos = vector(arg1); 16858 pos = vector(arg1);
16436 _opcode.insert(CImg<uptrT>::vector((uptrT)mp_vector_init,pos,arg1),0); 16859 _opcode.insert(CImg<uptrT>::vector((uptrT)mp_vector_init,pos,arg1),0);
16437 (_opcode>'y').move_to(code); 16860 (_opcode>'y').move_to(code);
@@ -16441,13 +16864,14 @@ namespace cimg_library_suffixed { @@ -16441,13 +16864,14 @@ namespace cimg_library_suffixed {
16441 16864
16442 case 'w' : 16865 case 'w' :
16443 if (!std::strncmp(ss,"whiledo",7) && (*ss7=='(' || (*ss7 && *ss7<=' ' && *ss8=='('))) { // While...do 16866 if (!std::strncmp(ss,"whiledo",7) && (*ss7=='(' || (*ss7 && *ss7<=' ' && *ss8=='('))) { // While...do
  16867 + _cimg_mp_op("Function 'whiledo()'");
16444 if (*ss7<=' ') cimg::swap(*ss7,*ss8); // Allow space before opening brace 16868 if (*ss7<=' ') cimg::swap(*ss7,*ss8); // Allow space before opening brace
16445 s1 = ss8; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1; 16869 s1 = ss8; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
16446 p1 = code._width; 16870 p1 = code._width;
16447 arg1 = compile(ss8,s1,depth1,0); 16871 arg1 = compile(ss8,s1,depth1,0);
16448 p2 = code._width; 16872 p2 = code._width;
16449 - pos = compile(s1 + 1,se1,depth1,0);  
16450 - _cimg_mp_check_type(arg1,1,"Function 'whiledo()'",1,0); 16873 + pos = compile(++s1,se1,depth1,0);
  16874 + _cimg_mp_check_type(arg1,1,1,0);
16451 arg2 = _cimg_mp_is_vector(pos)?_cimg_mp_vector_size(pos):0; // Output vector size (or 0 if scalar) 16875 arg2 = _cimg_mp_is_vector(pos)?_cimg_mp_vector_size(pos):0; // Output vector size (or 0 if scalar)
16452 CImg<uptrT>::vector((uptrT)mp_whiledo,pos,arg1,p2 - p1,code._width - p2,arg2).move_to(code,p1); 16876 CImg<uptrT>::vector((uptrT)mp_whiledo,pos,arg1,p2 - p1,code._width - p2,arg2).move_to(code,p1);
16453 _cimg_mp_return(pos); 16877 _cimg_mp_return(pos);
@@ -16457,15 +16881,31 @@ namespace cimg_library_suffixed { @@ -16457,15 +16881,31 @@ namespace cimg_library_suffixed {
16457 16881
16458 if (!std::strncmp(ss,"min(",4) || !std::strncmp(ss,"max(",4) || 16882 if (!std::strncmp(ss,"min(",4) || !std::strncmp(ss,"max(",4) ||
16459 !std::strncmp(ss,"med(",4) || !std::strncmp(ss,"kth(",4) || 16883 !std::strncmp(ss,"med(",4) || !std::strncmp(ss,"kth(",4) ||
16460 - !std::strncmp(ss,"arg(",4) || 16884 + !std::strncmp(ss,"arg(",4) || !std::strncmp(ss,"sum(",4) ||
  16885 + !std::strncmp(ss,"std(",4) || !std::strncmp(ss,"var(",4) ||
  16886 + !std::strncmp(ss,"prod(",5) || !std::strncmp(ss,"mean(",5) ||
16461 !std::strncmp(ss,"argmin(",7) || !std::strncmp(ss,"argmax(",7)) { // Multi-argument functions 16887 !std::strncmp(ss,"argmin(",7) || !std::strncmp(ss,"argmax(",7)) { // Multi-argument functions
  16888 + _cimg_mp_op(*ss=='a'?(ss[3]=='('?"Function 'arg()'":ss[4]=='i'?"Function 'argmin()'":
  16889 + "Function 'argmax()'"):
  16890 + *ss=='s'?(ss[1]=='u'?"Function 'sum()'":"Function 'std()'"):
  16891 + *ss=='k'?"Function 'kth()'":
  16892 + *ss=='p'?"Function 'prod()'":
  16893 + *ss=='v'?"Function 'var()'":
  16894 + ss[1]=='i'?"Function 'min()'":
  16895 + ss[1]=='a'?"Function 'max()'":
  16896 + ss[2]=='a'?"Function 'mean()'":"Function 'med()'");
16462 pos = scalar(); 16897 pos = scalar();
16463 - is_sth = *ss=='a' && ss[3]!='(';  
16464 CImg<uptrT>::vector((uptrT)(*ss=='a'?(ss[3]=='('?mp_arg:ss[4]=='i'?mp_argmin:mp_argmax): 16898 CImg<uptrT>::vector((uptrT)(*ss=='a'?(ss[3]=='('?mp_arg:ss[4]=='i'?mp_argmin:mp_argmax):
16465 - *ss=='k'?mp_kth:ss[1]=='i'?mp_min:  
16466 - ss[1]=='a'?mp_max:mp_med),pos). 16899 + *ss=='s'?(ss[1]=='u'?mp_sum:mp_std):
  16900 + *ss=='k'?mp_kth:
  16901 + *ss=='p'?mp_prod:
  16902 + *ss=='v'?mp_var:
  16903 + ss[1]=='i'?mp_min:
  16904 + ss[1]=='a'?mp_max:
  16905 + ss[2]=='a'?mp_mean:
  16906 + mp_med),pos).
16467 move_to(_opcode); 16907 move_to(_opcode);
16468 - for (s = is_sth?ss7:ss4; s<se; ++s) { 16908 + for (s = std::strchr(ss,'(') + 1; s<se; ++s) {
16469 ns = s; while (ns<se && (*ns!=',' || level[ns - expr._data]!=clevel1) && 16909 ns = s; while (ns<se && (*ns!=',' || level[ns - expr._data]!=clevel1) &&
16470 (*ns!=')' || level[ns - expr._data]!=clevel)) ++ns; 16910 (*ns!=')' || level[ns - expr._data]!=clevel)) ++ns;
16471 arg2 = compile(s,ns,depth1,0); 16911 arg2 = compile(s,ns,depth1,0);
@@ -16480,7 +16920,7 @@ namespace cimg_library_suffixed { @@ -16480,7 +16920,7 @@ namespace cimg_library_suffixed {
16480 _cimg_mp_return(pos); 16920 _cimg_mp_return(pos);
16481 } 16921 }
16482 16922
16483 - // No corresponding built-in function -> Look for a user-defined function. 16923 + // No corresponding built-in function -> Look for a user-defined macro.
16484 s0 = strchr(ss,'('); 16924 s0 = strchr(ss,'(');
16485 if (s0) { 16925 if (s0) {
16486 variable_name.assign(ss,s0 - ss + 1).back() = 0; 16926 variable_name.assign(ss,s0 - ss + 1).back() = 0;
@@ -16512,7 +16952,7 @@ namespace cimg_library_suffixed { @@ -16512,7 +16952,7 @@ namespace cimg_library_suffixed {
16512 if (p1!=p2+1) { // Number of specified argument do not fit 16952 if (p1!=p2+1) { // Number of specified argument do not fit
16513 *se = saved_char; cimg::strellipsize(variable_name,64); cimg::strellipsize(expr,64); 16953 *se = saved_char; cimg::strellipsize(variable_name,64); cimg::strellipsize(expr,64);
16514 throw CImgArgumentException("[_cimg_math_parser] " 16954 throw CImgArgumentException("[_cimg_math_parser] "
16515 - "CImg<%s>::%s: function '%s()': Number of specified arguments does not " 16955 + "CImg<%s>::%s: Function '%s()': Number of specified arguments does not "
16516 "match function declaration (%u argument%s required), " 16956 "match function declaration (%u argument%s required), "
16517 "in expression '%s%s%s'.", 16957 "in expression '%s%s%s'.",
16518 pixel_type(),_cimg_mp_calling_function,variable_name._data, 16958 pixel_type(),_cimg_mp_calling_function,variable_name._data,
@@ -16550,6 +16990,7 @@ namespace cimg_library_suffixed { @@ -16550,6 +16990,7 @@ namespace cimg_library_suffixed {
16550 16990
16551 // Vector specification using initializer '[ ... ]'. 16991 // Vector specification using initializer '[ ... ]'.
16552 if (*ss=='[' && *se1==']') { 16992 if (*ss=='[' && *se1==']') {
  16993 + _cimg_mp_op("Operator '[]'");
16553 arg1 = 0; // Number of specified values. 16994 arg1 = 0; // Number of specified values.
16554 if (*ss1!=']') for (s = ss1; s<se; ++s) { 16995 if (*ss1!=']') for (s = ss1; s<se; ++s) {
16555 ns = s; while (ns<se && (*ns!=',' || level[ns - expr._data]!=clevel1) && 16996 ns = s; while (ns<se && (*ns!=',' || level[ns - expr._data]!=clevel1) &&
@@ -16562,7 +17003,7 @@ namespace cimg_library_suffixed { @@ -16562,7 +17003,7 @@ namespace cimg_library_suffixed {
16562 } else { CImg<uptrT>::vector(arg2).move_to(_opcode); ++arg1; } 17003 } else { CImg<uptrT>::vector(arg2).move_to(_opcode); ++arg1; }
16563 s = ns; 17004 s = ns;
16564 } 17005 }
16565 - _cimg_mp_check_vector0(arg1,"operator '[]'"); 17006 + _cimg_mp_check_vector0(arg1);
16566 pos = vector(arg1); 17007 pos = vector(arg1);
16567 _opcode.insert(CImg<uptrT>::vector((uptrT)mp_vector_init,pos,arg1),0); 17008 _opcode.insert(CImg<uptrT>::vector((uptrT)mp_vector_init,pos,arg1),0);
16568 (_opcode>'y').move_to(code); 17009 (_opcode>'y').move_to(code);
@@ -16702,7 +17143,7 @@ namespace cimg_library_suffixed { @@ -16702,7 +17143,7 @@ namespace cimg_library_suffixed {
16702 // Reached an unknown item -> error. 17143 // Reached an unknown item -> error.
16703 is_sth = true; // is_valid_variable_name 17144 is_sth = true; // is_valid_variable_name
16704 if (*variable_name>='0' && *variable_name<='9') is_sth = false; 17145 if (*variable_name>='0' && *variable_name<='9') is_sth = false;
16705 - else for (ns = variable_name._data + 1; *ns; ++ns) 17146 + else for (ns = variable_name._data; *ns; ++ns)
16706 if (!is_varchar(*ns)) { is_sth = false; break; } 17147 if (!is_varchar(*ns)) { is_sth = false; break; }
16707 17148
16708 *se = saved_char; cimg::strellipsize(variable_name,64); cimg::strellipsize(expr,64); 17149 *se = saved_char; cimg::strellipsize(variable_name,64); cimg::strellipsize(expr,64);
@@ -16883,7 +17324,7 @@ namespace cimg_library_suffixed { @@ -16883,7 +17324,7 @@ namespace cimg_library_suffixed {
16883 while (siz-->0) *(ptr++) = -1; 17324 while (siz-->0) *(ptr++) = -1;
16884 } 17325 }
16885 17326
16886 - unsigned int vector(const unsigned int siz) { // Insert new vector of specified size in memory. 17327 + unsigned int vector(const unsigned int siz) { // Insert new vector of specified size in memory
16887 if (mempos + siz>=mem._width) { 17328 if (mempos + siz>=mem._width) {
16888 mem.resize(2*mem._width + siz,1,1,1,0); 17329 mem.resize(2*mem._width + siz,1,1,1,0);
16889 memtype.resize(mem._width,1,1,1,0); 17330 memtype.resize(mem._width,1,1,1,0);
@@ -16895,7 +17336,14 @@ namespace cimg_library_suffixed { @@ -16895,7 +17336,14 @@ namespace cimg_library_suffixed {
16895 return pos; 17336 return pos;
16896 } 17337 }
16897 17338
16898 - unsigned int vector_copy(const unsigned int arg) { // Insert new copy of specified vector in memory. 17339 + unsigned int vector(const unsigned int siz, const double value) { // Insert new initialized vector
  17340 + const unsigned int pos = vector(siz);
  17341 + double *ptr = &mem[pos] + 1;
  17342 + for (unsigned int i = 0; i<siz; ++i) *(ptr++) = value;
  17343 + return pos;
  17344 + }
  17345 +
  17346 + unsigned int vector_copy(const unsigned int arg) { // Insert new copy of specified vector in memory
16899 const unsigned int 17347 const unsigned int
16900 siz = _cimg_mp_vector_size(arg), 17348 siz = _cimg_mp_vector_size(arg),
16901 pos = vector(siz); 17349 pos = vector(siz);
@@ -16903,11 +17351,36 @@ namespace cimg_library_suffixed { @@ -16903,11 +17351,36 @@ namespace cimg_library_suffixed {
16903 return pos; 17351 return pos;
16904 } 17352 }
16905 17353
  17354 + void self_vector_s(const unsigned int pos, const mp_func op, const unsigned int arg1) {
  17355 + const unsigned int siz = _cimg_mp_vector_size(pos);
  17356 + if (siz>24) CImg<uptrT>::vector((uptrT)mp_self_map_vector_s,pos,siz,(uptrT)op,arg1).move_to(code);
  17357 + else {
  17358 + code.insert(siz);
  17359 + for (unsigned int k = 1; k<=siz; ++k)
  17360 + CImg<uptrT>::vector((uptrT)op,pos + k,arg1).move_to(code[code._width - 1 - siz + k]);
  17361 + }
  17362 + }
  17363 +
  17364 + void self_vector_v(const unsigned int pos, const mp_func op, const unsigned int arg1) {
  17365 + const unsigned int siz = _cimg_mp_vector_size(pos);
  17366 + if (siz>24) CImg<uptrT>::vector((uptrT)mp_self_map_vector_v,pos,siz,(uptrT)op,arg1).move_to(code);
  17367 + else {
  17368 + code.insert(siz);
  17369 + for (unsigned int k = 1; k<=siz; ++k)
  17370 + CImg<uptrT>::vector((uptrT)op,pos + k,arg1 + k).move_to(code[code._width - 1 - siz + k]);
  17371 + }
  17372 + }
  17373 +
16906 unsigned int vector1_v(const mp_func op, const unsigned int arg1) { 17374 unsigned int vector1_v(const mp_func op, const unsigned int arg1) {
16907 const unsigned int 17375 const unsigned int
16908 siz = _cimg_mp_vector_size(arg1), 17376 siz = _cimg_mp_vector_size(arg1),
16909 pos = is_tmp_vector(arg1)?arg1:vector(siz); 17377 pos = is_tmp_vector(arg1)?arg1:vector(siz);
16910 - CImg<uptrT>::vector((uptrT)mp_vector_map_v,pos,siz,(uptrT)op,arg1).move_to(code); 17378 + if (siz>24) CImg<uptrT>::vector((uptrT)mp_vector_map_v,pos,siz,(uptrT)op,arg1).move_to(code);
  17379 + else {
  17380 + code.insert(siz);
  17381 + for (unsigned int k = 1; k<=siz; ++k)
  17382 + CImg<uptrT>::vector((uptrT)op,pos + k,arg1 + k).move_to(code[code._width - 1 - siz + k]);
  17383 + }
16911 return pos; 17384 return pos;
16912 } 17385 }
16913 17386
@@ -16915,7 +17388,12 @@ namespace cimg_library_suffixed { @@ -16915,7 +17388,12 @@ namespace cimg_library_suffixed {
16915 const unsigned int 17388 const unsigned int
16916 siz = _cimg_mp_vector_size(arg1), 17389 siz = _cimg_mp_vector_size(arg1),
16917 pos = is_tmp_vector(arg1)?arg1:is_tmp_vector(arg2)?arg2:vector(siz); 17390 pos = is_tmp_vector(arg1)?arg1:is_tmp_vector(arg2)?arg2:vector(siz);
16918 - CImg<uptrT>::vector((uptrT)mp_vector_map_vv,pos,siz,(uptrT)op,arg1,arg2).move_to(code); 17391 + if (siz>24) CImg<uptrT>::vector((uptrT)mp_vector_map_vv,pos,siz,(uptrT)op,arg1,arg2).move_to(code);
  17392 + else {
  17393 + code.insert(siz);
  17394 + for (unsigned int k = 1; k<=siz; ++k)
  17395 + CImg<uptrT>::vector((uptrT)op,pos + k,arg1 + k,arg2 + k).move_to(code[code._width - 1 - siz + k]);
  17396 + }
16919 return pos; 17397 return pos;
16920 } 17398 }
16921 17399
@@ -16923,7 +17401,12 @@ namespace cimg_library_suffixed { @@ -16923,7 +17401,12 @@ namespace cimg_library_suffixed {
16923 const unsigned int 17401 const unsigned int
16924 siz = _cimg_mp_vector_size(arg1), 17402 siz = _cimg_mp_vector_size(arg1),
16925 pos = is_tmp_vector(arg1)?arg1:vector(siz); 17403 pos = is_tmp_vector(arg1)?arg1:vector(siz);
16926 - CImg<uptrT>::vector((uptrT)mp_vector_map_vs,pos,siz,(uptrT)op,arg1,arg2).move_to(code); 17404 + if (siz>24) CImg<uptrT>::vector((uptrT)mp_vector_map_vs,pos,siz,(uptrT)op,arg1,arg2).move_to(code);
  17405 + else {
  17406 + code.insert(siz);
  17407 + for (unsigned int k = 1; k<=siz; ++k)
  17408 + CImg<uptrT>::vector((uptrT)op,pos + k,arg1 + k,arg2).move_to(code[code._width - 1 - siz + k]);
  17409 + }
16927 return pos; 17410 return pos;
16928 } 17411 }
16929 17412
@@ -16931,7 +17414,12 @@ namespace cimg_library_suffixed { @@ -16931,7 +17414,12 @@ namespace cimg_library_suffixed {
16931 const unsigned int 17414 const unsigned int
16932 siz = _cimg_mp_vector_size(arg2), 17415 siz = _cimg_mp_vector_size(arg2),
16933 pos = is_tmp_vector(arg2)?arg2:vector(siz); 17416 pos = is_tmp_vector(arg2)?arg2:vector(siz);
16934 - CImg<uptrT>::vector((uptrT)mp_vector_map_sv,pos,siz,(uptrT)op,arg1,arg2).move_to(code); 17417 + if (siz>24) CImg<uptrT>::vector((uptrT)mp_vector_map_sv,pos,siz,(uptrT)op,arg1,arg2).move_to(code);
  17418 + else {
  17419 + code.insert(siz);
  17420 + for (unsigned int k = 1; k<=siz; ++k)
  17421 + CImg<uptrT>::vector((uptrT)op,pos + k,arg1,arg2 + k).move_to(code[code._width - 1 - siz + k]);
  17422 + }
16935 return pos; 17423 return pos;
16936 } 17424 }
16937 17425
@@ -16940,22 +17428,29 @@ namespace cimg_library_suffixed { @@ -16940,22 +17428,29 @@ namespace cimg_library_suffixed {
16940 const unsigned int 17428 const unsigned int
16941 siz = _cimg_mp_vector_size(arg1), 17429 siz = _cimg_mp_vector_size(arg1),
16942 pos = is_tmp_vector(arg1)?arg1:vector(siz); 17430 pos = is_tmp_vector(arg1)?arg1:vector(siz);
16943 - CImg<uptrT>::vector((uptrT)mp_vector_map_vss,pos,siz,(uptrT)op,arg1,arg2,arg3).move_to(code); 17431 + if (siz>24) CImg<uptrT>::vector((uptrT)mp_vector_map_vss,pos,siz,(uptrT)op,arg1,arg2,arg3).move_to(code);
  17432 + else {
  17433 + code.insert(siz);
  17434 + for (unsigned int k = 1; k<=siz; ++k)
  17435 + CImg<uptrT>::vector((uptrT)op,pos + k,arg1 + k,arg2,arg3).move_to(code[code._width - 1 - siz + k]);
  17436 + }
16944 return pos; 17437 return pos;
16945 } 17438 }
16946 17439
16947 // Check if a memory slot is a positive integer constant scalar value. 17440 // Check if a memory slot is a positive integer constant scalar value.
16948 - void check_constant(const unsigned int arg, const unsigned int n_arg, const char *const s_op, 17441 + void check_constant(const unsigned int arg, const unsigned int n_arg,
16949 const bool is_strictly_positive, 17442 const bool is_strictly_positive,
16950 const char *const ss, char *const se, const char saved_char) { 17443 const char *const ss, char *const se, const char saved_char) {
16951 - _cimg_mp_check_type(arg,n_arg,s_op,1,0); 17444 + _cimg_mp_check_type(arg,n_arg,1,0);
16952 if (!_cimg_mp_is_constant(arg) || mem[arg]<(is_strictly_positive?1:0) || (double)(int)mem[arg]!=mem[arg]) { 17445 if (!_cimg_mp_is_constant(arg) || mem[arg]<(is_strictly_positive?1:0) || (double)(int)mem[arg]!=mem[arg]) {
16953 - const char *s_arg = !n_arg?"":n_arg==1?"First ":n_arg==2?"Second ":n_arg==3?"Third ":"One "; 17446 + const char *s_arg = !n_arg?"":n_arg==1?"First ":n_arg==2?"Second ":n_arg==3?"Third ":
  17447 + n_arg==4?"Fourth ":n_arg==5?"Fifth ":n_arg==6?"Sixth ":n_arg==7?"Seventh ":n_arg==8?"Eighth ":
  17448 + n_arg==9?"Ninth ":"One of the ";
16954 *se = saved_char; cimg::strellipsize(expr,64); 17449 *se = saved_char; cimg::strellipsize(expr,64);
16955 throw CImgArgumentException("[_cimg_math_parser] " 17450 throw CImgArgumentException("[_cimg_math_parser] "
16956 - "CImg<%s>::%s(): %s: %s%s (of type '%s') is not a %spositive integer constant, " 17451 + "CImg<%s>::%s(): %s%s %s%s (of type '%s') is not a %spositive integer constant, "
16957 "in expression '%s%s%s'.", 17452 "in expression '%s%s%s'.",
16958 - pixel_type(),_cimg_mp_calling_function,s_op, 17453 + pixel_type(),_cimg_mp_calling_function,s_op,*s_op?":":"",
16959 s_arg,*s_arg?"argument":"Argument",s_type(arg)._data, 17454 s_arg,*s_arg?"argument":"Argument",s_type(arg)._data,
16960 is_strictly_positive?"strictly ":"", 17455 is_strictly_positive?"strictly ":"",
16961 (ss - 4)>expr._data?"...":"", 17456 (ss - 4)>expr._data?"...":"",
@@ -16965,9 +17460,9 @@ namespace cimg_library_suffixed { @@ -16965,9 +17460,9 @@ namespace cimg_library_suffixed {
16965 } 17460 }
16966 17461
16967 // Check a matrix is square. 17462 // Check a matrix is square.
16968 - void check_matrix_square(const unsigned int arg, const unsigned int n_arg, const char *const s_op, 17463 + void check_matrix_square(const unsigned int arg, const unsigned int n_arg,
16969 const char *const ss, char *const se, const char saved_char) { 17464 const char *const ss, char *const se, const char saved_char) {
16970 - _cimg_mp_check_type(arg,n_arg,s_op,2,0); 17465 + _cimg_mp_check_type(arg,n_arg,2,0);
16971 const unsigned int 17466 const unsigned int
16972 siz = _cimg_mp_vector_size(arg), 17467 siz = _cimg_mp_vector_size(arg),
16973 n = (unsigned int)std::sqrt((float)siz); 17468 n = (unsigned int)std::sqrt((float)siz);
@@ -16977,9 +17472,9 @@ namespace cimg_library_suffixed { @@ -16977,9 +17472,9 @@ namespace cimg_library_suffixed {
16977 else s_arg = !n_arg?"":n_arg==1?"First ":n_arg==2?"Second ":n_arg==3?"Third ":"One "; 17472 else s_arg = !n_arg?"":n_arg==1?"First ":n_arg==2?"Second ":n_arg==3?"Third ":"One ";
16978 *se = saved_char; cimg::strellipsize(expr,64); 17473 *se = saved_char; cimg::strellipsize(expr,64);
16979 throw CImgArgumentException("[_cimg_math_parser] " 17474 throw CImgArgumentException("[_cimg_math_parser] "
16980 - "CImg<%s>::%s(): %s: %s%s (of type '%s') " 17475 + "CImg<%s>::%s(): %s%s %s%s (of type '%s') "
16981 "cannot be considered as a square matrix, in expression '%s%s%s'.", 17476 "cannot be considered as a square matrix, in expression '%s%s%s'.",
16982 - pixel_type(),_cimg_mp_calling_function,s_op, 17477 + pixel_type(),_cimg_mp_calling_function,s_op,*s_op?":":"",
16983 s_arg,*s_op=='F'?(*s_arg?"argument":"Argument"):(*s_arg?"operand":"Operand"), 17478 s_arg,*s_op=='F'?(*s_arg?"argument":"Argument"):(*s_arg?"operand":"Operand"),
16984 s_type(arg)._data, 17479 s_type(arg)._data,
16985 (ss - 4)>expr._data?"...":"", 17480 (ss - 4)>expr._data?"...":"",
@@ -16992,7 +17487,7 @@ namespace cimg_library_suffixed { @@ -16992,7 +17487,7 @@ namespace cimg_library_suffixed {
16992 // Bits of 'mode' tells what types are allowed: 17487 // Bits of 'mode' tells what types are allowed:
16993 // { 1 = scalar | 2 = vectorN }. 17488 // { 1 = scalar | 2 = vectorN }.
16994 // If 'N' is not zero, it also restricts the vectors to be of size N only. 17489 // If 'N' is not zero, it also restricts the vectors to be of size N only.
16995 - void check_type(const unsigned int arg, const unsigned int n_arg, const char *const s_op, 17490 + void check_type(const unsigned int arg, const unsigned int n_arg,
16996 const unsigned int mode, const unsigned int N, 17491 const unsigned int mode, const unsigned int N,
16997 const char *const ss, char *const se, const char saved_char) { 17492 const char *const ss, char *const se, const char saved_char) {
16998 const bool 17493 const bool
@@ -17004,7 +17499,9 @@ namespace cimg_library_suffixed { @@ -17004,7 +17499,9 @@ namespace cimg_library_suffixed {
17004 if (!cond) { 17499 if (!cond) {
17005 const char *s_arg; 17500 const char *s_arg;
17006 if (*s_op!='F') s_arg = !n_arg?"":n_arg==1?"Left-hand ":"Right-hand "; 17501 if (*s_op!='F') s_arg = !n_arg?"":n_arg==1?"Left-hand ":"Right-hand ";
17007 - else s_arg = !n_arg?"":n_arg==1?"First ":n_arg==2?"Second ":n_arg==3?"Third ":"One "; 17502 + else s_arg = !n_arg?"":n_arg==1?"First ":n_arg==2?"Second ":n_arg==3?"Third ":
  17503 + n_arg==4?"Fourth ":n_arg==5?"Fifth ":n_arg==6?"Sixth ":n_arg==7?"Seventh ":n_arg==8?"Eighth":
  17504 + n_arg==9?"Ninth":"One of the ";
17008 CImg<charT> sb_type(32); 17505 CImg<charT> sb_type(32);
17009 if (mode==1) cimg_snprintf(sb_type,sb_type._width,"'scalar'"); 17506 if (mode==1) cimg_snprintf(sb_type,sb_type._width,"'scalar'");
17010 else if (mode==2) { 17507 else if (mode==2) {
@@ -17016,9 +17513,9 @@ namespace cimg_library_suffixed { @@ -17016,9 +17513,9 @@ namespace cimg_library_suffixed {
17016 } 17513 }
17017 *se = saved_char; cimg::strellipsize(expr,64); 17514 *se = saved_char; cimg::strellipsize(expr,64);
17018 throw CImgArgumentException("[_cimg_math_parser] " 17515 throw CImgArgumentException("[_cimg_math_parser] "
17019 - "CImg<%s>::%s(): %s: %s%s has invalid type '%s' (should be %s), " 17516 + "CImg<%s>::%s(): %s%s %s%s has invalid type '%s' (should be %s), "
17020 "in expression '%s%s%s'.", 17517 "in expression '%s%s%s'.",
17021 - pixel_type(),_cimg_mp_calling_function,s_op, 17518 + pixel_type(),_cimg_mp_calling_function,s_op,*s_op?":":"",
17022 s_arg,*s_op=='F'?(*s_arg?"argument":"Argument"):(*s_arg?"operand":"Operand"), 17519 s_arg,*s_op=='F'?(*s_arg?"argument":"Argument"):(*s_arg?"operand":"Operand"),
17023 s_type(arg)._data,sb_type._data, 17520 s_type(arg)._data,sb_type._data,
17024 (ss - 4)>expr._data?"...":"", 17521 (ss - 4)>expr._data?"...":"",
@@ -17027,24 +17524,39 @@ namespace cimg_library_suffixed { @@ -17027,24 +17524,39 @@ namespace cimg_library_suffixed {
17027 } 17524 }
17028 } 17525 }
17029 17526
  17527 + // Check is listin is not empty.
  17528 + void check_list(const bool is_out,
  17529 + const char *const ss, char *const se, const char saved_char) {
  17530 + if ((!is_out && !listin) || (is_out && !listout)) {
  17531 + *se = saved_char; cimg::strellipsize(expr,64);
  17532 + throw CImgArgumentException("[_cimg_math_parser] "
  17533 + "CImg<%s>::%s(): %s%s Invalid call with an empty image list, "
  17534 + "in expression '%s%s%s'.",
  17535 + pixel_type(),_cimg_mp_calling_function,s_op,*s_op?":":"",
  17536 + (ss - 4)>expr._data?"...":"",
  17537 + (ss - 4)>expr._data?ss - 4:expr._data,
  17538 + se<&expr.back()?"...":"");
  17539 + }
  17540 + }
  17541 +
17030 // Check a vector is not 0-dimensional, or with unknown dimension at compile time. 17542 // Check a vector is not 0-dimensional, or with unknown dimension at compile time.
17031 - void check_vector0(const unsigned int dim, const char *const s_op, 17543 + void check_vector0(const unsigned int dim,
17032 const char *const ss, char *const se, const char saved_char) { 17544 const char *const ss, char *const se, const char saved_char) {
17033 if (!dim) { 17545 if (!dim) {
17034 *se = saved_char; cimg::strellipsize(expr,64); 17546 *se = saved_char; cimg::strellipsize(expr,64);
17035 throw CImgArgumentException("[_cimg_math_parser] " 17547 throw CImgArgumentException("[_cimg_math_parser] "
17036 - "CImg<%s>::%s(): %s: Invalid construction of a 0-dimensional vector, " 17548 + "CImg<%s>::%s(): %s%s Invalid construction of a 0-dimensional vector, "
17037 "in expression '%s%s%s'.", 17549 "in expression '%s%s%s'.",
17038 - pixel_type(),_cimg_mp_calling_function,s_op, 17550 + pixel_type(),_cimg_mp_calling_function,s_op,*s_op?":":"",
17039 (ss - 4)>expr._data?"...":"", 17551 (ss - 4)>expr._data?"...":"",
17040 (ss - 4)>expr._data?ss - 4:expr._data, 17552 (ss - 4)>expr._data?ss - 4:expr._data,
17041 se<&expr.back()?"...":""); 17553 se<&expr.back()?"...":"");
17042 } else if (dim==~0U) { 17554 } else if (dim==~0U) {
17043 *se = saved_char; cimg::strellipsize(expr,64); 17555 *se = saved_char; cimg::strellipsize(expr,64);
17044 throw CImgArgumentException("[_cimg_math_parser] " 17556 throw CImgArgumentException("[_cimg_math_parser] "
17045 - "CImg<%s>::%s(): %s: Invalid construction of a vector with dynamic size, " 17557 + "CImg<%s>::%s(): %s%s Invalid construction of a vector with dynamic size, "
17046 "in expression '%s%s%s'.", 17558 "in expression '%s%s%s'.",
17047 - pixel_type(),_cimg_mp_calling_function,s_op, 17559 + pixel_type(),_cimg_mp_calling_function,s_op,*s_op?":":"",
17048 (ss - 4)>expr._data?"...":"", 17560 (ss - 4)>expr._data?"...":"",
17049 (ss - 4)>expr._data?ss - 4:expr._data, 17561 (ss - 4)>expr._data?ss - 4:expr._data,
17050 se<&expr.back()?"...":""); 17562 se<&expr.back()?"...":"");
@@ -17253,6 +17765,26 @@ namespace cimg_library_suffixed { @@ -17253,6 +17765,26 @@ namespace cimg_library_suffixed {
17253 return std::cosh(_mp_arg(2)); 17765 return std::cosh(_mp_arg(2));
17254 } 17766 }
17255 17767
  17768 + static double mp_crop(_cimg_math_parser& mp) {
  17769 + double *ptrd = &_mp_arg(1) + 1;
  17770 + const int x = (int)_mp_arg(3), y = (int)_mp_arg(4), z = (int)_mp_arg(5), c = (int)_mp_arg(6);
  17771 + const unsigned int
  17772 + dx = (unsigned int)mp.opcode[7],
  17773 + dy = (unsigned int)mp.opcode[8],
  17774 + dz = (unsigned int)mp.opcode[9],
  17775 + dc = (unsigned int)mp.opcode[10];
  17776 + const bool boundary_conditions = (bool)_mp_arg(11);
  17777 + unsigned int ind = (unsigned int)mp.opcode[2];
  17778 + if (ind!=~0U) ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width());
  17779 + const CImg<T> &img = ind==~0U?mp.imgin:mp.listin[ind];
  17780 + if (!img) std::memset(ptrd,0,dx*dy*dz*dc*sizeof(double));
  17781 + else CImg<double>(ptrd,dx,dy,dz,dc,true) = img.get_crop(x,y,z,c,
  17782 + x + dx - 1,y + dy - 1,
  17783 + z + dz - 1,c + dc - 1,
  17784 + boundary_conditions);
  17785 + return cimg::type<double>::nan();
  17786 + }
  17787 +
17256 static double mp_cross(_cimg_math_parser& mp) { 17788 static double mp_cross(_cimg_math_parser& mp) {
17257 CImg<doubleT> 17789 CImg<doubleT>
17258 vout(&_mp_arg(1) + 1,1,3,1,1,true), 17790 vout(&_mp_arg(1) + 1,1,3,1,1,true),
@@ -17268,52 +17800,56 @@ namespace cimg_library_suffixed { @@ -17268,52 +17800,56 @@ namespace cimg_library_suffixed {
17268 } 17800 }
17269 17801
17270 static double mp_debug(_cimg_math_parser& mp) { 17802 static double mp_debug(_cimg_math_parser& mp) {
17271 -#ifdef cimg_use_openmp  
17272 - const unsigned int n_thread = omp_get_thread_num();  
17273 -#else  
17274 - const unsigned int n_thread = 0;  
17275 -#endif  
17276 CImg<charT> expr(mp.opcode._height - 3); 17803 CImg<charT> expr(mp.opcode._height - 3);
17277 const uptrT *ptrs = mp.opcode._data + 3; 17804 const uptrT *ptrs = mp.opcode._data + 3;
17278 cimg_for(expr,ptrd,char) *ptrd = (char)*(ptrs++); 17805 cimg_for(expr,ptrd,char) *ptrd = (char)*(ptrs++);
17279 cimg::strellipsize(expr); 17806 cimg::strellipsize(expr);
17280 const uptrT g_target = mp.opcode[1]; 17807 const uptrT g_target = mp.opcode[1];
17281 - std::fprintf(cimg::output(),  
17282 - "\n[_cimg_math_parser] %p[thread #%u]:%*c"  
17283 - "Start debugging expression '%s', code length %u -> mem[%u] (memsize: %u)",  
17284 - (void*)&mp,n_thread,mp.debug_indent,' ',  
17285 - expr._data,(unsigned int)mp.opcode[2],(unsigned int)g_target,mp.mem._width);  
17286 - std::fflush(cimg::output());  
17287 - const CImg<uptrT> *const p_end = (++mp.p_code) + mp.opcode[2];  
17288 - CImg<uptrT> _op;  
17289 - mp.debug_indent+=3;  
17290 - for ( ; mp.p_code<p_end; ++mp.p_code) {  
17291 - const CImg<uptrT> &op = *mp.p_code;  
17292 - mp.opcode._data = op._data; mp.opcode._height = op._height;  
17293 17808
17294 - _op.assign(1,op._height - 1);  
17295 - const uptrT *ptrs = op._data + 1;  
17296 - for (uptrT *ptrd = _op._data, *const ptrde = _op._data + _op._height; ptrd<ptrde; ++ptrd)  
17297 - *ptrd = *(ptrs++); 17809 +#ifndef cimg_use_openmp
  17810 + const unsigned int n_thread = 0;
  17811 +#else
  17812 + const unsigned int n_thread = omp_get_thread_num();
  17813 +#pragma omp critical
  17814 +#endif
  17815 + {
  17816 + std::fprintf(cimg::output(),
  17817 + "\n[_cimg_math_parser] %p[thread #%u]:%*c"
  17818 + "Start debugging expression '%s', code length %u -> mem[%u] (memsize: %u)",
  17819 + (void*)&mp,n_thread,mp.debug_indent,' ',
  17820 + expr._data,(unsigned int)mp.opcode[2],(unsigned int)g_target,mp.mem._width);
  17821 + std::fflush(cimg::output());
  17822 + const CImg<uptrT> *const p_end = (++mp.p_code) + mp.opcode[2];
  17823 + CImg<uptrT> _op;
  17824 + mp.debug_indent+=3;
  17825 + for ( ; mp.p_code<p_end; ++mp.p_code) {
  17826 + const CImg<uptrT> &op = *mp.p_code;
  17827 + mp.opcode._data = op._data; mp.opcode._height = op._height;
  17828 +
  17829 + _op.assign(1,op._height - 1);
  17830 + const uptrT *ptrs = op._data + 1;
  17831 + for (uptrT *ptrd = _op._data, *const ptrde = _op._data + _op._height; ptrd<ptrde; ++ptrd)
  17832 + *ptrd = *(ptrs++);
17298 17833
17299 - const uptrT target = mp.opcode[1];  
17300 - mp.mem[target] = _cimg_mp_defunc(mp); 17834 + const uptrT target = mp.opcode[1];
  17835 + mp.mem[target] = _cimg_mp_defunc(mp);
  17836 + std::fprintf(cimg::output(),
  17837 + "\n[_cimg_math_parser] %p[thread #%u]:%*c"
  17838 + "Opcode %p = [ %p,%s ] -> mem[%u] = %g",
  17839 + (void*)&mp,n_thread,mp.debug_indent,' ',
  17840 + (void*)mp.opcode._data,(void*)*mp.opcode,_op.value_string().data(),
  17841 + (unsigned int)target,mp.mem[target]);
  17842 + std::fflush(cimg::output());
  17843 + }
  17844 + mp.debug_indent-=3;
17301 std::fprintf(cimg::output(), 17845 std::fprintf(cimg::output(),
17302 "\n[_cimg_math_parser] %p[thread #%u]:%*c" 17846 "\n[_cimg_math_parser] %p[thread #%u]:%*c"
17303 - "Opcode %p = [ %p,%s ] -> mem[%u] = %g", 17847 + "End debugging expression '%s' -> mem[%u] = %g (memsize: %u)",
17304 (void*)&mp,n_thread,mp.debug_indent,' ', 17848 (void*)&mp,n_thread,mp.debug_indent,' ',
17305 - (void*)mp.opcode._data,(void*)*mp.opcode,_op.value_string().data(),  
17306 - (unsigned int)target,mp.mem[target]); 17849 + expr._data,(unsigned int)g_target,mp.mem[g_target],mp.mem._width);
17307 std::fflush(cimg::output()); 17850 std::fflush(cimg::output());
  17851 + --mp.p_code;
17308 } 17852 }
17309 - mp.debug_indent-=3;  
17310 - std::fprintf(cimg::output(),  
17311 - "\n[_cimg_math_parser] %p[thread #%u]:%*c"  
17312 - "End debugging expression '%s' -> mem[%u] = %g (memsize: %u)",  
17313 - (void*)&mp,n_thread,mp.debug_indent,' ',  
17314 - expr._data,(unsigned int)g_target,mp.mem[g_target],mp.mem._width);  
17315 - std::fflush(cimg::output());  
17316 - --mp.p_code;  
17317 return mp.mem[g_target]; 17853 return mp.mem[g_target];
17318 } 17854 }
17319 17855
@@ -17321,6 +17857,24 @@ namespace cimg_library_suffixed { @@ -17321,6 +17857,24 @@ namespace cimg_library_suffixed {
17321 return _mp_arg(2) - 1; 17857 return _mp_arg(2) - 1;
17322 } 17858 }
17323 17859
  17860 + static double mp_det(_cimg_math_parser& mp) {
  17861 + const double *ptrs = &_mp_arg(2) + 1;
  17862 + const unsigned int k = (unsigned int)mp.opcode(3);
  17863 + return CImg<double>(ptrs,k,k,1,1,true).det();
  17864 + }
  17865 +
  17866 + static double mp_diag(_cimg_math_parser& mp) {
  17867 + double *ptrd = &_mp_arg(1) + 1;
  17868 + const double *ptrs = &_mp_arg(2) + 1;
  17869 + const unsigned int k = (unsigned int)mp.opcode(3);
  17870 + CImg<double>(ptrd,k,k,1,1,true) = CImg<double>(ptrs,1,k,1,1,true).get_diagonal();
  17871 + return cimg::type<double>::nan();
  17872 + }
  17873 +
  17874 + static double mp_div(_cimg_math_parser& mp) {
  17875 + return _mp_arg(2)/_mp_arg(3);
  17876 + }
  17877 +
17324 static double mp_dot(_cimg_math_parser& mp) { 17878 static double mp_dot(_cimg_math_parser& mp) {
17325 const unsigned int siz = (unsigned int)mp.opcode[4]; 17879 const unsigned int siz = (unsigned int)mp.opcode[4];
17326 return CImg<doubleT>(&_mp_arg(2) + 1,1,siz,1,1,true). 17880 return CImg<doubleT>(&_mp_arg(2) + 1,1,siz,1,1,true).
@@ -17346,8 +17900,36 @@ namespace cimg_library_suffixed { @@ -17346,8 +17900,36 @@ namespace cimg_library_suffixed {
17346 return mp.mem[mem_proc]; 17900 return mp.mem[mem_proc];
17347 } 17901 }
17348 17902
17349 - static double mp_div(_cimg_math_parser& mp) {  
17350 - return _mp_arg(2)/_mp_arg(3); 17903 + static double mp_draw(_cimg_math_parser& mp) {
  17904 + const int x = (int)_mp_arg(3), y = (int)_mp_arg(4), z = (int)_mp_arg(5), c = (int)_mp_arg(6);
  17905 + const unsigned int
  17906 + dx = (unsigned int)mp.opcode[7],
  17907 + dy = (unsigned int)mp.opcode[8],
  17908 + dz = (unsigned int)mp.opcode[9],
  17909 + dc = (unsigned int)mp.opcode[10];
  17910 + const CImg<double> S(&_mp_arg(1) + 1,dx,dy,dz,dc,true);
  17911 + const float opacity = (float)_mp_arg(11);
  17912 + unsigned int ind = (unsigned int)mp.opcode[2];
  17913 + if (ind!=~0U) ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width());
  17914 + CImg<T> &img = ind==~0U?mp.imgout:mp.listout[ind];
  17915 + if (img) {
  17916 + if (mp.opcode[12]!=(uptrT)-1) {
  17917 + const CImg<double> M(&_mp_arg(12) + 1,dx,dy,dz,(unsigned int)mp.opcode[13],true);
  17918 + img.draw_image(x,y,z,c,S,M,opacity,(float)_mp_arg(14));
  17919 + } else img.draw_image(x,y,z,c,S,opacity);
  17920 + }
  17921 + return cimg::type<double>::nan();
  17922 + }
  17923 +
  17924 + static double mp_eig(_cimg_math_parser& mp) {
  17925 + double *ptrd = &_mp_arg(1) + 1;
  17926 + const double *ptr1 = &_mp_arg(2) + 1;
  17927 + const unsigned int k = (unsigned int)mp.opcode(3);
  17928 + CImg<double> val, vec;
  17929 + CImg<double>(ptr1,k,k,1,1,true).symmetric_eigen(val,vec);
  17930 + CImg<double>(ptrd,k,1,1,1,true) = val.unroll('x');
  17931 + CImg<double>(ptrd + k,k,k,1,1,true) = vec.get_transpose();
  17932 + return cimg::type<double>::nan();
17351 } 17933 }
17352 17934
17353 static double mp_eq(_cimg_math_parser& mp) { 17935 static double mp_eq(_cimg_math_parser& mp) {
@@ -17358,6 +17940,13 @@ namespace cimg_library_suffixed { @@ -17358,6 +17940,13 @@ namespace cimg_library_suffixed {
17358 return std::exp(_mp_arg(2)); 17940 return std::exp(_mp_arg(2));
17359 } 17941 }
17360 17942
  17943 + static double mp_eye(_cimg_math_parser& mp) {
  17944 + double *ptrd = &_mp_arg(1) + 1;
  17945 + const unsigned int k = (unsigned int)mp.opcode(2);
  17946 + CImg<double>(ptrd,k,k,1,1,true).identity_matrix();
  17947 + return cimg::type<double>::nan();
  17948 + }
  17949 +
17361 static double mp_g(_cimg_math_parser& mp) { 17950 static double mp_g(_cimg_math_parser& mp) {
17362 cimg::unused(mp); 17951 cimg::unused(mp);
17363 return cimg::grand(); 17952 return cimg::grand();
@@ -17424,6 +18013,14 @@ namespace cimg_library_suffixed { @@ -17424,6 +18013,14 @@ namespace cimg_library_suffixed {
17424 return (double)(long)_mp_arg(2); 18013 return (double)(long)_mp_arg(2);
17425 } 18014 }
17426 18015
  18016 + static double mp_inv(_cimg_math_parser& mp) {
  18017 + double *ptrd = &_mp_arg(1) + 1;
  18018 + const double *ptr1 = &_mp_arg(2) + 1;
  18019 + const unsigned int k = (unsigned int)mp.opcode(3);
  18020 + CImg<double>(ptrd,k,k,1,1,true) = CImg<double>(ptr1,k,k,1,1,true).get_invert();
  18021 + return cimg::type<double>::nan();
  18022 + }
  18023 +
17427 static double mp_ioff(_cimg_math_parser& mp) { 18024 static double mp_ioff(_cimg_math_parser& mp) {
17428 const unsigned int 18025 const unsigned int
17429 boundary_conditions = (unsigned int)_mp_arg(3); 18026 boundary_conditions = (unsigned int)_mp_arg(3);
@@ -17713,9 +18310,8 @@ namespace cimg_library_suffixed { @@ -17713,9 +18310,8 @@ namespace cimg_library_suffixed {
17713 z = (int)_mp_arg(5), c = (int)_mp_arg(6); 18310 z = (int)_mp_arg(5), c = (int)_mp_arg(6);
17714 const double val = _mp_arg(1); 18311 const double val = _mp_arg(1);
17715 if (x>=0 && x<img.width() && y>=0 && y<img.height() && 18312 if (x>=0 && x<img.width() && y>=0 && y<img.height() &&
17716 - z>=0 && z<img.depth() && c>=0 && c<img.spectrum()) { 18313 + z>=0 && z<img.depth() && c>=0 && c<img.spectrum())
17717 img(x,y,z,c) = (T)val; 18314 img(x,y,z,c) = (T)val;
17718 - }  
17719 return val; 18315 return val;
17720 } 18316 }
17721 18317
@@ -17744,9 +18340,8 @@ namespace cimg_library_suffixed { @@ -17744,9 +18340,8 @@ namespace cimg_library_suffixed {
17744 z = (int)(oz + _mp_arg(5)), c = (int)(oc + _mp_arg(6)); 18340 z = (int)(oz + _mp_arg(5)), c = (int)(oc + _mp_arg(6));
17745 const double val = _mp_arg(1); 18341 const double val = _mp_arg(1);
17746 if (x>=0 && x<img.width() && y>=0 && y<img.height() && 18342 if (x>=0 && x<img.width() && y>=0 && y<img.height() &&
17747 - z>=0 && z<img.depth() && c>=0 && c<img.spectrum()) { 18343 + z>=0 && z<img.depth() && c>=0 && c<img.spectrum())
17748 img(x,y,z,c) = (T)val; 18344 img(x,y,z,c) = (T)val;
17749 - }  
17750 return val; 18345 return val;
17751 } 18346 }
17752 18347
@@ -18099,46 +18694,6 @@ namespace cimg_library_suffixed { @@ -18099,46 +18694,6 @@ namespace cimg_library_suffixed {
18099 return (double)(_mp_arg(2)<=_mp_arg(3)); 18694 return (double)(_mp_arg(2)<=_mp_arg(3));
18100 } 18695 }
18101 18696
18102 - static double mp_matrix_det(_cimg_math_parser& mp) {  
18103 - const double *ptrs = &_mp_arg(2) + 1;  
18104 - const unsigned int k = (unsigned int)mp.opcode(3);  
18105 - return CImg<double>(ptrs,k,k,1,1,true).det();  
18106 - }  
18107 -  
18108 - static double mp_matrix_diag(_cimg_math_parser& mp) {  
18109 - double *ptrd = &_mp_arg(1) + 1;  
18110 - const double *ptrs = &_mp_arg(2) + 1;  
18111 - const unsigned int k = (unsigned int)mp.opcode(3);  
18112 - CImg<double>(ptrd,k,k,1,1,true) = CImg<double>(ptrs,1,k,1,1,true).get_diagonal();  
18113 - return cimg::type<double>::nan();  
18114 - }  
18115 -  
18116 - static double mp_matrix_eig(_cimg_math_parser& mp) {  
18117 - double *ptrd = &_mp_arg(1) + 1;  
18118 - const double *ptr1 = &_mp_arg(2) + 1;  
18119 - const unsigned int k = (unsigned int)mp.opcode(3);  
18120 - CImg<double> val, vec;  
18121 - CImg<double>(ptr1,k,k,1,1,true).symmetric_eigen(val,vec);  
18122 - CImg<double>(ptrd,k,1,1,1,true) = val.unroll('x');  
18123 - CImg<double>(ptrd + k,k,k,1,1,true) = vec.get_transpose();  
18124 - return cimg::type<double>::nan();  
18125 - }  
18126 -  
18127 - static double mp_matrix_eye(_cimg_math_parser& mp) {  
18128 - double *ptrd = &_mp_arg(1) + 1;  
18129 - const unsigned int k = (unsigned int)mp.opcode(2);  
18130 - CImg<double>(ptrd,k,k,1,1,true).identity_matrix();  
18131 - return cimg::type<double>::nan();  
18132 - }  
18133 -  
18134 - static double mp_matrix_inv(_cimg_math_parser& mp) {  
18135 - double *ptrd = &_mp_arg(1) + 1;  
18136 - const double *ptr1 = &_mp_arg(2) + 1;  
18137 - const unsigned int k = (unsigned int)mp.opcode(3);  
18138 - CImg<double>(ptrd,k,k,1,1,true) = CImg<double>(ptr1,k,k,1,1,true).get_invert();  
18139 - return cimg::type<double>::nan();  
18140 - }  
18141 -  
18142 static double mp_matrix_mul(_cimg_math_parser& mp) { 18697 static double mp_matrix_mul(_cimg_math_parser& mp) {
18143 double *ptrd = &_mp_arg(1) + 1; 18698 double *ptrd = &_mp_arg(1) + 1;
18144 const double 18699 const double
@@ -18152,48 +18707,110 @@ namespace cimg_library_suffixed { @@ -18152,48 +18707,110 @@ namespace cimg_library_suffixed {
18152 return cimg::type<double>::nan(); 18707 return cimg::type<double>::nan();
18153 } 18708 }
18154 18709
18155 - static double mp_matrix_rot(_cimg_math_parser& mp) {  
18156 - double *ptrd = &_mp_arg(1) + 1;  
18157 - const float x = (float)_mp_arg(2), y = (float)_mp_arg(3), z = (float)_mp_arg(4), theta = (float)_mp_arg(5);  
18158 - CImg<double>(ptrd,3,3,1,1,true) = CImg<double>::rotation_matrix(x,y,z,theta);  
18159 - return cimg::type<double>::nan();  
18160 - }  
18161 -  
18162 - static double mp_matrix_solve(_cimg_math_parser& mp) {  
18163 - double *ptrd = &_mp_arg(1) + 1;  
18164 - const double  
18165 - *ptr1 = &_mp_arg(2) + 1,  
18166 - *ptr2 = &_mp_arg(3) + 1;  
18167 - const unsigned int  
18168 - k = (unsigned int)mp.opcode(4),  
18169 - l = (unsigned int)mp.opcode(5),  
18170 - m = (unsigned int)mp.opcode(6);  
18171 - CImg<double>(ptrd,m,l,1,1,true) = CImg<double>(ptr2,m,k,1,1,true).get_solve(CImg<double>(ptr1,l,k,1,1,true));  
18172 - return cimg::type<double>::nan();  
18173 - }  
18174 -  
18175 - static double mp_matrix_trace(_cimg_math_parser& mp) {  
18176 - const double *ptrs = &_mp_arg(2) + 1;  
18177 - const unsigned int k = (unsigned int)mp.opcode(3);  
18178 - return CImg<double>(ptrs,k,k,1,1,true).trace();  
18179 - }  
18180 -  
18181 - static double mp_matrix_trans(_cimg_math_parser& mp) {  
18182 - double *ptrd = &_mp_arg(1) + 1;  
18183 - const double *ptr1 = &_mp_arg(2) + 1;  
18184 - const unsigned int  
18185 - k = (unsigned int)mp.opcode(3),  
18186 - l = (unsigned int)mp.opcode(4);  
18187 - CImg<double>(ptrd,l,k,1,1,true) = CImg<double>(ptr1,k,l,1,1,true).get_transpose();  
18188 - return cimg::type<double>::nan();  
18189 - }  
18190 -  
18191 static double mp_max(_cimg_math_parser& mp) { 18710 static double mp_max(_cimg_math_parser& mp) {
18192 double val = _mp_arg(2); 18711 double val = _mp_arg(2);
18193 for (unsigned int i = 3; i<mp.opcode._height; ++i) val = cimg::max(val,_mp_arg(i)); 18712 for (unsigned int i = 3; i<mp.opcode._height; ++i) val = cimg::max(val,_mp_arg(i));
18194 return val; 18713 return val;
18195 } 18714 }
18196 18715
  18716 + static double* _mp_memcopy_double(_cimg_math_parser& mp, const unsigned int ind, const uptrT *const p_ref,
  18717 + const long siz, const long inc) {
  18718 + const long
  18719 + off = *p_ref?p_ref[1] + (long)mp.mem[(long)p_ref[2]] + 1:ind,
  18720 + eoff = off + (siz - 1)*inc;
  18721 + if (off<0 || eoff>=mp.mem.width())
  18722 + throw CImgArgumentException("[_cimg_math_parser] CImg<%s>: 'copy()': "
  18723 + "Out-of-bounds variable pointer "
  18724 + "(length: %ld, increment: %ld, offset start: %ld, "
  18725 + "offset end: %ld, offset max: %u).",
  18726 + mp.imgin.pixel_type(),siz,inc,off,eoff,mp.mem._width - 1);
  18727 + return &mp.mem[off];
  18728 + }
  18729 +
  18730 + static float* _mp_memcopy_float(_cimg_math_parser& mp, const uptrT *const p_ref,
  18731 + const long siz, const long inc) {
  18732 + const unsigned ind = p_ref[1];
  18733 + const CImg<T> &img = ind==~0U?mp.imgin:mp.listin[cimg::mod((int)mp.mem[ind],mp.listin.width())];
  18734 + const bool is_relative = (bool)p_ref[2];
  18735 + int ox, oy, oz, oc;
  18736 + long off = 0;
  18737 + if (is_relative) {
  18738 + ox = (int)mp.mem[_cimg_mp_x];
  18739 + oy = (int)mp.mem[_cimg_mp_y];
  18740 + oz = (int)mp.mem[_cimg_mp_z];
  18741 + oc = (int)mp.mem[_cimg_mp_c];
  18742 + off = img.offset(ox,oy,oz,oc);
  18743 + }
  18744 + if ((*p_ref)%2) {
  18745 + const int
  18746 + x = (int)mp.mem[p_ref[3]],
  18747 + y = (int)mp.mem[p_ref[4]],
  18748 + z = (int)mp.mem[p_ref[5]],
  18749 + c = *p_ref==5?0:(int)mp.mem[p_ref[6]];
  18750 + off+=(long)img.offset(x,y,z,c);
  18751 + } else off+=(long)mp.mem[p_ref[3]];
  18752 + const long eoff = off + (siz - 1)*inc;
  18753 + if (off<0 || eoff>=(long)img.size())
  18754 + throw CImgArgumentException("[_cimg_math_parser] CImg<%s>: Function 'copy()': "
  18755 + "Out-of-bounds image pointer "
  18756 + "(length: %ld, increment: %ld, offset start: %ld, "
  18757 + "offset end: %ld, offset max: %lu).",
  18758 + mp.imgin.pixel_type(),siz,inc,off,eoff,img.size() - 1);
  18759 + return (float*)&img[off];
  18760 + }
  18761 +
  18762 + static double mp_memcopy(_cimg_math_parser& mp) {
  18763 + long siz = (long)_mp_arg(4);
  18764 + const long inc_d = (long)_mp_arg(5), inc_s = (long)_mp_arg(6);
  18765 + if (siz>0) {
  18766 + const bool
  18767 + is_doubled = mp.opcode[7]<=1,
  18768 + is_doubles = mp.opcode[14]<=1;
  18769 + if (is_doubled && is_doubles) { // (double*) <- (double*)
  18770 + double *ptrd = _mp_memcopy_double(mp,mp.opcode[2],&mp.opcode[7],siz,inc_d);
  18771 + const double *ptrs = _mp_memcopy_double(mp,mp.opcode[3],&mp.opcode[14],siz,inc_s);
  18772 + if (inc_d==1 && inc_s==1) {
  18773 + if (ptrs + siz - 1<ptrd || ptrs>ptrd + siz - 1) std::memcpy(ptrd,ptrs,siz*sizeof(double));
  18774 + else std::memmove(ptrd,ptrs,siz*sizeof(double));
  18775 + } else {
  18776 + if (ptrs + (siz - 1)*inc_s<ptrd || ptrs>ptrd + (siz - 1)*inc_d)
  18777 + while (siz-->0) { *ptrd = (double)*ptrs; ptrd+=inc_d; ptrs+=inc_s; }
  18778 + else { // Overlapping buffers
  18779 + CImg<double> buf(siz);
  18780 + cimg_for(buf,ptr,double) { *ptr = *ptrs; ptrs+=inc_s; }
  18781 + ptrs = buf;
  18782 + while (siz-->0) { *ptrd = *(ptrs++); ptrd+=inc_d; }
  18783 + }
  18784 + }
  18785 + } else if (is_doubled && !is_doubles) { // (double*) <- (float*)
  18786 + double *ptrd = _mp_memcopy_double(mp,mp.opcode[2],&mp.opcode[7],siz,inc_d);
  18787 + const float *ptrs = _mp_memcopy_float(mp,&mp.opcode[14],siz,inc_s);
  18788 + while (siz-->0) { *ptrd = (double)*ptrs; ptrd+=inc_d; ptrs+=inc_s; }
  18789 + } else if (!is_doubled && is_doubles) { // (float*) <- (double*)
  18790 + float *ptrd = _mp_memcopy_float(mp,&mp.opcode[7],siz,inc_d);
  18791 + const double *ptrs = _mp_memcopy_double(mp,mp.opcode[3],&mp.opcode[14],siz,inc_s);
  18792 + while (siz-->0) { *ptrd = (float)*ptrs; ptrd+=inc_d; ptrs+=inc_s; }
  18793 + } else { // (float*) <- (float*)
  18794 + float *ptrd = _mp_memcopy_float(mp,&mp.opcode[7],siz,inc_d);
  18795 + const float *ptrs = _mp_memcopy_float(mp,&mp.opcode[14],siz,inc_s);
  18796 + if (inc_d==1 && inc_s==1) {
  18797 + if (ptrs + siz - 1<ptrd || ptrs>ptrd + siz - 1) std::memcpy(ptrd,ptrs,siz*sizeof(float));
  18798 + else std::memmove(ptrd,ptrs,siz*sizeof(float));
  18799 + } else {
  18800 + if (ptrs + (siz - 1)*inc_s<ptrd || ptrs>ptrd + (siz - 1)*inc_d)
  18801 + while (siz-->0) { *ptrd = (float)*ptrs; ptrd+=inc_d; ptrs+=inc_s; }
  18802 + else { // Overlapping buffers
  18803 + CImg<float> buf(siz);
  18804 + cimg_for(buf,ptr,float) { *ptr = *ptrs; ptrs+=inc_s; }
  18805 + ptrs = buf;
  18806 + while (siz-->0) { *ptrd = *(ptrs++); ptrd+=inc_d; }
  18807 + }
  18808 + }
  18809 + }
  18810 + }
  18811 + return _mp_arg(1);
  18812 + }
  18813 +
18197 static double mp_min(_cimg_math_parser& mp) { 18814 static double mp_min(_cimg_math_parser& mp) {
18198 double val = _mp_arg(2); 18815 double val = _mp_arg(2);
18199 for (unsigned int i = 3; i<mp.opcode._height; ++i) val = cimg::min(val,_mp_arg(i)); 18816 for (unsigned int i = 3; i<mp.opcode._height; ++i) val = cimg::min(val,_mp_arg(i));
@@ -18204,6 +18821,12 @@ namespace cimg_library_suffixed { @@ -18204,6 +18821,12 @@ namespace cimg_library_suffixed {
18204 return -_mp_arg(2); 18821 return -_mp_arg(2);
18205 } 18822 }
18206 18823
  18824 + static double mp_mean(_cimg_math_parser& mp) {
  18825 + double val = _mp_arg(2);
  18826 + for (unsigned int i = 3; i<mp.opcode._height; ++i) val+=_mp_arg(i);
  18827 + return val/(mp.opcode._height - 2);
  18828 + }
  18829 +
18207 static double mp_med(_cimg_math_parser& mp) { 18830 static double mp_med(_cimg_math_parser& mp) {
18208 CImg<doubleT> vals(mp.opcode._height - 2); 18831 CImg<doubleT> vals(mp.opcode._height - 2);
18209 double *p = vals.data(); 18832 double *p = vals.data();
@@ -18278,13 +18901,26 @@ namespace cimg_library_suffixed { @@ -18278,13 +18901,26 @@ namespace cimg_library_suffixed {
18278 } 18901 }
18279 18902
18280 static double mp_print(_cimg_math_parser& mp) { 18903 static double mp_print(_cimg_math_parser& mp) {
  18904 + cimg::mutex(6);
18281 CImg<charT> expr(mp.opcode._height - 2); 18905 CImg<charT> expr(mp.opcode._height - 2);
18282 const uptrT *ptrs = mp.opcode._data + 2; 18906 const uptrT *ptrs = mp.opcode._data + 2;
18283 cimg_for(expr,ptrd,char) *ptrd = (char)*(ptrs++); 18907 cimg_for(expr,ptrd,char) *ptrd = (char)*(ptrs++);
18284 cimg::strellipsize(expr); 18908 cimg::strellipsize(expr);
18285 const double val = _mp_arg(1); 18909 const double val = _mp_arg(1);
18286 - std::fprintf(cimg::output(),"\n[_cimg_math_parser] %s = %g",expr._data,val);  
18287 - std::fflush(cimg::output()); 18910 +#ifdef cimg_use_openmp
  18911 +#pragma omp critical
  18912 +#endif
  18913 + {
  18914 + std::fprintf(cimg::output(),"\n[_cimg_math_parser] %s = %g",expr._data,val);
  18915 + std::fflush(cimg::output());
  18916 + }
  18917 + cimg::mutex(6,0);
  18918 + return val;
  18919 + }
  18920 +
  18921 + static double mp_prod(_cimg_math_parser& mp) {
  18922 + double val = _mp_arg(2);
  18923 + for (unsigned int i = 3; i<mp.opcode._height; ++i) val*=_mp_arg(i);
18288 return val; 18924 return val;
18289 } 18925 }
18290 18926
@@ -18300,6 +18936,26 @@ namespace cimg_library_suffixed { @@ -18300,6 +18936,26 @@ namespace cimg_library_suffixed {
18300 return cimg::ror(_mp_arg(2),(unsigned int)_mp_arg(3)); 18936 return cimg::ror(_mp_arg(2),(unsigned int)_mp_arg(3));
18301 } 18937 }
18302 18938
  18939 + static double mp_rot2d(_cimg_math_parser& mp) {
  18940 + double *ptrd = &_mp_arg(1) + 1;
  18941 + const float
  18942 + theta = (float)_mp_arg(2),
  18943 + ca = std::cos(theta),
  18944 + sa = std::sin(theta);
  18945 + *(ptrd++) = ca;
  18946 + *(ptrd++) = -sa;
  18947 + *(ptrd++) = sa;
  18948 + *ptrd = ca;
  18949 + return cimg::type<double>::nan();
  18950 + }
  18951 +
  18952 + static double mp_rot3d(_cimg_math_parser& mp) {
  18953 + double *ptrd = &_mp_arg(1) + 1;
  18954 + const float x = (float)_mp_arg(2), y = (float)_mp_arg(3), z = (float)_mp_arg(4), theta = (float)_mp_arg(5);
  18955 + CImg<double>(ptrd,3,3,1,1,true) = CImg<double>::rotation_matrix(x,y,z,theta);
  18956 + return cimg::type<double>::nan();
  18957 + }
  18958 +
18303 static double mp_round(_cimg_math_parser& mp) { 18959 static double mp_round(_cimg_math_parser& mp) {
18304 return cimg::round(_mp_arg(2),_mp_arg(3),(int)_mp_arg(4)); 18960 return cimg::round(_mp_arg(2),_mp_arg(3),(int)_mp_arg(4));
18305 } 18961 }
@@ -18403,9 +19059,8 @@ namespace cimg_library_suffixed { @@ -18403,9 +19059,8 @@ namespace cimg_library_suffixed {
18403 z = (int)_mp_arg(4), c = (int)_mp_arg(5); 19059 z = (int)_mp_arg(4), c = (int)_mp_arg(5);
18404 const double val = _mp_arg(1); 19060 const double val = _mp_arg(1);
18405 if (x>=0 && x<img.width() && y>=0 && y<img.height() && 19061 if (x>=0 && x<img.width() && y>=0 && y<img.height() &&
18406 - z>=0 && z<img.depth() && c>=0 && c<img.spectrum()) { 19062 + z>=0 && z<img.depth() && c>=0 && c<img.spectrum())
18407 img(x,y,z,c) = (T)val; 19063 img(x,y,z,c) = (T)val;
18408 - }  
18409 return val; 19064 return val;
18410 } 19065 }
18411 19066
@@ -18432,9 +19087,8 @@ namespace cimg_library_suffixed { @@ -18432,9 +19087,8 @@ namespace cimg_library_suffixed {
18432 z = (int)(oz + _mp_arg(4)), c = (int)(oc + _mp_arg(5)); 19087 z = (int)(oz + _mp_arg(4)), c = (int)(oc + _mp_arg(5));
18433 const double val = _mp_arg(1); 19088 const double val = _mp_arg(1);
18434 if (x>=0 && x<img.width() && y>=0 && y<img.height() && 19089 if (x>=0 && x<img.width() && y>=0 && y<img.height() &&
18435 - z>=0 && z<img.depth() && c>=0 && c<img.spectrum()) { 19090 + z>=0 && z<img.depth() && c>=0 && c<img.spectrum())
18436 img(x,y,z,c) = (T)val; 19091 img(x,y,z,c) = (T)val;
18437 - }  
18438 return val; 19092 return val;
18439 } 19093 }
18440 19094
@@ -18558,10 +19212,53 @@ namespace cimg_library_suffixed { @@ -18558,10 +19212,53 @@ namespace cimg_library_suffixed {
18558 return cimg::sinc(_mp_arg(2)); 19212 return cimg::sinc(_mp_arg(2));
18559 } 19213 }
18560 19214
  19215 + static double mp_single(_cimg_math_parser& mp) {
  19216 + const double res = _mp_arg(1);
  19217 +#ifdef cimg_use_openmp
  19218 +#pragma omp critical
  19219 +#endif
  19220 + {
  19221 + for (const CImg<uptrT> *const p_end = ++mp.p_code + mp.opcode[2];
  19222 + mp.p_code<p_end; ++mp.p_code) { // Evaluate loop iteration + condition
  19223 + const CImg<uptrT> &op = *mp.p_code;
  19224 + mp.opcode._data = op._data; mp.opcode._height = op._height;
  19225 + const uptrT target = mp.opcode[1];
  19226 + mp.mem[target] = _cimg_mp_defunc(mp);
  19227 + }
  19228 + }
  19229 + --mp.p_code;
  19230 + return res;
  19231 + }
  19232 +
18561 static double mp_sinh(_cimg_math_parser& mp) { 19233 static double mp_sinh(_cimg_math_parser& mp) {
18562 return std::sinh(_mp_arg(2)); 19234 return std::sinh(_mp_arg(2));
18563 } 19235 }
18564 19236
  19237 + static double mp_solve(_cimg_math_parser& mp) {
  19238 + double *ptrd = &_mp_arg(1) + 1;
  19239 + const double
  19240 + *ptr1 = &_mp_arg(2) + 1,
  19241 + *ptr2 = &_mp_arg(3) + 1;
  19242 + const unsigned int
  19243 + k = (unsigned int)mp.opcode(4),
  19244 + l = (unsigned int)mp.opcode(5),
  19245 + m = (unsigned int)mp.opcode(6);
  19246 + CImg<double>(ptrd,m,k,1,1,true) = CImg<double>(ptr2,m,l,1,1,true).get_solve(CImg<double>(ptr1,k,l,1,1,true));
  19247 + return cimg::type<double>::nan();
  19248 + }
  19249 +
  19250 + static double mp_sort(_cimg_math_parser& mp) {
  19251 + double *const ptrd = &_mp_arg(1) + 1;
  19252 + const double *const ptrs = &_mp_arg(2) + 1;
  19253 + const unsigned int
  19254 + siz = mp.opcode[3],
  19255 + chunk_siz = mp.opcode[5];
  19256 + const bool is_increasing = (bool)_mp_arg(4);
  19257 + CImg<doubleT>(ptrd,chunk_siz,siz/chunk_siz,1,1,true) = CImg<doubleT>(ptrs,chunk_siz,siz/chunk_siz,1,1,true).
  19258 + get_sort(is_increasing,chunk_siz>1?'y':0);
  19259 + return cimg::type<double>::nan();
  19260 + }
  19261 +
18565 static double mp_sqr(_cimg_math_parser& mp) { 19262 static double mp_sqr(_cimg_math_parser& mp) {
18566 return cimg::sqr(_mp_arg(2)); 19263 return cimg::sqr(_mp_arg(2));
18567 } 19264 }
@@ -18570,10 +19267,23 @@ namespace cimg_library_suffixed { @@ -18570,10 +19267,23 @@ namespace cimg_library_suffixed {
18570 return std::sqrt(_mp_arg(2)); 19267 return std::sqrt(_mp_arg(2));
18571 } 19268 }
18572 19269
  19270 + static double mp_std(_cimg_math_parser& mp) {
  19271 + CImg<doubleT> vals(mp.opcode._height - 2);
  19272 + double *p = vals.data();
  19273 + for (unsigned int i = 2; i<mp.opcode._height; ++i) *(p++) = _mp_arg(i);
  19274 + return std::sqrt(vals.variance());
  19275 + }
  19276 +
18573 static double mp_sub(_cimg_math_parser& mp) { 19277 static double mp_sub(_cimg_math_parser& mp) {
18574 return _mp_arg(2) - _mp_arg(3); 19278 return _mp_arg(2) - _mp_arg(3);
18575 } 19279 }
18576 19280
  19281 + static double mp_sum(_cimg_math_parser& mp) {
  19282 + double val = _mp_arg(2);
  19283 + for (unsigned int i = 3; i<mp.opcode._height; ++i) val+=_mp_arg(i);
  19284 + return val;
  19285 + }
  19286 +
18577 static double mp_tan(_cimg_math_parser& mp) { 19287 static double mp_tan(_cimg_math_parser& mp) {
18578 return std::tan(_mp_arg(2)); 19288 return std::tan(_mp_arg(2));
18579 } 19289 }
@@ -18582,10 +19292,33 @@ namespace cimg_library_suffixed { @@ -18582,10 +19292,33 @@ namespace cimg_library_suffixed {
18582 return std::tanh(_mp_arg(2)); 19292 return std::tanh(_mp_arg(2));
18583 } 19293 }
18584 19294
  19295 + static double mp_trace(_cimg_math_parser& mp) {
  19296 + const double *ptrs = &_mp_arg(2) + 1;
  19297 + const unsigned int k = (unsigned int)mp.opcode(3);
  19298 + return CImg<double>(ptrs,k,k,1,1,true).trace();
  19299 + }
  19300 +
  19301 + static double mp_transp(_cimg_math_parser& mp) {
  19302 + double *ptrd = &_mp_arg(1) + 1;
  19303 + const double *ptr1 = &_mp_arg(2) + 1;
  19304 + const unsigned int
  19305 + k = (unsigned int)mp.opcode(3),
  19306 + l = (unsigned int)mp.opcode(4);
  19307 + CImg<double>(ptrd,l,k,1,1,true) = CImg<double>(ptr1,k,l,1,1,true).get_transpose();
  19308 + return cimg::type<double>::nan();
  19309 + }
  19310 +
18585 static double mp_u(_cimg_math_parser& mp) { 19311 static double mp_u(_cimg_math_parser& mp) {
18586 return cimg::rand(_mp_arg(2),_mp_arg(3)); 19312 return cimg::rand(_mp_arg(2),_mp_arg(3));
18587 } 19313 }
18588 19314
  19315 + static double mp_var(_cimg_math_parser& mp) {
  19316 + CImg<doubleT> vals(mp.opcode._height - 2);
  19317 + double *p = vals.data();
  19318 + for (unsigned int i = 2; i<mp.opcode._height; ++i) *(p++) = _mp_arg(i);
  19319 + return vals.variance();
  19320 + }
  19321 +
18589 static double mp_vector_copy(_cimg_math_parser& mp) { 19322 static double mp_vector_copy(_cimg_math_parser& mp) {
18590 std::memcpy(&_mp_arg(1) + 1,&_mp_arg(2) + 1,sizeof(double)*mp.opcode[3]); 19323 std::memcpy(&_mp_arg(1) + 1,&_mp_arg(2) + 1,sizeof(double)*mp.opcode[3]);
18591 return cimg::type<double>::nan(); 19324 return cimg::type<double>::nan();
@@ -18704,15 +19437,6 @@ namespace cimg_library_suffixed { @@ -18704,15 +19437,6 @@ namespace cimg_library_suffixed {
18704 return _mp_arg(5); 19437 return _mp_arg(5);
18705 } 19438 }
18706 19439
18707 - static double mp_vector_sort(_cimg_math_parser& mp) {  
18708 - double *const ptrd = &_mp_arg(1) + 1;  
18709 - const double *const ptrs = &_mp_arg(2) + 1;  
18710 - const unsigned int siz = mp.opcode[3];  
18711 - const bool is_increasing = (bool)_mp_arg(4);  
18712 - CImg<doubleT>(ptrd,1,siz,1,1,true) = CImg<doubleT>(ptrs,1,siz,1,1,true).get_sort(is_increasing);  
18713 - return cimg::type<double>::nan();  
18714 - }  
18715 -  
18716 static double mp_vector_print(_cimg_math_parser& mp) { 19440 static double mp_vector_print(_cimg_math_parser& mp) {
18717 CImg<charT> expr(mp.opcode._height - 3); 19441 CImg<charT> expr(mp.opcode._height - 3);
18718 const uptrT *ptrs = mp.opcode._data + 3; 19442 const uptrT *ptrs = mp.opcode._data + 3;
@@ -20185,7 +20909,8 @@ namespace cimg_library_suffixed { @@ -20185,7 +20909,8 @@ namespace cimg_library_suffixed {
20185 case 's' : return (double)_spectrum; 20909 case 's' : return (double)_spectrum;
20186 case 'r' : return (double)_is_shared; 20910 case 'r' : return (double)_is_shared;
20187 } 20911 }
20188 - _cimg_math_parser mp(expression + (*expression=='>' || *expression=='<' || *expression=='*'?1:0),"eval", 20912 + _cimg_math_parser mp(expression + (*expression=='>' || *expression=='<' ||
  20913 + *expression=='*' || *expression==':'?1:0),"eval",
20189 *this,img_output,list_inputs,list_outputs); 20914 *this,img_output,list_inputs,list_outputs);
20190 return mp(x,y,z,c); 20915 return mp(x,y,z,c);
20191 } 20916 }
@@ -20229,7 +20954,8 @@ namespace cimg_library_suffixed { @@ -20229,7 +20954,8 @@ namespace cimg_library_suffixed {
20229 case 's' : output.assign(1); *output = (t)_spectrum; 20954 case 's' : output.assign(1); *output = (t)_spectrum;
20230 case 'r' : output.assign(1); *output = (t)_is_shared; 20955 case 'r' : output.assign(1); *output = (t)_is_shared;
20231 } 20956 }
20232 - _cimg_math_parser mp(expression + (*expression=='>' || *expression=='<' || *expression=='*'?1:0),"eval", 20957 + _cimg_math_parser mp(expression + (*expression=='>' || *expression=='<' ||
  20958 + *expression=='*' || *expression==':'?1:0),"eval",
20233 *this,img_output,list_inputs,list_outputs); 20959 *this,img_output,list_inputs,list_outputs);
20234 output.assign(1,cimg::max(1U,mp.result_dim)); 20960 output.assign(1,cimg::max(1U,mp.result_dim));
20235 mp(x,y,z,c,output._data); 20961 mp(x,y,z,c,output._data);
@@ -20823,13 +21549,13 @@ namespace cimg_library_suffixed { @@ -20823,13 +21549,13 @@ namespace cimg_library_suffixed {
20823 "incompatible dimensions.", 21549 "incompatible dimensions.",
20824 cimg_instance, 21550 cimg_instance,
20825 A._width,A._height,A._depth,A._spectrum,A._data); 21551 A._width,A._height,A._depth,A._spectrum,A._data);
20826 - if (_width!=1) {  
20827 - cimg_forX(*this,i) draw_image(i,get_column(i).solve(A));  
20828 - return *this;  
20829 - }  
20830 -  
20831 typedef _cimg_Ttfloat Ttfloat; 21552 typedef _cimg_Ttfloat Ttfloat;
20832 - if (A._width==A._height) { 21553 + if (A._width==A._height) { // Classical linear system
  21554 + if (_width!=1) {
  21555 + CImg<T> res(_width,A._width);
  21556 + cimg_forX(*this,i) res.draw_image(i,get_column(i).solve(A));
  21557 + return res.move_to(*this);
  21558 + }
20833 #ifdef cimg_use_lapack 21559 #ifdef cimg_use_lapack
20834 char TRANS = 'N'; 21560 char TRANS = 'N';
20835 int INFO, N = _height, LWORK = 4*N, *const IPIV = new int[N]; 21561 int INFO, N = _height, LWORK = 4*N, *const IPIV = new int[N];
@@ -20865,6 +21591,11 @@ namespace cimg_library_suffixed { @@ -20865,6 +21591,11 @@ namespace cimg_library_suffixed {
20865 #endif 21591 #endif
20866 } else { // Least-square solution for non-square systems. 21592 } else { // Least-square solution for non-square systems.
20867 #ifdef cimg_use_lapack 21593 #ifdef cimg_use_lapack
  21594 + if (_width!=1) {
  21595 + CImg<T> res(_width,A._width);
  21596 + cimg_forX(*this,i) res.draw_image(i,get_column(i).solve(A));
  21597 + return res.move_to(*this);
  21598 + }
20868 char TRANS = 'N'; 21599 char TRANS = 'N';
20869 int INFO, N = A._width, M = A._height, LWORK = -1, LDA = M, LDB = M, NRHS = _width; 21600 int INFO, N = A._width, M = A._height, LWORK = -1, LDA = M, LDB = M, NRHS = _width;
20870 Ttfloat WORK_QUERY; 21601 Ttfloat WORK_QUERY;
@@ -22393,24 +23124,25 @@ namespace cimg_library_suffixed { @@ -22393,24 +23124,25 @@ namespace cimg_library_suffixed {
22393 23124
22394 CImg<T>& _fill(const char *const expression, const bool repeat_values, const bool allow_formula, 23125 CImg<T>& _fill(const char *const expression, const bool repeat_values, const bool allow_formula,
22395 const CImgList<T> *const list_inputs, CImgList<T> *const list_outputs, 23126 const CImgList<T> *const list_inputs, CImgList<T> *const list_outputs,
22396 - const char *const calling_function, const CImg<T> *provide_base) { 23127 + const char *const calling_function, const CImg<T> *provides_copy) {
22397 if (is_empty() || !expression || !*expression) return *this; 23128 if (is_empty() || !expression || !*expression) return *this;
22398 const unsigned int omode = cimg::exception_mode(); 23129 const unsigned int omode = cimg::exception_mode();
22399 cimg::exception_mode(0); 23130 cimg::exception_mode(0);
22400 CImg<charT> is_error; 23131 CImg<charT> is_error;
22401 23132
22402 if (allow_formula) try { // Try to fill values according to a formula 23133 if (allow_formula) try { // Try to fill values according to a formula
22403 - bool is_parallelizable = true;  
22404 - const CImg<T>  
22405 - _base = _cimg_math_parser::needs_input_copy(expression,is_parallelizable)?  
22406 - (provide_base?*provide_base:+*this):CImg<T>(),  
22407 - &base = provide_base?*provide_base:_base?_base:*this;  
22408 - _cimg_math_parser mp(expression + (*expression=='>' || *expression=='<' || *expression=='*'?1:0), 23134 + CImg<T> base = provides_copy?provides_copy->get_shared():get_shared();
  23135 + _cimg_math_parser mp(expression + (*expression=='>' || *expression=='<' ||
  23136 + *expression=='*' || *expression==':'?1:0),
22409 calling_function,base,this,list_inputs,list_outputs); 23137 calling_function,base,this,list_inputs,list_outputs);
  23138 + if (!provides_copy && expression && *expression!='>' && *expression!='<' && *expression!=':' &&
  23139 + mp.need_input_copy)
  23140 + base.assign().assign(*this); // Needs input copy
  23141 +
22410 bool do_in_parallel = false; 23142 bool do_in_parallel = false;
22411 #ifdef cimg_use_openmp 23143 #ifdef cimg_use_openmp
22412 - cimg_openmp_if(*expression=='*' ||  
22413 - (is_parallelizable && _width>=320 && _height*_depth*_spectrum>=2 && 23144 + cimg_openmp_if(*expression=='*' || *expression==':' ||
  23145 + (mp.is_parallelizable && _width>=320 && _height*_depth*_spectrum>=2 &&
22414 std::strlen(expression)>=6)) 23146 std::strlen(expression)>=6))
22415 do_in_parallel = true; 23147 do_in_parallel = true;
22416 #endif 23148 #endif
@@ -26443,18 +27175,20 @@ namespace cimg_library_suffixed { @@ -26443,18 +27175,20 @@ namespace cimg_library_suffixed {
26443 \param boundary Boundary conditions. Can be <tt>{ 0=dirichlet | 1=neumann | 2=periodic }</tt>. 27175 \param boundary Boundary conditions. Can be <tt>{ 0=dirichlet | 1=neumann | 2=periodic }</tt>.
26444 \note Most of the time, size of the image is modified. 27176 \note Most of the time, size of the image is modified.
26445 **/ 27177 **/
26446 - CImg<T>& rotate(const float angle, const unsigned int interpolation=1, const unsigned int boundary=0) { 27178 + CImg<T>& rotate(const float angle, const unsigned int interpolation=1,
  27179 + const unsigned int boundary_conditions=0) {
26447 const float nangle = cimg::mod(angle,360.0f); 27180 const float nangle = cimg::mod(angle,360.0f);
26448 if (nangle==0.0f) return *this; 27181 if (nangle==0.0f) return *this;
26449 - return get_rotate(angle,interpolation,boundary).move_to(*this); 27182 + return get_rotate(angle,interpolation,boundary_conditions).move_to(*this);
26450 } 27183 }
26451 27184
26452 //! Rotate image with arbitrary angle \newinstance. 27185 //! Rotate image with arbitrary angle \newinstance.
26453 - CImg<T> get_rotate(const float angle, const unsigned int interpolation=1, const unsigned int boundary=0) const { 27186 + CImg<T> get_rotate(const float angle, const unsigned int interpolation=1,
  27187 + const unsigned int boundary_conditions=0) const {
26454 if (is_empty()) return *this; 27188 if (is_empty()) return *this;
26455 CImg<T> res; 27189 CImg<T> res;
26456 const float nangle = cimg::mod(angle,360.0f); 27190 const float nangle = cimg::mod(angle,360.0f);
26457 - if (boundary!=1 && cimg::mod(nangle,90.0f)==0) { // Optimized version for orthogonal angles. 27191 + if (boundary_conditions!=1 && cimg::mod(nangle,90.0f)==0) { // Optimized version for orthogonal angles.
26458 const int wm1 = width() - 1, hm1 = height() - 1; 27192 const int wm1 = width() - 1, hm1 = height() - 1;
26459 const int iangle = (int)nangle/90; 27193 const int iangle = (int)nangle/90;
26460 switch (iangle) { 27194 switch (iangle) {
@@ -26487,7 +27221,7 @@ namespace cimg_library_suffixed { @@ -26487,7 +27221,7 @@ namespace cimg_library_suffixed {
26487 w2 = 0.5f*_width, h2 = 0.5f*_height, 27221 w2 = 0.5f*_width, h2 = 0.5f*_height,
26488 dw2 = 0.5f*(ux + vx), dh2 = 0.5f*(uy + vy); 27222 dw2 = 0.5f*(ux + vx), dh2 = 0.5f*(uy + vy);
26489 res.assign((int)(ux + vx),(int)(uy + vy),_depth,_spectrum); 27223 res.assign((int)(ux + vx),(int)(uy + vy),_depth,_spectrum);
26490 - switch (boundary) { 27224 + switch (boundary_conditions) {
26491 case 0 : { // Dirichlet boundaries. 27225 case 0 : { // Dirichlet boundaries.
26492 switch (interpolation) { 27226 switch (interpolation) {
26493 case 2 : { // Cubic interpolation. 27227 case 2 : { // Cubic interpolation.
@@ -26577,7 +27311,7 @@ namespace cimg_library_suffixed { @@ -26577,7 +27311,7 @@ namespace cimg_library_suffixed {
26577 "rotate(): Invalid specified border conditions %d " 27311 "rotate(): Invalid specified border conditions %d "
26578 "(should be { 0=dirichlet | 1=neumann | 2=periodic }).", 27312 "(should be { 0=dirichlet | 1=neumann | 2=periodic }).",
26579 cimg_instance, 27313 cimg_instance,
26580 - boundary); 27314 + boundary_conditions);
26581 } 27315 }
26582 } 27316 }
26583 return res; 27317 return res;
@@ -26593,13 +27327,13 @@ namespace cimg_library_suffixed { @@ -26593,13 +27327,13 @@ namespace cimg_library_suffixed {
26593 \param interpolation_type Type of interpolation. Can be <tt>{ 0=nearest | 1=linear | 2=cubic }</tt>. 27327 \param interpolation_type Type of interpolation. Can be <tt>{ 0=nearest | 1=linear | 2=cubic }</tt>.
26594 **/ 27328 **/
26595 CImg<T>& rotate(const float angle, const float cx, const float cy, const float zoom, 27329 CImg<T>& rotate(const float angle, const float cx, const float cy, const float zoom,
26596 - const unsigned int interpolation=1, const unsigned int boundary=3) {  
26597 - return get_rotate(angle,cx,cy,zoom,interpolation,boundary).move_to(*this); 27330 + const unsigned int interpolation=1, const unsigned int boundary_conditions=0) {
  27331 + return get_rotate(angle,cx,cy,zoom,interpolation,boundary_conditions).move_to(*this);
26598 } 27332 }
26599 27333
26600 //! Rotate image with arbitrary angle, around a center point \newinstance. 27334 //! Rotate image with arbitrary angle, around a center point \newinstance.
26601 CImg<T> get_rotate(const float angle, const float cx, const float cy, const float zoom, 27335 CImg<T> get_rotate(const float angle, const float cx, const float cy, const float zoom,
26602 - const unsigned int interpolation=1, const unsigned int boundary=3) const { 27336 + const unsigned int interpolation=1, const unsigned int boundary_conditions=0) const {
26603 if (interpolation>2) 27337 if (interpolation>2)
26604 throw CImgArgumentException(_cimg_instance 27338 throw CImgArgumentException(_cimg_instance
26605 "rotate(): Invalid specified interpolation type %d " 27339 "rotate(): Invalid specified interpolation type %d "
@@ -26613,7 +27347,7 @@ namespace cimg_library_suffixed { @@ -26613,7 +27347,7 @@ namespace cimg_library_suffixed {
26613 rad = (float)((angle*cimg::PI)/180.0), 27347 rad = (float)((angle*cimg::PI)/180.0),
26614 ca = (float)std::cos(rad)/zoom, 27348 ca = (float)std::cos(rad)/zoom,
26615 sa = (float)std::sin(rad)/zoom; 27349 sa = (float)std::sin(rad)/zoom;
26616 - switch (boundary) { 27350 + switch (boundary_conditions) {
26617 case 0 : { 27351 case 0 : {
26618 switch (interpolation) { 27352 switch (interpolation) {
26619 case 2 : { 27353 case 2 : {
@@ -26703,7 +27437,7 @@ namespace cimg_library_suffixed { @@ -26703,7 +27437,7 @@ namespace cimg_library_suffixed {
26703 "rotate(): Invalid specified border conditions %d " 27437 "rotate(): Invalid specified border conditions %d "
26704 "(should be { 0=dirichlet | 1=neumann | 2=periodic }).", 27438 "(should be { 0=dirichlet | 1=neumann | 2=periodic }).",
26705 cimg_instance, 27439 cimg_instance,
26706 - boundary); 27440 + boundary_conditions);
26707 } 27441 }
26708 return res; 27442 return res;
26709 } 27443 }
@@ -29523,12 +30257,25 @@ namespace cimg_library_suffixed { @@ -29523,12 +30257,25 @@ namespace cimg_library_suffixed {
29523 //! Compute watershed transform. 30257 //! Compute watershed transform.
29524 /** 30258 /**
29525 \param priority Priority map. 30259 \param priority Priority map.
29526 - \param fill_lines Tells if watershed lines must be filled or not. 30260 + \param is_high_connectivity Boolean that choose between 4(false)- or 8(true)-connectivity
  30261 + in 2d case, and between 6(false)- or 26(true)-connectivity in 3d case.
29527 \note Non-zero values of the instance instance are propagated to zero-valued ones according to 30262 \note Non-zero values of the instance instance are propagated to zero-valued ones according to
29528 - specified the priority map. 30263 + specified the priority map.
29529 **/ 30264 **/
29530 template<typename t> 30265 template<typename t>
29531 - CImg<T>& watershed(const CImg<t>& priority, const bool fill_lines=true) { 30266 + CImg<T>& watershed(const CImg<t>& priority, const bool is_high_connectivity=false) {
  30267 +#define _cimg_watershed_init(cond,X,Y,Z) \
  30268 + if (cond && !(*this)(X,Y,Z)) Q._priority_queue_insert(labels,sizeQ,priority(X,Y,Z),X,Y,Z,nb_seeds)
  30269 +
  30270 +#define _cimg_watershed_propagate(cond,X,Y,Z) \
  30271 + if (cond) { \
  30272 + if ((*this)(X,Y,Z)) { \
  30273 + ns = labels(X,Y,Z) - 1; xs = seeds(ns,0); ys = seeds(ns,1); zs = seeds(ns,2); \
  30274 + d = cimg::sqr((float)x - xs) + cimg::sqr((float)y - ys) + cimg::sqr((float)z - zs); \
  30275 + if (d<dmin) { dmin = d; nmin = ns; label = (*this)(xs,ys,zs); } \
  30276 + } else Q._priority_queue_insert(labels,sizeQ,priority(X,Y,Z),X,Y,Z,n); \
  30277 + }
  30278 +
29532 if (is_empty()) return *this; 30279 if (is_empty()) return *this;
29533 if (!is_sameXYZ(priority)) 30280 if (!is_sameXYZ(priority))
29534 throw CImgArgumentException(_cimg_instance 30281 throw CImgArgumentException(_cimg_instance
@@ -29538,29 +30285,62 @@ namespace cimg_library_suffixed { @@ -29538,29 +30285,62 @@ namespace cimg_library_suffixed {
29538 priority._width,priority._height,priority._depth,priority._spectrum,priority._data); 30285 priority._width,priority._height,priority._depth,priority._spectrum,priority._data);
29539 if (_spectrum!=1) { 30286 if (_spectrum!=1) {
29540 cimg_forC(*this,c) 30287 cimg_forC(*this,c)
29541 - get_shared_channel(c).watershed(priority.get_shared_channel(c%priority._spectrum),fill_lines); 30288 + get_shared_channel(c).watershed(priority.get_shared_channel(c%priority._spectrum));
29542 return *this; 30289 return *this;
29543 } 30290 }
29544 30291
29545 - CImg<boolT> is_queued(_width,_height,_depth,1,0); 30292 + CImg<uintT> labels(_width,_height,_depth,1,0), seeds(64,3);
29546 CImg<typename cimg::superset2<T,t,int>::type> Q; 30293 CImg<typename cimg::superset2<T,t,int>::type> Q;
29547 unsigned int sizeQ = 0; 30294 unsigned int sizeQ = 0;
  30295 + int px, nx, py, ny, pz, nz;
  30296 + bool is_px, is_nx, is_py, is_ny, is_pz, is_nz;
  30297 + const bool is_3d = _depth>1;
29548 30298
29549 // Find seed points and insert them in priority queue. 30299 // Find seed points and insert them in priority queue.
  30300 + unsigned int nb_seeds = 0;
29550 const T *ptrs = _data; 30301 const T *ptrs = _data;
29551 - cimg_forXYZ(*this,x,y,z) if (*(ptrs++)) {  
29552 - if (x - 1>=0 && !(*this)(x - 1,y,z))  
29553 - Q._priority_queue_insert(is_queued,sizeQ,priority(x - 1,y,z),x - 1,y,z);  
29554 - if (x + 1<width() && !(*this)(x + 1,y,z))  
29555 - Q._priority_queue_insert(is_queued,sizeQ,priority(x + 1,y,z),x + 1,y,z);  
29556 - if (y - 1>=0 && !(*this)(x,y - 1,z))  
29557 - Q._priority_queue_insert(is_queued,sizeQ,priority(x,y - 1,z),x,y - 1,z);  
29558 - if (y + 1<height() && !(*this)(x,y + 1,z))  
29559 - Q._priority_queue_insert(is_queued,sizeQ,priority(x,y + 1,z),x,y + 1,z);  
29560 - if (z - 1>=0 && !(*this)(x,y,z - 1))  
29561 - Q._priority_queue_insert(is_queued,sizeQ,priority(x,y,z - 1),x,y,z - 1);  
29562 - if (z + 1<depth() && !(*this)(x,y,z + 1))  
29563 - Q._priority_queue_insert(is_queued,sizeQ,priority(x,y,z + 1),x,y,z + 1); 30302 + cimg_forXYZ(*this,x,y,z) if (*(ptrs++)) { // 3d version
  30303 + if (nb_seeds>=seeds._width) seeds.resize(2*seeds._width,3,1,1,0);
  30304 + seeds(nb_seeds,0) = x; seeds(nb_seeds,1) = y; seeds(nb_seeds++,2) = z;
  30305 + px = x - 1; nx = x + 1;
  30306 + py = y - 1; ny = y + 1;
  30307 + pz = z - 1; nz = z + 1;
  30308 + is_px = px>=0; is_nx = nx<width();
  30309 + is_py = py>=0; is_ny = ny<height();
  30310 + is_pz = pz>=0; is_nz = nz<depth();
  30311 + _cimg_watershed_init(is_px,px,y,z);
  30312 + _cimg_watershed_init(is_nx,nx,y,z);
  30313 + _cimg_watershed_init(is_py,x,py,z);
  30314 + _cimg_watershed_init(is_ny,x,ny,z);
  30315 + if (is_3d) {
  30316 + _cimg_watershed_init(is_pz,x,y,pz);
  30317 + _cimg_watershed_init(is_nz,x,y,nz);
  30318 + }
  30319 + if (is_high_connectivity) {
  30320 + _cimg_watershed_init(is_px && is_py,px,py,z);
  30321 + _cimg_watershed_init(is_nx && is_py,nx,py,z);
  30322 + _cimg_watershed_init(is_px && is_ny,px,ny,z);
  30323 + _cimg_watershed_init(is_nx && is_ny,nx,ny,z);
  30324 + if (is_3d) {
  30325 + _cimg_watershed_init(is_px && is_pz,px,y,pz);
  30326 + _cimg_watershed_init(is_nx && is_pz,nx,y,pz);
  30327 + _cimg_watershed_init(is_px && is_nz,px,y,nz);
  30328 + _cimg_watershed_init(is_nx && is_nz,nx,y,nz);
  30329 + _cimg_watershed_init(is_py && is_pz,x,py,pz);
  30330 + _cimg_watershed_init(is_ny && is_pz,x,ny,pz);
  30331 + _cimg_watershed_init(is_py && is_nz,x,py,nz);
  30332 + _cimg_watershed_init(is_ny && is_nz,x,ny,nz);
  30333 + _cimg_watershed_init(is_px && is_py && is_pz,px,py,pz);
  30334 + _cimg_watershed_init(is_nx && is_py && is_pz,nx,py,pz);
  30335 + _cimg_watershed_init(is_px && is_ny && is_pz,px,ny,pz);
  30336 + _cimg_watershed_init(is_nx && is_ny && is_pz,nx,ny,pz);
  30337 + _cimg_watershed_init(is_px && is_py && is_nz,px,py,nz);
  30338 + _cimg_watershed_init(is_nx && is_py && is_nz,nx,py,nz);
  30339 + _cimg_watershed_init(is_px && is_ny && is_nz,px,ny,nz);
  30340 + _cimg_watershed_init(is_nx && is_ny && is_nz,nx,ny,nz);
  30341 + }
  30342 + }
  30343 + labels(x,y,z) = nb_seeds;
29564 } 30344 }
29565 30345
29566 // Start watershed computation. 30346 // Start watershed computation.
@@ -29568,145 +30348,113 @@ namespace cimg_library_suffixed { @@ -29568,145 +30348,113 @@ namespace cimg_library_suffixed {
29568 30348
29569 // Get and remove point with maximal priority from the queue. 30349 // Get and remove point with maximal priority from the queue.
29570 const int x = (int)Q(0,1), y = (int)Q(0,2), z = (int)Q(0,3); 30350 const int x = (int)Q(0,1), y = (int)Q(0,2), z = (int)Q(0,3);
29571 - Q._priority_queue_remove(sizeQ); 30351 + const unsigned int n = labels(x,y,z);
  30352 + px = x - 1; nx = x + 1;
  30353 + py = y - 1; ny = y + 1;
  30354 + pz = z - 1; nz = z + 1;
  30355 + is_px = px>=0; is_nx = nx<width();
  30356 + is_py = py>=0; is_ny = ny<height();
  30357 + is_pz = pz>=0; is_nz = nz<depth();
29572 30358
29573 // Check labels of the neighbors. 30359 // Check labels of the neighbors.
29574 - bool is_same_label = true;  
29575 - T label = 0;  
29576 - if (x - 1>=0) {  
29577 - if ((*this)(x - 1,y,z)) {  
29578 - if (!label) label = (*this)(x - 1,y,z);  
29579 - else if (label!=(*this)(x - 1,y,z)) is_same_label = false;  
29580 - } else Q._priority_queue_insert(is_queued,sizeQ,priority(x - 1,y,z),x - 1,y,z);  
29581 - }  
29582 - if (x + 1<width()) {  
29583 - if ((*this)(x + 1,y,z)) {  
29584 - if (!label) label = (*this)(x + 1,y,z);  
29585 - else if (label!=(*this)(x + 1,y,z)) is_same_label = false;  
29586 - } else Q._priority_queue_insert(is_queued,sizeQ,priority(x + 1,y,z),x + 1,y,z);  
29587 - }  
29588 - if (y - 1>=0) {  
29589 - if ((*this)(x,y - 1,z)) {  
29590 - if (!label) label = (*this)(x,y - 1,z);  
29591 - else if (label!=(*this)(x,y - 1,z)) is_same_label = false;  
29592 - } else Q._priority_queue_insert(is_queued,sizeQ,priority(x,y - 1,z),x,y - 1,z);  
29593 - }  
29594 - if (y + 1<height()) {  
29595 - if ((*this)(x,y + 1,z)) {  
29596 - if (!label) label = (*this)(x,y + 1,z);  
29597 - else if (label!=(*this)(x,y + 1,z)) is_same_label = false;  
29598 - } else Q._priority_queue_insert(is_queued,sizeQ,priority(x,y + 1,z),x,y + 1,z);  
29599 - }  
29600 - if (z - 1>=0) {  
29601 - if ((*this)(x,y,z - 1)) {  
29602 - if (!label) label = (*this)(x,y,z - 1);  
29603 - else if (label!=(*this)(x,y,z - 1)) is_same_label = false;  
29604 - } else Q._priority_queue_insert(is_queued,sizeQ,priority(x,y,z - 1),x,y,z - 1);  
29605 - }  
29606 - if (z + 1<depth()) {  
29607 - if ((*this)(x,y,z + 1)) {  
29608 - if (!label) label = (*this)(x,y,z + 1);  
29609 - else if (label!=(*this)(x,y,z + 1)) is_same_label = false;  
29610 - } else Q._priority_queue_insert(is_queued,sizeQ,priority(x,y,z + 1),x,y,z + 1);  
29611 - }  
29612 - if (is_same_label) (*this)(x,y,z) = label;  
29613 - }  
29614 -  
29615 - // Fill lines.  
29616 - if (fill_lines) {  
29617 -  
29618 - // Sort all non-labeled pixels with labeled neighbors.  
29619 - is_queued = false;  
29620 - const T *ptrs = _data;  
29621 - cimg_forXYZ(*this,x,y,z) if (!*(ptrs++) &&  
29622 - ((x - 1>=0 && (*this)(x - 1,y,z)) || (x + 1<width() && (*this)(x + 1,y,z)) ||  
29623 - (y - 1>=0 && (*this)(x,y - 1,z)) || (y + 1<height() && (*this)(x,y + 1,z)) ||  
29624 - (z - 1>=0 && (*this)(x,y,z - 1)) || (z + 1>depth() && (*this)(x,y,z + 1))))  
29625 - Q._priority_queue_insert(is_queued,sizeQ,priority(x,y,z),x,y,z); 30360 + Q._priority_queue_remove(sizeQ);
29626 30361
29627 - // Start line filling process.  
29628 - while (sizeQ) {  
29629 - const int x = (int)Q(0,1), y = (int)Q(0,2), z = (int)Q(0,3);  
29630 - Q._priority_queue_remove(sizeQ);  
29631 - t pmax = cimg::type<t>::min();  
29632 - int xmax = 0, ymax = 0, zmax = 0;  
29633 - if (x - 1>=0) {  
29634 - if ((*this)(x - 1,y,z)) {  
29635 - if (priority(x - 1,y,z)>pmax) { pmax = priority(x - 1,y,z); xmax = x - 1; ymax = y; zmax = z; }  
29636 - } else Q._priority_queue_insert(is_queued,sizeQ,priority(x - 1,y,z),x - 1,y,z);  
29637 - }  
29638 - if (x + 1<width()) {  
29639 - if ((*this)(x + 1,y,z)) {  
29640 - if (priority(x + 1,y,z)>pmax) { pmax = priority(x + 1,y,z); xmax = x + 1; ymax = y; zmax = z; }  
29641 - } else Q._priority_queue_insert(is_queued,sizeQ,priority(x + 1,y,z),x + 1,y,z);  
29642 - }  
29643 - if (y - 1>=0) {  
29644 - if ((*this)(x,y - 1,z)) {  
29645 - if (priority(x,y - 1,z)>pmax) { pmax = priority(x,y - 1,z); xmax = x; ymax = y - 1; zmax = z; }  
29646 - } else Q._priority_queue_insert(is_queued,sizeQ,priority(x,y - 1,z),x,y - 1,z);  
29647 - }  
29648 - if (y + 1<height()) {  
29649 - if ((*this)(x,y + 1,z)) {  
29650 - if (priority(x,y + 1,z)>pmax) { pmax = priority(x,y + 1,z); xmax = x; ymax = y + 1; zmax = z; }  
29651 - } else Q._priority_queue_insert(is_queued,sizeQ,priority(x,y + 1,z),x,y + 1,z);  
29652 - }  
29653 - if (z - 1>=0) {  
29654 - if ((*this)(x,y,z - 1)) {  
29655 - if (priority(x,y,z - 1)>pmax) { pmax = priority(x,y,z - 1); xmax = x; ymax = y; zmax = z - 1; }  
29656 - } else Q._priority_queue_insert(is_queued,sizeQ,priority(x,y,z - 1),x,y,z - 1);  
29657 - }  
29658 - if (z + 1<depth()) {  
29659 - if ((*this)(x,y,z + 1)) {  
29660 - if (priority(x,y,z + 1)>pmax) { pmax = priority(x,y,z + 1); xmax = x; ymax = y; zmax = z + 1; }  
29661 - } else Q._priority_queue_insert(is_queued,sizeQ,priority(x,y,z + 1),x,y,z + 1);  
29662 - }  
29663 - (*this)(x,y,z) = (*this)(xmax,ymax,zmax); 30362 + unsigned int xs, ys, zs, ns, nmin = 0;
  30363 + float d, dmin = cimg::type<float>::inf();
  30364 + T label = 0;
  30365 + _cimg_watershed_propagate(is_px,px,y,z);
  30366 + _cimg_watershed_propagate(is_nx,nx,y,z);
  30367 + _cimg_watershed_propagate(is_py,x,py,z);
  30368 + _cimg_watershed_propagate(is_ny,x,ny,z);
  30369 + if (is_3d) {
  30370 + _cimg_watershed_propagate(is_pz,x,y,pz);
  30371 + _cimg_watershed_propagate(is_nz,x,y,nz);
29664 } 30372 }
  30373 + if (is_high_connectivity) {
  30374 + _cimg_watershed_propagate(is_px && is_py,px,py,z);
  30375 + _cimg_watershed_propagate(is_nx && is_py,nx,py,z);
  30376 + _cimg_watershed_propagate(is_px && is_ny,px,ny,z);
  30377 + _cimg_watershed_propagate(is_nx && is_ny,nx,ny,z);
  30378 + if (is_3d) {
  30379 + _cimg_watershed_propagate(is_px && is_pz,px,y,pz);
  30380 + _cimg_watershed_propagate(is_nx && is_pz,nx,y,pz);
  30381 + _cimg_watershed_propagate(is_px && is_nz,px,y,nz);
  30382 + _cimg_watershed_propagate(is_nx && is_nz,nx,y,nz);
  30383 + _cimg_watershed_propagate(is_py && is_pz,x,py,pz);
  30384 + _cimg_watershed_propagate(is_ny && is_pz,x,ny,pz);
  30385 + _cimg_watershed_propagate(is_py && is_nz,x,py,nz);
  30386 + _cimg_watershed_propagate(is_ny && is_nz,x,ny,nz);
  30387 + _cimg_watershed_propagate(is_px && is_py && is_pz,px,py,pz);
  30388 + _cimg_watershed_propagate(is_nx && is_py && is_pz,nx,py,pz);
  30389 + _cimg_watershed_propagate(is_px && is_ny && is_pz,px,ny,pz);
  30390 + _cimg_watershed_propagate(is_nx && is_ny && is_pz,nx,ny,pz);
  30391 + _cimg_watershed_propagate(is_px && is_py && is_nz,px,py,nz);
  30392 + _cimg_watershed_propagate(is_nx && is_py && is_nz,nx,py,nz);
  30393 + _cimg_watershed_propagate(is_px && is_ny && is_nz,px,ny,nz);
  30394 + _cimg_watershed_propagate(is_nx && is_ny && is_nz,nx,ny,nz);
  30395 + }
  30396 + }
  30397 + (*this)(x,y,z) = label;
  30398 + labels(x,y,z) = ++nmin;
29665 } 30399 }
29666 return *this; 30400 return *this;
29667 } 30401 }
29668 30402
29669 //! Compute watershed transform \newinstance. 30403 //! Compute watershed transform \newinstance.
29670 template<typename t> 30404 template<typename t>
29671 - CImg<T> get_watershed(const CImg<t>& priority, const bool fill_lines=true) const {  
29672 - return (+*this).watershed(priority,fill_lines); 30405 + CImg<T> get_watershed(const CImg<t>& priority, const bool is_high_connectivity=false) const {
  30406 + return (+*this).watershed(priority,is_high_connectivity);
29673 } 30407 }
29674 30408
29675 // [internal] Insert/Remove items in priority queue, for watershed/distance transforms. 30409 // [internal] Insert/Remove items in priority queue, for watershed/distance transforms.
29676 - template<typename t>  
29677 - bool _priority_queue_insert(CImg<boolT>& is_queued, unsigned int& siz, const t value,  
29678 - const unsigned int x, const unsigned int y, const unsigned int z) { 30410 + template<typename tq, typename tv>
  30411 + bool _priority_queue_insert(CImg<tq>& is_queued, unsigned int& siz, const tv value,
  30412 + const unsigned int x, const unsigned int y, const unsigned int z,
  30413 + const unsigned int n=1) {
29679 if (is_queued(x,y,z)) return false; 30414 if (is_queued(x,y,z)) return false;
29680 - is_queued(x,y,z) = true; 30415 + is_queued(x,y,z) = (tq)n;
29681 if (++siz>=_width) { if (!is_empty()) resize(_width*2,4,1,1,0); else assign(64,4); } 30416 if (++siz>=_width) { if (!is_empty()) resize(_width*2,4,1,1,0); else assign(64,4); }
29682 - (*this)(siz - 1,0) = (T)value; (*this)(siz - 1,1) = (T)x; (*this)(siz - 1,2) = (T)y; (*this)(siz - 1,3) = (T)z; 30417 + (*this)(siz - 1,0) = (T)value;
  30418 + (*this)(siz - 1,1) = (T)x;
  30419 + (*this)(siz - 1,2) = (T)y;
  30420 + (*this)(siz - 1,3) = (T)z;
29683 for (unsigned int pos = siz - 1, par = 0; pos && value>(*this)(par=(pos + 1)/2 - 1,0); pos = par) { 30421 for (unsigned int pos = siz - 1, par = 0; pos && value>(*this)(par=(pos + 1)/2 - 1,0); pos = par) {
29684 - cimg::swap((*this)(pos,0),(*this)(par,0)); cimg::swap((*this)(pos,1),(*this)(par,1));  
29685 - cimg::swap((*this)(pos,2),(*this)(par,2)); cimg::swap((*this)(pos,3),(*this)(par,3)); 30422 + cimg::swap((*this)(pos,0),(*this)(par,0));
  30423 + cimg::swap((*this)(pos,1),(*this)(par,1));
  30424 + cimg::swap((*this)(pos,2),(*this)(par,2));
  30425 + cimg::swap((*this)(pos,3),(*this)(par,3));
29686 } 30426 }
29687 return true; 30427 return true;
29688 } 30428 }
29689 30429
29690 CImg<T>& _priority_queue_remove(unsigned int& siz) { 30430 CImg<T>& _priority_queue_remove(unsigned int& siz) {
29691 - (*this)(0,0) = (*this)(--siz,0); (*this)(0,1) = (*this)(siz,1);  
29692 - (*this)(0,2) = (*this)(siz,2); (*this)(0,3) = (*this)(siz,3); 30431 + (*this)(0,0) = (*this)(--siz,0);
  30432 + (*this)(0,1) = (*this)(siz,1);
  30433 + (*this)(0,2) = (*this)(siz,2);
  30434 + (*this)(0,3) = (*this)(siz,3);
29693 const float value = (*this)(0,0); 30435 const float value = (*this)(0,0);
29694 for (unsigned int pos = 0, left = 0, right = 0; 30436 for (unsigned int pos = 0, left = 0, right = 0;
29695 ((right=2*(pos + 1),(left=right - 1))<siz && value<(*this)(left,0)) || 30437 ((right=2*(pos + 1),(left=right - 1))<siz && value<(*this)(left,0)) ||
29696 (right<siz && value<(*this)(right,0));) { 30438 (right<siz && value<(*this)(right,0));) {
29697 if (right<siz) { 30439 if (right<siz) {
29698 if ((*this)(left,0)>(*this)(right,0)) { 30440 if ((*this)(left,0)>(*this)(right,0)) {
29699 - cimg::swap((*this)(pos,0),(*this)(left,0)); cimg::swap((*this)(pos,1),(*this)(left,1));  
29700 - cimg::swap((*this)(pos,2),(*this)(left,2)); cimg::swap((*this)(pos,3),(*this)(left,3)); 30441 + cimg::swap((*this)(pos,0),(*this)(left,0));
  30442 + cimg::swap((*this)(pos,1),(*this)(left,1));
  30443 + cimg::swap((*this)(pos,2),(*this)(left,2));
  30444 + cimg::swap((*this)(pos,3),(*this)(left,3));
29701 pos = left; 30445 pos = left;
29702 } else { 30446 } else {
29703 - cimg::swap((*this)(pos,0),(*this)(right,0)); cimg::swap((*this)(pos,1),(*this)(right,1));  
29704 - cimg::swap((*this)(pos,2),(*this)(right,2)); cimg::swap((*this)(pos,3),(*this)(right,3)); 30447 + cimg::swap((*this)(pos,0),(*this)(right,0));
  30448 + cimg::swap((*this)(pos,1),(*this)(right,1));
  30449 + cimg::swap((*this)(pos,2),(*this)(right,2));
  30450 + cimg::swap((*this)(pos,3),(*this)(right,3));
29705 pos = right; 30451 pos = right;
29706 } 30452 }
29707 } else { 30453 } else {
29708 - cimg::swap((*this)(pos,0),(*this)(left,0)); cimg::swap((*this)(pos,1),(*this)(left,1));  
29709 - cimg::swap((*this)(pos,2),(*this)(left,2)); cimg::swap((*this)(pos,3),(*this)(left,3)); 30454 + cimg::swap((*this)(pos,0),(*this)(left,0));
  30455 + cimg::swap((*this)(pos,1),(*this)(left,1));
  30456 + cimg::swap((*this)(pos,2),(*this)(left,2));
  30457 + cimg::swap((*this)(pos,3),(*this)(left,3));
29710 pos = left; 30458 pos = left;
29711 } 30459 }
29712 } 30460 }
@@ -39484,11 +40232,11 @@ namespace cimg_library_suffixed { @@ -39484,11 +40232,11 @@ namespace cimg_library_suffixed {
39484 lZ = sprite.depth() - (z0 + sprite.depth()>depth()?z0 + sprite.depth() - depth():0) + (bz?z0:0), 40232 lZ = sprite.depth() - (z0 + sprite.depth()>depth()?z0 + sprite.depth() - depth():0) + (bz?z0:0),
39485 lC = sprite.spectrum() - (c0 + sprite.spectrum()>spectrum()?c0 + sprite.spectrum() - spectrum():0) + (bc?c0:0); 40233 lC = sprite.spectrum() - (c0 + sprite.spectrum()>spectrum()?c0 + sprite.spectrum() - spectrum():0) + (bc?c0:0);
39486 const t 40234 const t
39487 - *ptrs = sprite._data -  
39488 - (bx?x0:0) -  
39489 - (by?y0*(uptrT)sprite.width():0) -  
39490 - (bz?z0*(uptrT)sprite.width()*sprite.height():0) -  
39491 - (bc?c0*(uptrT)sprite.width()*sprite.height()*sprite.depth():0); 40235 + *ptrs = sprite._data +
  40236 + (bx?-x0:0) +
  40237 + (by?-y0*(uptrT)sprite.width():0) +
  40238 + (bz?-z0*(uptrT)sprite.width()*sprite.height():0) +
  40239 + (bc?-c0*(uptrT)sprite.width()*sprite.height()*sprite.depth():0);
39492 const uptrT 40240 const uptrT
39493 offX = (unsigned long)_width - lX, 40241 offX = (unsigned long)_width - lX,
39494 soffX = (unsigned long)sprite._width - lX, 40242 soffX = (unsigned long)sprite._width - lX,
@@ -39528,11 +40276,11 @@ namespace cimg_library_suffixed { @@ -39528,11 +40276,11 @@ namespace cimg_library_suffixed {
39528 lZ = sprite.depth() - (z0 + sprite.depth()>depth()?z0 + sprite.depth() - depth():0) + (bz?z0:0), 40276 lZ = sprite.depth() - (z0 + sprite.depth()>depth()?z0 + sprite.depth() - depth():0) + (bz?z0:0),
39529 lC = sprite.spectrum() - (c0 + sprite.spectrum()>spectrum()?c0 + sprite.spectrum() - spectrum():0) + (bc?c0:0); 40277 lC = sprite.spectrum() - (c0 + sprite.spectrum()>spectrum()?c0 + sprite.spectrum() - spectrum():0) + (bc?c0:0);
39530 const T 40278 const T
39531 - *ptrs = sprite._data -  
39532 - (bx?x0:0) -  
39533 - (by?y0*(uptrT)sprite.width():0) -  
39534 - (bz?z0*(uptrT)sprite.width()*sprite.height():0) -  
39535 - (bc?c0*(uptrT)sprite.width()*sprite.height()*sprite.depth():0); 40279 + *ptrs = sprite._data +
  40280 + (bx?-x0:0) +
  40281 + (by?-y0*(uptrT)sprite.width():0) +
  40282 + (bz?-z0*(uptrT)sprite.width()*sprite.height():0) +
  40283 + (bc?-c0*(uptrT)sprite.width()*sprite.height()*sprite.depth():0);
39536 const unsigned long 40284 const unsigned long
39537 offX = (unsigned long)_width - lX, 40285 offX = (unsigned long)_width - lX,
39538 soffX = (unsigned long)sprite._width - lX, 40286 soffX = (unsigned long)sprite._width - lX,
@@ -39623,10 +40371,10 @@ namespace cimg_library_suffixed { @@ -39623,10 +40371,10 @@ namespace cimg_library_suffixed {
39623 lZ = sprite.depth() - (z0 + sprite.depth()>depth()?z0 + sprite.depth() - depth():0) + (bz?z0:0), 40371 lZ = sprite.depth() - (z0 + sprite.depth()>depth()?z0 + sprite.depth() - depth():0) + (bz?z0:0),
39624 lC = sprite.spectrum() - (c0 + sprite.spectrum()>spectrum()?c0 + sprite.spectrum() - spectrum():0) + (bc?c0:0); 40372 lC = sprite.spectrum() - (c0 + sprite.spectrum()>spectrum()?c0 + sprite.spectrum() - spectrum():0) + (bc?c0:0);
39625 const uptrT 40373 const uptrT
39626 - coff = -(bx?x0:0) -  
39627 - (by?y0*(uptrT)mask.width():0) -  
39628 - (bz?z0*(uptrT)mask.width()*mask.height():0) -  
39629 - (bc?c0*(uptrT)mask.width()*mask.height()*mask.depth():0), 40374 + coff = (bx?-x0:0) +
  40375 + (by?-y0*(uptrT)mask.width():0) +
  40376 + (bz?-z0*(uptrT)mask.width()*mask.height():0) +
  40377 + (bc?-c0*(uptrT)mask.width()*mask.height()*mask.depth():0),
39630 ssize = (uptrT)mask.width()*mask.height()*mask.depth()*mask.spectrum(); 40378 ssize = (uptrT)mask.width()*mask.height()*mask.depth()*mask.spectrum();
39631 const ti *ptrs = sprite._data + coff; 40379 const ti *ptrs = sprite._data + coff;
39632 const tm *ptrm = mask._data + coff; 40380 const tm *ptrm = mask._data + coff;
@@ -43423,7 +44171,7 @@ namespace cimg_library_suffixed { @@ -43423,7 +44171,7 @@ namespace cimg_library_suffixed {
43423 unsigned int cdx = 0, dx = 0, dy = 0; 44171 unsigned int cdx = 0, dx = 0, dy = 0;
43424 int err = 0; 44172 int err = 0;
43425 double val; 44173 double val;
43426 - assign(256,256); 44174 + assign(256,256,1,1,0);
43427 while ((err = std::fscanf(nfile,"%lf%255[^0-9eEinfa.+-]",&val,delimiter._data))>0) { 44175 while ((err = std::fscanf(nfile,"%lf%255[^0-9eEinfa.+-]",&val,delimiter._data))>0) {
43428 if (err>0) (*this)(cdx++,dy) = (T)val; 44176 if (err>0) (*this)(cdx++,dy) = (T)val;
43429 if (cdx>=_width) resize(3*_width/2,_height,1,1,0); 44177 if (cdx>=_width) resize(3*_width/2,_height,1,1,0);
@@ -48536,7 +49284,7 @@ namespace cimg_library_suffixed { @@ -48536,7 +49284,7 @@ namespace cimg_library_suffixed {
48536 **/ 49284 **/
48537 const CImg<T>& save_tiff(const char *const filename, const unsigned int compression_type=0, 49285 const CImg<T>& save_tiff(const char *const filename, const unsigned int compression_type=0,
48538 const float *const voxel_size=0, const char *const description=0, 49286 const float *const voxel_size=0, const char *const description=0,
48539 - const bool is_bigtiff=true) const { 49287 + const bool use_bigtiff=true) const {
48540 if (!filename) 49288 if (!filename)
48541 throw CImgArgumentException(_cimg_instance 49289 throw CImgArgumentException(_cimg_instance
48542 "save_tiff(): Specified filename is (null).", 49290 "save_tiff(): Specified filename is (null).",
@@ -48544,7 +49292,9 @@ namespace cimg_library_suffixed { @@ -48544,7 +49292,9 @@ namespace cimg_library_suffixed {
48544 if (is_empty()) { cimg::fempty(0,filename); return *this; } 49292 if (is_empty()) { cimg::fempty(0,filename); return *this; }
48545 49293
48546 #ifdef cimg_use_tiff 49294 #ifdef cimg_use_tiff
48547 - TIFF *tif = TIFFOpen(filename,is_bigtiff?"w8":"w4"); 49295 + const bool
  49296 + _use_bigtiff = use_bigtiff && sizeof(uptrT)>=8 && size()*sizeof(T)>=1UL<<31; // No bigtiff for small images.
  49297 + TIFF *tif = TIFFOpen(filename,_use_bigtiff?"w8":"w4");
48548 if (tif) { 49298 if (tif) {
48549 cimg_forZ(*this,z) _save_tiff(tif,z,z,compression_type,voxel_size,description); 49299 cimg_forZ(*this,z) _save_tiff(tif,z,z,compression_type,voxel_size,description);
48550 TIFFClose(tif); 49300 TIFFClose(tif);
@@ -48554,7 +49304,7 @@ namespace cimg_library_suffixed { @@ -48554,7 +49304,7 @@ namespace cimg_library_suffixed {
48554 filename); 49304 filename);
48555 return *this; 49305 return *this;
48556 #else 49306 #else
48557 - cimg::unused(compression_type,voxel_size,description,is_bigtiff); 49307 + cimg::unused(compression_type,voxel_size,description,use_bigtiff);
48558 return save_other(filename); 49308 return save_other(filename);
48559 #endif 49309 #endif
48560 } 49310 }
@@ -49078,9 +49828,9 @@ namespace cimg_library_suffixed { @@ -49078,9 +49828,9 @@ namespace cimg_library_suffixed {
49078 if (is_empty()) { cimg::fempty(file,filename); return *this; } 49828 if (is_empty()) { cimg::fempty(file,filename); return *this; }
49079 49829
49080 std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); 49830 std::FILE *const nfile = file?file:cimg::fopen(filename,"wb");
49081 - static const unsigned char header[36] = { 'P','A','N','D','O','R','E','0','4',0,0,0,  
49082 - 0,0,0,0,'C','I','m','g',0,0,0,0,0,  
49083 - 'N','o',' ','d','a','t','e',0,0,0,0 }; 49831 + unsigned char header[36] = { 'P','A','N','D','O','R','E','0','4',0,0,0,
  49832 + 0,0,0,0,'C','I','m','g',0,0,0,0,0,
  49833 + 'N','o',' ','d','a','t','e',0,0,0,0 };
49084 unsigned int nbdims, dims[5] = { 0 }; 49834 unsigned int nbdims, dims[5] = { 0 };
49085 bool saved = false; 49835 bool saved = false;
49086 _cimg_save_pandore_case(1,1,1,"unsigned char",2); 49836 _cimg_save_pandore_case(1,1,1,"unsigned char",2);
@@ -52584,7 +53334,7 @@ namespace cimg_library_suffixed { @@ -52584,7 +53334,7 @@ namespace cimg_library_suffixed {
52584 *tmp = *str_pixeltype = *str_endian = 0; 53334 *tmp = *str_pixeltype = *str_endian = 0;
52585 unsigned int j, N, W, H, D, C; 53335 unsigned int j, N, W, H, D, C;
52586 int i, err; 53336 int i, err;
52587 - j = 0; while((i=std::fgetc(nfile))!='\n' && i!=EOF && j<256) tmp[j++] = (char)i; tmp[j] = 0; 53337 + j = 0; while ((i=std::fgetc(nfile))!='\n' && i!=EOF && j<256) tmp[j++] = (char)i; tmp[j] = 0;
52588 err = cimg_sscanf(tmp,"%u%*c%255[A-Za-z_]%*c%255[sA-Za-z_ ]", 53338 err = cimg_sscanf(tmp,"%u%*c%255[A-Za-z_]%*c%255[sA-Za-z_ ]",
52589 &N,str_pixeltype._data,str_endian._data); 53339 &N,str_pixeltype._data,str_endian._data);
52590 if (err<2) { 53340 if (err<2) {
@@ -53773,7 +54523,7 @@ namespace cimg_library_suffixed { @@ -53773,7 +54523,7 @@ namespace cimg_library_suffixed {
53773 #define _cimg_save_cimg_case(Ts,Tss) \ 54523 #define _cimg_save_cimg_case(Ts,Tss) \
53774 if (!saved && !cimg::strcasecmp(Ts,str_pixeltype)) { \ 54524 if (!saved && !cimg::strcasecmp(Ts,str_pixeltype)) { \
53775 for (unsigned int l = 0; l<lmax; ++l) { \ 54525 for (unsigned int l = 0; l<lmax; ++l) { \
53776 - j = 0; while((i=std::fgetc(nfile))!='\n') tmp[j++]=(char)i; tmp[j] = 0; \ 54526 + j = 0; while ((i=std::fgetc(nfile))!='\n') tmp[j++]=(char)i; tmp[j] = 0; \
53777 W = H = D = C = 0; \ 54527 W = H = D = C = 0; \
53778 if (cimg_sscanf(tmp,"%u %u %u %u",&W,&H,&D,&C)!=4) \ 54528 if (cimg_sscanf(tmp,"%u %u %u %u",&W,&H,&D,&C)!=4) \
53779 throw CImgIOException(_cimglist_instance \ 54529 throw CImgIOException(_cimglist_instance \
@@ -53843,7 +54593,7 @@ namespace cimg_library_suffixed { @@ -53843,7 +54593,7 @@ namespace cimg_library_suffixed {
53843 *tmp = *str_pixeltype = *str_endian = 0; 54593 *tmp = *str_pixeltype = *str_endian = 0;
53844 unsigned int j, N, W, H, D, C; 54594 unsigned int j, N, W, H, D, C;
53845 int i, err; 54595 int i, err;
53846 - j = 0; while((i=std::fgetc(nfile))!='\n' && i!=EOF && j<256) tmp[j++] = (char)i; tmp[j] = 0; 54596 + j = 0; while ((i=std::fgetc(nfile))!='\n' && i!=EOF && j<256) tmp[j++] = (char)i; tmp[j] = 0;
53847 err = cimg_sscanf(tmp,"%u%*c%255[A-Za-z_]%*c%255[sA-Za-z_ ]",&N,str_pixeltype._data,str_endian._data); 54597 err = cimg_sscanf(tmp,"%u%*c%255[A-Za-z_]%*c%255[sA-Za-z_ ]",&N,str_pixeltype._data,str_endian._data);
53848 if (err<2) { 54598 if (err<2) {
53849 if (!file) cimg::fclose(nfile); 54599 if (!file) cimg::fclose(nfile);
@@ -53966,7 +54716,7 @@ namespace cimg_library_suffixed { @@ -53966,7 +54716,7 @@ namespace cimg_library_suffixed {
53966 **/ 54716 **/
53967 const CImgList<T>& save_tiff(const char *const filename, const unsigned int compression_type=0, 54717 const CImgList<T>& save_tiff(const char *const filename, const unsigned int compression_type=0,
53968 const float *const voxel_size=0, const char *const description=0, 54718 const float *const voxel_size=0, const char *const description=0,
53969 - const bool is_bigtiff=true) const { 54719 + const bool use_bigtiff=true) const {
53970 if (!filename) 54720 if (!filename)
53971 throw CImgArgumentException(_cimglist_instance 54721 throw CImgArgumentException(_cimglist_instance
53972 "save_tiff(): Specified filename is (null).", 54722 "save_tiff(): Specified filename is (null).",
@@ -53974,14 +54724,17 @@ namespace cimg_library_suffixed { @@ -53974,14 +54724,17 @@ namespace cimg_library_suffixed {
53974 if (is_empty()) { cimg::fempty(0,filename); return *this; } 54724 if (is_empty()) { cimg::fempty(0,filename); return *this; }
53975 54725
53976 #ifndef cimg_use_tiff 54726 #ifndef cimg_use_tiff
53977 - if (_width==1) _data[0].save_tiff(filename,compression_type,voxel_size,description,is_bigtiff); 54727 + if (_width==1) _data[0].save_tiff(filename,compression_type,voxel_size,description,use_bigtiff);
53978 else cimglist_for(*this,l) { 54728 else cimglist_for(*this,l) {
53979 CImg<charT> nfilename(1024); 54729 CImg<charT> nfilename(1024);
53980 cimg::number_filename(filename,l,6,nfilename); 54730 cimg::number_filename(filename,l,6,nfilename);
53981 - _data[l].save_tiff(nfilename,compression_type,voxel_size,description,is_bigtiff); 54731 + _data[l].save_tiff(nfilename,compression_type,voxel_size,description,use_bigtiff);
53982 } 54732 }
53983 #else 54733 #else
53984 - TIFF *tif = TIFFOpen(filename,is_bigtiff?"w8":"w4"); 54734 + typename CImg<T>::uptrT siz = 0;
  54735 + cimglist_for(*this,l) siz+=_data[l].size();
  54736 + const bool _use_bigtiff = use_bigtiff && sizeof(siz)>=8 && siz*sizeof(T)>=1UL<<31; // No bigtiff for small images.
  54737 + TIFF *tif = TIFFOpen(filename,_use_bigtiff?"w8":"w4");
53985 if (tif) { 54738 if (tif) {
53986 for (unsigned int dir = 0, l = 0; l<_width; ++l) { 54739 for (unsigned int dir = 0, l = 0; l<_width; ++l) {
53987 const CImg<T>& img = (*this)[l]; 54740 const CImg<T>& img = (*this)[l];
stim/image/image.h
@@ -35,7 +35,7 @@ public: @@ -35,7 +35,7 @@ public:
35 img = cimg_library::CImg<T>(x, y, z); 35 img = cimg_library::CImg<T>(x, y, z);
36 }*/ 36 }*/
37 37
38 - image(unsigned int x, unsigned int y = 1, unsigned int z = 1, unsigned int c = 1){ 38 + image(size_t x, size_t y = 1, size_t z = 1, size_t c = 1){
39 img = cimg_library::CImg<T>(x, y, z, c); 39 img = cimg_library::CImg<T>(x, y, z, c);
40 } 40 }
41 41
@@ -50,13 +50,13 @@ public: @@ -50,13 +50,13 @@ public:
50 } 50 }
51 51
52 //create an image from an interleaved buffer 52 //create an image from an interleaved buffer
53 - void set_interleaved(T* buffer, unsigned int width, unsigned int height, unsigned int channels = 1){ 53 + void set_interleaved(T* buffer, size_t width, size_t height, size_t channels = 1){
54 54
55 T* non_interleaved = (T*)malloc(width * height * 3 * sizeof(T)); 55 T* non_interleaved = (T*)malloc(width * height * 3 * sizeof(T));
56 - unsigned int S = width * height; 56 + size_t S = width * height;
57 57
58 - for(unsigned int i = 0; i < S; i++){  
59 - for(unsigned int c = 0; c < channels; c++){ 58 + for(size_t i = 0; i < S; i++){
  59 + for(size_t c = 0; c < channels; c++){
60 non_interleaved[i + c * S] = buffer[i * channels + c]; 60 non_interleaved[i + c * S] = buffer[i * channels + c];
61 } 61 }
62 } 62 }
@@ -71,19 +71,19 @@ public: @@ -71,19 +71,19 @@ public:
71 71
72 void data_interleaved(T* data){ 72 void data_interleaved(T* data){
73 73
74 - unsigned int C = channels();  
75 - unsigned int X = width() * height(); 74 + size_t C = channels();
  75 + size_t X = width() * height();
76 76
77 T* ptr = img.data(); 77 T* ptr = img.data();
78 78
79 //for each channel 79 //for each channel
80 - for(unsigned int c = 0; c < C; c++) 80 + for(size_t c = 0; c < C; c++)
81 //convert each pixel 81 //convert each pixel
82 - for(unsigned int x = 0; x < X; x++) 82 + for(size_t x = 0; x < X; x++)
83 data[x * C + c] = ptr[c * X + x]; 83 data[x * C + c] = ptr[c * X + x];
84 } 84 }
85 85
86 - image<T> channel(unsigned int c){ 86 + image<T> channel(size_t c){
87 87
88 //create a new image 88 //create a new image
89 image<T> single; 89 image<T> single;
@@ -94,7 +94,7 @@ public: @@ -94,7 +94,7 @@ public:
94 94
95 } 95 }
96 96
97 - T& operator()(unsigned x, unsigned y, unsigned z = 0, unsigned c = 0){ 97 + T& operator()(size_t x, size_t y, size_t z = 0, size_t c = 0){
98 return img(x, y, z, c); 98 return img(x, y, z, c);
99 } 99 }
100 100
@@ -103,9 +103,9 @@ public: @@ -103,9 +103,9 @@ public:
103 /// @param v is the value used to set all values in the image 103 /// @param v is the value used to set all values in the image
104 image<T> operator=(T v){ 104 image<T> operator=(T v){
105 105
106 - unsigned int X = width() * height() * depth() * channels(); 106 + size_t X = width() * height() * depth() * channels();
107 107
108 - for(unsigned x = 0; x < X; x++) 108 + for(size_t x = 0; x < X; x++)
109 img.data()[x] = v; 109 img.data()[x] = v;
110 110
111 return *this; 111 return *this;
@@ -117,10 +117,10 @@ public: @@ -117,10 +117,10 @@ public:
117 /// @param c is the channel number that the data will be copied to 117 /// @param c is the channel number that the data will be copied to
118 /// @param buffer is a pointer to the image to be copied to channel c 118 /// @param buffer is a pointer to the image to be copied to channel c
119 119
120 - void set_channel(unsigned int c, T* buffer){ 120 + void set_channel(size_t c, T* buffer){
121 121
122 //calculate the number of pixels in a channel 122 //calculate the number of pixels in a channel
123 - unsigned int channel_size = width() * height(); 123 + size_t channel_size = width() * height();
124 124
125 //retreive a pointer to the raw image data 125 //retreive a pointer to the raw image data
126 T* ptr = img.data() + channel_size * c; 126 T* ptr = img.data() + channel_size * c;
@@ -129,7 +129,7 @@ public: @@ -129,7 +129,7 @@ public:
129 memcpy(ptr, buffer, sizeof(T) * channel_size); 129 memcpy(ptr, buffer, sizeof(T) * channel_size);
130 } 130 }
131 131
132 - image<T> getslice(unsigned int c){ 132 + image<T> getslice(size_t c){
133 133
134 //create a new image 134 //create a new image
135 image<T> slice; 135 image<T> slice;
@@ -140,19 +140,19 @@ public: @@ -140,19 +140,19 @@ public:
140 140
141 } 141 }
142 142
143 - unsigned int channels(){  
144 - return (unsigned int)img.spectrum(); 143 + size_t channels(){
  144 + return (size_t)img.spectrum();
145 } 145 }
146 146
147 - unsigned int width(){ 147 + size_t width(){
148 return img.width(); 148 return img.width();
149 } 149 }
150 150
151 - unsigned int height(){ 151 + size_t height(){
152 return img.height(); 152 return img.height();
153 } 153 }
154 154
155 - unsigned int depth(){ 155 + size_t depth(){
156 return img.depth(); 156 return img.depth();
157 } 157 }
158 158
@@ -162,22 +162,22 @@ public: @@ -162,22 +162,22 @@ public:
162 } 162 }
163 163
164 //returns the size (number of values) of the image 164 //returns the size (number of values) of the image
165 - unsigned long size(){ 165 + size_t size(){
166 return img.size(); 166 return img.size();
167 } 167 }
168 168
169 /// Returns the number of nonzero values 169 /// Returns the number of nonzero values
170 - unsigned int nnz(){ 170 + size_t nnz(){
171 171
172 - unsigned long P = width() * height();  
173 - unsigned long C = channels(); 172 + size_t P = width() * height();
  173 + size_t C = channels();
174 174
175 T* ptr = img.data(); 175 T* ptr = img.data();
176 176
177 - unsigned long n = 0; 177 + size_t n = 0;
178 178
179 - for(unsigned long p = 0; p < P; p++){  
180 - for(unsigned long c = 0; c < C; c++){ 179 + for(size_t p = 0; p < P; p++){
  180 + for(size_t c = 0; c < C; c++){
181 181
182 if(ptr[c * P + p] > 0){ 182 if(ptr[c * P + p] > 0){
183 n++; 183 n++;
@@ -191,19 +191,19 @@ public: @@ -191,19 +191,19 @@ public:
191 } 191 }
192 192
193 //this function returns indices of pixels that have nonzero values 193 //this function returns indices of pixels that have nonzero values
194 - std::vector<unsigned long> sparse_idx(){ 194 + std::vector<size_t> sparse_idx(){
195 195
196 - std::vector<unsigned long> s; //allocate an array 196 + std::vector<size_t> s; //allocate an array
197 s.resize(nnz()); //allocate space in the array 197 s.resize(nnz()); //allocate space in the array
198 198
199 - unsigned long P = width() * height();  
200 - unsigned long C = channels(); 199 + size_t P = width() * height();
  200 + size_t C = channels();
201 201
202 T* ptr = img.data(); //get a pointer to the image data 202 T* ptr = img.data(); //get a pointer to the image data
203 203
204 - unsigned long i = 0;  
205 - for(unsigned long p = 0; p < P; p++){  
206 - for(unsigned long c = 0; c < C; c++){ 204 + size_t i = 0;
  205 + for(size_t p = 0; p < P; p++){
  206 + for(size_t c = 0; c < C; c++){
207 207
208 if(ptr[c * P + p] > 0){ 208 if(ptr[c * P + p] > 0){
209 s[i] = p; 209 s[i] = p;
@@ -220,9 +220,9 @@ public: @@ -220,9 +220,9 @@ public:
220 /// Returns the maximum pixel value in the image 220 /// Returns the maximum pixel value in the image
221 T maxv(){ 221 T maxv(){
222 float max = 0; 222 float max = 0;
223 - unsigned long N = width() * height(); //get the number of pixels 223 + size_t N = width() * height(); //get the number of pixels
224 224
225 - for (unsigned long i=0; i<N; i++){ 225 + for (size_t i=0; i<N; i++){
226 226
227 if (img.data()[i] > max) 227 if (img.data()[i] > max)
228 { 228 {
@@ -236,9 +236,9 @@ public: @@ -236,9 +236,9 @@ public:
236 /// Returns the minimum pixel value in the image 236 /// Returns the minimum pixel value in the image
237 T minv(){ 237 T minv(){
238 float min = 0; 238 float min = 0;
239 - unsigned long N = width() * height(); //get the number of pixels 239 + size_t N = width() * height(); //get the number of pixels
240 240
241 - for (unsigned long i=0; i<N; i++){ 241 + for (size_t i=0; i<N; i++){
242 242
243 if (img.data()[i] < min) 243 if (img.data()[i] < min)
244 { 244 {
@@ -276,8 +276,8 @@ public: @@ -276,8 +276,8 @@ public:
276 276
277 image<T> result; 277 image<T> result;
278 float zoom = 1; 278 float zoom = 1;
279 - unsigned int interpolation = 1;  
280 - unsigned int boundary = 1; 279 + size_t interpolation = 1;
  280 + size_t boundary = 1;
281 result.img = img.get_rotate (angle, cx, cy, zoom, interpolation, boundary); 281 result.img = img.get_rotate (angle, cx, cy, zoom, interpolation, boundary);
282 //result.save("data_output/test_rotate_neum.bmp"); 282 //result.save("data_output/test_rotate_neum.bmp");
283 283
@@ -286,13 +286,13 @@ public: @@ -286,13 +286,13 @@ public:
286 286
287 // leila's code for non_interleaving data in 3D 287 // leila's code for non_interleaving data in 3D
288 //create an data set from an interleaved buffer 288 //create an data set from an interleaved buffer
289 - void set_interleaved3(T* buffer, unsigned int width, unsigned int height, unsigned int depth, unsigned int channels = 3){ 289 + void set_interleaved3(T* buffer, size_t width, size_t height, size_t depth, size_t channels = 3){
290 290
291 T* non_interleaved3 = (T*)malloc(width * height * depth * 3 * sizeof(T)); 291 T* non_interleaved3 = (T*)malloc(width * height * depth * 3 * sizeof(T));
292 - unsigned int p = width * height * depth; 292 + size_t p = width * height * depth;
293 293
294 - for(unsigned int i = 0; i < p; i++){  
295 - for(unsigned int c = 0; c < channels; c++){ 294 + for(size_t i = 0; i < p; i++){
  295 + for(size_t c = 0; c < channels; c++){
296 non_interleaved3[i + c * p] = buffer[i * channels + c]; 296 non_interleaved3[i + c * p] = buffer[i * channels + c];
297 } 297 }
298 } 298 }
stim/parser/arguments.h
@@ -76,7 +76,7 @@ namespace stim{ @@ -76,7 +76,7 @@ namespace stim{
76 76
77 } 77 }
78 78
79 - int nargs() 79 + size_t nargs()
80 { 80 {
81 return vals.size(); 81 return vals.size();
82 } 82 }
@@ -135,9 +135,9 @@ namespace stim{ @@ -135,9 +135,9 @@ namespace stim{
135 } 135 }
136 136
137 //get the width of the left column 137 //get the width of the left column
138 - int col_width() 138 + size_t col_width()
139 { 139 {
140 - int n = 3; 140 + size_t n = 3;
141 //add the length of the option name 141 //add the length of the option name
142 n += name.size(); 142 n += name.size();
143 143
@@ -148,7 +148,7 @@ namespace stim{ @@ -148,7 +148,7 @@ namespace stim{
148 n += 6; 148 n += 6;
149 149
150 //for each default option value 150 //for each default option value
151 - for(unsigned int v=0; v<vals.size(); v++) 151 + for(size_t v=0; v<vals.size(); v++)
152 n += vals[v].size() + 1; 152 n += vals[v].size() + 1;
153 } 153 }
154 154
@@ -160,7 +160,7 @@ namespace stim{ @@ -160,7 +160,7 @@ namespace stim{
160 160
161 161
162 //string output 162 //string output
163 - std::string toStr(int width = 0) 163 + std::string toStr(size_t width = 0)
164 { 164 {
165 std::stringstream ss; 165 std::stringstream ss;
166 166
@@ -174,7 +174,7 @@ namespace stim{ @@ -174,7 +174,7 @@ namespace stim{
174 if(ansi) 174 if(ansi)
175 left_part += "\033[1;32m"; 175 left_part += "\033[1;32m";
176 left_part += " ( = "; 176 left_part += " ( = ";
177 - for(unsigned int v=0; v<vals.size(); v++) 177 + for(size_t v=0; v<vals.size(); v++)
178 left_part += vals[v] + std::string(" "); 178 left_part += vals[v] + std::string(" ");
179 left_part += ")"; 179 left_part += ")";
180 if(ansi) 180 if(ansi)
@@ -191,7 +191,7 @@ namespace stim{ @@ -191,7 +191,7 @@ namespace stim{
191 ss<<std::left<<std::setw(width + color_size)<<left_part; 191 ss<<std::left<<std::setw(width + color_size)<<left_part;
192 192
193 //output right column 193 //output right column
194 - for(unsigned int d=0; d<desc.size(); d++) 194 + for(size_t d=0; d<desc.size(); d++)
195 { 195 {
196 if(d == 0) 196 if(d == 0)
197 ss<<desc[0]; 197 ss<<desc[0];
@@ -234,7 +234,7 @@ namespace stim{ @@ -234,7 +234,7 @@ namespace stim{
234 struct argsection 234 struct argsection
235 { 235 {
236 std::string name; 236 std::string name;
237 - unsigned int index; 237 + size_t index;
238 }; 238 };
239 239
240 /**The arglist class implements command line arguments. 240 /**The arglist class implements command line arguments.
@@ -285,7 +285,7 @@ namespace stim{ @@ -285,7 +285,7 @@ namespace stim{
285 std::vector<std::string> args; 285 std::vector<std::string> args;
286 286
287 //column width of the longest option 287 //column width of the longest option
288 - int col_width; 288 + size_t col_width;
289 289
290 //list of sections 290 //list of sections
291 std::vector<argsection> sections; 291 std::vector<argsection> sections;
@@ -327,7 +327,7 @@ namespace stim{ @@ -327,7 +327,7 @@ namespace stim{
327 opt.set_ansi(ansi); 327 opt.set_ansi(ansi);
328 opts.push_back(opt); 328 opts.push_back(opt);
329 329
330 - col_width = std::max<int>(col_width, opt.col_width()); 330 + col_width = std::max<size_t>(col_width, opt.col_width());
331 } 331 }
332 332
333 ///Specifies a section name that can be used to organize parameters in the output. 333 ///Specifies a section name that can be used to organize parameters in the output.
@@ -373,32 +373,28 @@ namespace stim{ @@ -373,32 +373,28 @@ namespace stim{
373 ///Retrieves the index for a supported argument, given that argument's name. 373 ///Retrieves the index for a supported argument, given that argument's name.
374 374
375 /// @param _name is the name of the requested argument 375 /// @param _name is the name of the requested argument
376 - int index(std::string _name) 376 + size_t index(std::string _name)
377 { 377 {
378 - unsigned int i = find(opts.begin(), opts.end(), _name) - opts.begin(); 378 + size_t i = find(opts.begin(), opts.end(), _name) - opts.begin();
379 379
380 - if(i >= opts.size())  
381 - return -1; 380 + if(i >= opts.size()){
  381 + std::cout<<"ERROR stim::arglist: option name '"<<_name<<"' not found"<<std::endl;
  382 + exit(1);
  383 + }
382 384
383 - return (int)i; 385 + return i;
384 } 386 }
385 387
386 ///Sets an argument to a specified value 388 ///Sets an argument to a specified value
387 389
388 /// @param _name is the name of the argument to be set 390 /// @param _name is the name of the argument to be set
389 /// @param _value is the value that it is given 391 /// @param _value is the value that it is given
390 - void set(std::string _name, std::string _value)  
391 - {  
392 - int i = index(_name); 392 + void set(std::string _name, std::string _value){
  393 + size_t i = index(_name);
393 394
394 - if(i != -1)  
395 - {  
396 - opts[i].set(_value);  
397 - //adjust the column width if necessary  
398 - col_width = (std::max)(col_width, opts[i].col_width());  
399 - }  
400 - else  
401 - std::cout<<"ERROR - option not recognized: "<<_name<<std::endl; 395 + opts[i].set(_value);
  396 + //adjust the column width if necessary
  397 + col_width = (std::max)(col_width, opts[i].col_width());
402 } 398 }
403 399
404 ///Parses the command line 400 ///Parses the command line
@@ -449,10 +445,9 @@ namespace stim{ @@ -449,10 +445,9 @@ namespace stim{
449 /// @param _name is the name of the argument 445 /// @param _name is the name of the argument
450 bool operator()(std::string _name) 446 bool operator()(std::string _name)
451 { 447 {
452 - int i = find(opts.begin(), opts.end(), _name) - opts.begin(); 448 + size_t i = find(opts.begin(), opts.end(), _name) - opts.begin();
453 449
454 - if(i < 0)  
455 - { 450 + if(i < 0){
456 std::cout<<"ERROR - Unspecified parameter name: "<<_name<<std::endl; 451 std::cout<<"ERROR - Unspecified parameter name: "<<_name<<std::endl;
457 exit(1); 452 exit(1);
458 } 453 }
@@ -463,12 +458,11 @@ namespace stim{ @@ -463,12 +458,11 @@ namespace stim{
463 ///Returns the number of parameters for a specified argument 458 ///Returns the number of parameters for a specified argument
464 459
465 /// @param _name is the name of the argument whose parameter number will be returned 460 /// @param _name is the name of the argument whose parameter number will be returned
466 - unsigned int nargs(std::string _name) 461 + size_t nargs(std::string _name)
467 { 462 {
468 - int i = find(opts.begin(), opts.end(), _name) - opts.begin(); 463 + size_t i = find(opts.begin(), opts.end(), _name) - opts.begin();
469 464
470 - if(i < 0)  
471 - { 465 + if(i < 0){
472 std::cout<<"ERROR - Unspecified parameter name: "<<_name<<std::endl; 466 std::cout<<"ERROR - Unspecified parameter name: "<<_name<<std::endl;
473 exit(1); 467 exit(1);
474 } 468 }
@@ -477,14 +471,14 @@ namespace stim{ @@ -477,14 +471,14 @@ namespace stim{
477 } 471 }
478 472
479 ///Returns the number of arguments that have been set 473 ///Returns the number of arguments that have been set
480 - unsigned int nargs(){ 474 + size_t nargs(){
481 return args.size(); 475 return args.size();
482 } 476 }
483 477
484 /// Returns the number of options that are set 478 /// Returns the number of options that are set
485 - unsigned int nopts(){  
486 - unsigned int n = 0; //initialize the counter for the number of options  
487 - for(unsigned int i = 0; i < opts.size(); i++) //go through each option 479 + size_t nopts(){
  480 + size_t n = 0; //initialize the counter for the number of options
  481 + for(size_t i = 0; i < opts.size(); i++) //go through each option
488 if(opts[i].is_set()) n++; //if a value is specified, increment the counter 482 if(opts[i].is_set()) n++; //if a value is specified, increment the counter
489 return n; 483 return n;
490 } 484 }
@@ -492,7 +486,7 @@ namespace stim{ @@ -492,7 +486,7 @@ namespace stim{
492 ///Returns the name of an argument, given its index 486 ///Returns the name of an argument, given its index
493 487
494 /// @param a is the index of the requested argument 488 /// @param a is the index of the requested argument
495 - std::string arg(unsigned int a){ 489 + std::string arg(size_t a){
496 return args[a]; 490 return args[a];
497 } 491 }
498 492
@@ -501,7 +495,7 @@ namespace stim{ @@ -501,7 +495,7 @@ namespace stim{
501 /// @param _name is the name of the requested argument 495 /// @param _name is the name of the requested argument
502 cmd_option operator[](std::string _name) 496 cmd_option operator[](std::string _name)
503 { 497 {
504 - int i = find(opts.begin(), opts.end(), _name) - opts.begin(); 498 + size_t i = find(opts.begin(), opts.end(), _name) - opts.begin();
505 499
506 if(i < 0 || i >= opts.size()) 500 if(i < 0 || i >= opts.size())
507 { 501 {
stim/parser/filename.h
@@ -305,7 +305,7 @@ public: @@ -305,7 +305,7 @@ public:
305 return result; //return the result 305 return result; //return the result
306 } 306 }
307 307
308 - stim::filename insert(unsigned i, unsigned int n = 2){ 308 + stim::filename insert(size_t i, size_t n = 2){
309 309
310 std::stringstream ss; 310 std::stringstream ss;
311 ss << std::setw(n) << std::setfill('0') << i; 311 ss << std::setw(n) << std::setfill('0') << i;
stim/visualization/colormap.h
@@ -36,7 +36,7 @@ namespace stim{ @@ -36,7 +36,7 @@ namespace stim{
36 36
37 enum colormapType {cmBrewer, cmGrayscale, cmRainbow}; 37 enum colormapType {cmBrewer, cmGrayscale, cmRainbow};
38 38
39 -static void buffer2image(unsigned char* buffer, std::string filename, unsigned int width, unsigned int height) 39 +static void buffer2image(unsigned char* buffer, std::string filename, size_t width, size_t height)
40 { 40 {
41 /*unsigned char* non_interleaved = (unsigned char*)malloc(x_size * y_size * 3); 41 /*unsigned char* non_interleaved = (unsigned char*)malloc(x_size * y_size * 3);
42 unsigned int S = x_size * y_size; 42 unsigned int S = x_size * y_size;
@@ -216,9 +216,9 @@ static void gpu2image(T* gpuSource, std::string fileDest, unsigned int x_size, u @@ -216,9 +216,9 @@ static void gpu2image(T* gpuSource, std::string fileDest, unsigned int x_size, u
216 #endif 216 #endif
217 217
218 template<class T> 218 template<class T>
219 -static void cpuApplyBrewer(T* cpuSource, unsigned char* cpuDest, unsigned int N, T minVal = 0, T maxVal = 1) 219 +static void cpuApplyBrewer(T* cpuSource, unsigned char* cpuDest, size_t N, T minVal = 0, T maxVal = 1)
220 { 220 {
221 - for(int i=0; i<N; i++) 221 + for(size_t i=0; i<N; i++)
222 { 222 {
223 //compute the normalized value on [minVal maxVal] 223 //compute the normalized value on [minVal maxVal]
224 float a; 224 float a;
@@ -249,15 +249,15 @@ static void cpuApplyBrewer(T* cpuSource, unsigned char* cpuDest, unsigned int N, @@ -249,15 +249,15 @@ static void cpuApplyBrewer(T* cpuSource, unsigned char* cpuDest, unsigned int N,
249 } 249 }
250 250
251 251
252 - cpuDest[i * 3 + 0] = 255 * r;  
253 - cpuDest[i * 3 + 1] = 255 * g;  
254 - cpuDest[i * 3 + 2] = 255 * b; 252 + cpuDest[i * 3 + 0] = (unsigned char)(255 * r);
  253 + cpuDest[i * 3 + 1] = (unsigned char)(255 * g);
  254 + cpuDest[i * 3 + 2] = (unsigned char)(255 * b);
255 255
256 } 256 }
257 } 257 }
258 258
259 template<class T> 259 template<class T>
260 -static void cpu2cpu(T* cpuSource, unsigned char* cpuDest, unsigned int nVals, T valMin, T valMax, colormapType cm = cmGrayscale) 260 +static void cpu2cpu(T* cpuSource, unsigned char* cpuDest, size_t nVals, T valMin, T valMax, colormapType cm = cmGrayscale)
261 { 261 {
262 262
263 if(cm == cmBrewer) 263 if(cm == cmBrewer)
@@ -279,15 +279,15 @@ static void cpu2cpu(T* cpuSource, unsigned char* cpuDest, unsigned int nVals, T @@ -279,15 +279,15 @@ static void cpu2cpu(T* cpuSource, unsigned char* cpuDest, unsigned int nVals, T
279 if(a < 0) a = 0; 279 if(a < 0) a = 0;
280 if(a > 1) a = 1; 280 if(a > 1) a = 1;
281 281
282 - cpuDest[i * 3 + 0] = 255 * a;  
283 - cpuDest[i * 3 + 1] = 255 * a;  
284 - cpuDest[i * 3 + 2] = 255 * a; 282 + cpuDest[i * 3 + 0] = (unsigned char)(255 * a);
  283 + cpuDest[i * 3 + 1] = (unsigned char)(255 * a);
  284 + cpuDest[i * 3 + 2] = (unsigned char)(255 * a);
285 } 285 }
286 } 286 }
287 } 287 }
288 288
289 template<class T> 289 template<class T>
290 -static void cpu2cpu(T* cpuSource, unsigned char* cpuDest, unsigned int nVals, colormapType cm = cmGrayscale) 290 +static void cpu2cpu(T* cpuSource, unsigned char* cpuDest, unsigned long long nVals, colormapType cm = cmGrayscale)
291 { 291 {
292 //computes the max and min range automatically 292 //computes the max and min range automatically
293 293
@@ -313,7 +313,7 @@ static void cpu2cpu(T* cpuSource, unsigned char* cpuDest, unsigned int nVals, co @@ -313,7 +313,7 @@ static void cpu2cpu(T* cpuSource, unsigned char* cpuDest, unsigned int nVals, co
313 313
314 314
315 template<typename T> 315 template<typename T>
316 -static void cpu2image(T* cpuSource, std::string fileDest, unsigned int x_size, unsigned int y_size, T valMin, T valMax, colormapType cm = cmGrayscale) 316 +static void cpu2image(T* cpuSource, std::string fileDest, size_t x_size, size_t y_size, T valMin, T valMax, colormapType cm = cmGrayscale)
317 { 317 {
318 //allocate a color buffer 318 //allocate a color buffer
319 unsigned char* cpuBuffer = (unsigned char*) malloc(sizeof(unsigned char) * 3 * x_size * y_size); 319 unsigned char* cpuBuffer = (unsigned char*) malloc(sizeof(unsigned char) * 3 * x_size * y_size);
@@ -329,7 +329,7 @@ static void cpu2image(T* cpuSource, std::string fileDest, unsigned int x_size, u @@ -329,7 +329,7 @@ static void cpu2image(T* cpuSource, std::string fileDest, unsigned int x_size, u
329 } 329 }
330 330
331 template<typename T> 331 template<typename T>
332 -static void cpu2image(T* cpuSource, std::string fileDest, unsigned int x_size, unsigned int y_size, colormapType cm = cmGrayscale) 332 +static void cpu2image(T* cpuSource, std::string fileDest, size_t x_size, size_t y_size, colormapType cm = cmGrayscale)
333 { 333 {
334 //allocate a color buffer 334 //allocate a color buffer
335 unsigned char* cpuBuffer = (unsigned char*) malloc(sizeof(unsigned char) * 3 * x_size * y_size); 335 unsigned char* cpuBuffer = (unsigned char*) malloc(sizeof(unsigned char) * 3 * x_size * y_size);