Commit 9d3ba0b10c295c9bd0a6a5b1be4779e482be4515
1 parent
798cea97
added stim::hsi as a bridge, fixed warnings for a clean build of HSIproc
Showing
12 changed files
with
2096 additions
and
1319 deletions
Show diff stats
stim/envi/bil.h
@@ -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 |
stim/envi/bip.h
@@ -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 |
stim/envi/bsq.h
@@ -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 |
stim/envi/envi.h
@@ -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; |
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 |
stim/image/CImg.h
@@ -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); |