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 | 2 | #define STIM_BIL_H |
3 | 3 | |
4 | 4 | #include "../envi/envi_header.h" |
5 | -#include "../envi/binary.h" | |
5 | +#include "../envi/hsi.h" | |
6 | 6 | #include <cstring> |
7 | 7 | #include <utility> |
8 | 8 | |
... | ... | @@ -19,28 +19,29 @@ namespace stim{ |
19 | 19 | |
20 | 20 | template <typename T> |
21 | 21 | |
22 | -class bil: public binary<T> { | |
22 | +class bil: public hsi<T> { | |
23 | 23 | |
24 | 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 | 29 | return R[0]; |
30 | 30 | } |
31 | - unsigned long Y(){ | |
31 | + unsigned long long Y(){ | |
32 | 32 | return R[2]; |
33 | 33 | } |
34 | - unsigned long Z(){ | |
34 | + unsigned long long Z(){ | |
35 | 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 | 39 | using binary<T>::progress; |
39 | 40 | |
40 | 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 | 46 | public: |
46 | 47 | |
... | ... | @@ -48,6 +49,8 @@ public: |
48 | 49 | using binary<T>::file; |
49 | 50 | using binary<T>::R; |
50 | 51 | |
52 | + bil(){ hsi<T>::init_bil(); } | |
53 | + | |
51 | 54 | /// Open a data file for reading using the class interface. |
52 | 55 | |
53 | 56 | /// @param filename is the name of the binary file on disk |
... | ... | @@ -56,11 +59,16 @@ public: |
56 | 59 | /// @param B is the number of samples (bands) along dimension 3 |
57 | 60 | /// @param header_offset is the number of bytes (if any) in the binary header |
58 | 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 | 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 | 76 | |
69 | 77 | /// @param p is a pointer to an allocated region of memory at least X * Y * sizeof(T) in size. |
70 | 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 | 80 | //return binary<T>::read_plane_1(p, page); |
73 | 81 | |
74 | 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 | 86 | if (page >= Z()){ //make sure the bank number is right |
79 | 87 | std::cout<<"ERROR: page out of range"<<std::endl; |
... | ... | @@ -81,7 +89,7 @@ public: |
81 | 89 | } |
82 | 90 | |
83 | 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 | 94 | file.read((char *)(p + i * X()), L); |
87 | 95 | file.seekg( jump, std::ios::cur); |
... | ... | @@ -99,12 +107,12 @@ public: |
99 | 107 | |
100 | 108 | //if there are no wavelengths in the BSQ file |
101 | 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 | 118 | //get the bands numbers around the wavelength |
... | ... | @@ -132,9 +140,9 @@ public: |
132 | 140 | p2=(T*)malloc(S); |
133 | 141 | band_index(p1, page - 1); |
134 | 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 | 147 | free(p1); |
140 | 148 | free(p2); |
... | ... | @@ -154,10 +162,10 @@ public: |
154 | 162 | /// @param wavelength is the wavelength to retrieve |
155 | 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 | 169 | T * p1; |
162 | 170 | T * p2; |
163 | 171 | |
... | ... | @@ -186,9 +194,9 @@ public: |
186 | 194 | memcpy(p1, c + (page - 1) * X(), L); |
187 | 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 | 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 | 202 | else //if the wavelength is equal to a wavelength in header file |
... | ... | @@ -202,7 +210,7 @@ public: |
202 | 210 | /// @param p is a pointer to pre-allocated memory at least B * sizeof(T) in size. |
203 | 211 | /// @param x is the x-coordinate (dimension 1) of the spectrum. |
204 | 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 | 214 | return binary<T>::read_line_1(p, x, y, PROGRESS); |
207 | 215 | } |
208 | 216 | |
... | ... | @@ -210,18 +218,18 @@ public: |
210 | 218 | |
211 | 219 | /// @param p is a pointer to pre-allocated memory at least sizeof(T) in size. |
212 | 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 | 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 | 227 | //get the pixel |
220 | 228 | return spectrum(p, x, y); |
221 | 229 | } |
222 | 230 | |
223 | 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 | 233 | return binary<T>::read_plane_2(p, y); |
226 | 234 | } |
227 | 235 | |
... | ... | @@ -232,15 +240,15 @@ public: |
232 | 240 | /// @param wls is the list of baseline points based on band labels. |
233 | 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 | 245 | std::ofstream target(outname.c_str(), std::ios::binary); //open the target binary file |
238 | 246 | std::string headername = outname + ".hdr"; //the header file name |
239 | 247 | |
240 | 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 | 253 | T* c; //pointer to the current Y slice |
246 | 254 | c = (T*)malloc(L); //memory allocation |
... | ... | @@ -254,7 +262,7 @@ public: |
254 | 262 | |
255 | 263 | double ai, bi; //stores the two baseline points wavelength surrounding the current band |
256 | 264 | double ci; //stores the current band's wavelength |
257 | - unsigned control; | |
265 | + unsigned long long control; | |
258 | 266 | |
259 | 267 | if (a == NULL || b == NULL || c == NULL){ |
260 | 268 | std::cout<<"ERROR: error allocating memory"; |
... | ... | @@ -262,7 +270,7 @@ public: |
262 | 270 | } |
263 | 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 | 275 | //get the current y slice |
268 | 276 | read_plane_y(c, k); |
... | ... | @@ -287,7 +295,7 @@ public: |
287 | 295 | |
288 | 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 | 300 | //update baseline points, if necessary |
293 | 301 | if( w[cii] >= bi && cii != B - 1) { |
... | ... | @@ -317,7 +325,7 @@ public: |
317 | 325 | |
318 | 326 | ci = w[cii]; |
319 | 327 | |
320 | - unsigned jump = cii * X(); | |
328 | + unsigned long long jump = cii * X(); | |
321 | 329 | //perform the baseline correction |
322 | 330 | for(unsigned i=0; i < X(); i++) |
323 | 331 | { |
... | ... | @@ -347,11 +355,11 @@ public: |
347 | 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 | 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 | 364 | std::ofstream target(outname.c_str(), std::ios::binary); //open the target binary file |
357 | 365 | std::string headername = outname + ".hdr"; //the header file name |
... | ... | @@ -364,12 +372,12 @@ public: |
364 | 372 | |
365 | 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 | 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 | 382 | if( mask != NULL && !mask[m + j * X()] ) |
375 | 383 | c[m + i * X()] = (T)0.0; |
... | ... | @@ -393,7 +401,7 @@ public: |
393 | 401 | /// @param outname is the name of the output BSQ file to be saved to disk. |
394 | 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 | 406 | std::ofstream target(outname.c_str(), std::ios::binary); |
399 | 407 | std::string headername = outname + ".hdr"; |
... | ... | @@ -401,7 +409,7 @@ public: |
401 | 409 | T * p; //pointer to the current band |
402 | 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 | 414 | band_index(p, i); |
407 | 415 | target.write(reinterpret_cast<const char*>(p), S); //write a band data into target file |
... | ... | @@ -429,13 +437,13 @@ public: |
429 | 437 | T * q; //pointer to the current ZX slice for bip file |
430 | 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 | 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 | 447 | q[k + j * Z()] = p[ks + j]; |
440 | 448 | |
441 | 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 | 469 | /// @param result is a pointer to a pre-allocated array at least X * Y * sizeof(T) in size. |
462 | 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 | 473 | band(result, wavelength); //get band |
466 | 474 | |
467 | 475 | //perform the baseline correction |
468 | 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 | 478 | result[i] =(T) (result[i] - (rp[i] - lp[i]) * r - lp[i] ); |
471 | 479 | } |
472 | 480 | return true; |
... | ... | @@ -482,8 +490,8 @@ public: |
482 | 490 | |
483 | 491 | T* lp; |
484 | 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 | 495 | lp = (T*) malloc(S); //memory allocation |
488 | 496 | rp = (T*) malloc(S); |
489 | 497 | |
... | ... | @@ -513,8 +521,8 @@ public: |
513 | 521 | T* cur; //current band 1 |
514 | 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 | 527 | lp = (T*) malloc(S); //memory allocation |
520 | 528 | rp = (T*) malloc(S); |
... | ... | @@ -524,9 +532,9 @@ public: |
524 | 532 | memset(result, (char)0, S); |
525 | 533 | |
526 | 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 | 563 | //calculate the beginning and the ending part |
556 | 564 | baseline_band(lb, rb, lp, rp, rab, cur2); //ending part |
557 | 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 | 569 | baseline_band(lb, rb, lp, rp, lab, cur2); //beginnning part |
562 | 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 | 575 | //calculate the area |
568 | 576 | ai++; |
569 | - for(unsigned i = ai; i <= bi ;i++) | |
577 | + for(unsigned long long i = ai; i <= bi ;i++) | |
570 | 578 | { |
571 | 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 | 584 | std::swap(cur,cur2); //swap the band pointers |
577 | 585 | } |
... | ... | @@ -601,7 +609,7 @@ public: |
601 | 609 | height(lb1, rb1, pos1, p1); |
602 | 610 | height(lb2, rb2, pos2, p2); |
603 | 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 | 613 | if(p1[i] == 0 && p2[i] ==0) |
606 | 614 | result[i] = 1; |
607 | 615 | else |
... | ... | @@ -632,7 +640,7 @@ public: |
632 | 640 | area(lb1, rb1, lab1, rab1, p1); |
633 | 641 | height(lb2, rb2, pos, p2); |
634 | 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 | 644 | if(p1[i] == 0 && p2[i] ==0) |
637 | 645 | result[i] = 1; |
638 | 646 | else |
... | ... | @@ -665,7 +673,7 @@ public: |
665 | 673 | area(lb1, rb1, lab1, rab1, p1); |
666 | 674 | area(lb2, rb2, lab2, rab2, p2); |
667 | 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 | 677 | if(p1[i] == 0 && p2[i] ==0) |
670 | 678 | result[i] = 1; |
671 | 679 | else |
... | ... | @@ -690,8 +698,8 @@ public: |
690 | 698 | T* cur; //current band 1 |
691 | 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 | 704 | lp = (T*) malloc(S); //memory allocation |
697 | 705 | rp = (T*) malloc(S); |
... | ... | @@ -701,9 +709,9 @@ public: |
701 | 709 | memset(result, (char)0, S); |
702 | 710 | |
703 | 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 | 716 | //to make sure the left and the right bound are in the bandwidth |
709 | 717 | if (lb < w[0] || rb < w[0] || lb > w[n-1] || rb >w[n-1]){ |
... | ... | @@ -730,23 +738,23 @@ public: |
730 | 738 | //calculate the beginning and the ending part |
731 | 739 | baseline_band(lb, rb, lp, rp, rab, cur2); //ending part |
732 | 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 | 744 | baseline_band(lb, rb, lp, rp, lab, cur2); //beginnning part |
737 | 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 | 750 | //calculate f(x) times x |
743 | 751 | ai++; |
744 | - for(unsigned i = ai; i <= bi ;i++) | |
752 | + for(unsigned long long i = ai; i <= bi ;i++) | |
745 | 753 | { |
746 | 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 | 759 | std::swap(cur,cur2); //swap the band pointers |
752 | 760 | } |
... | ... | @@ -773,7 +781,7 @@ public: |
773 | 781 | x_area(lb, rb, lab, rab, p1); |
774 | 782 | area(lb, rb, lab, rab, p2); |
775 | 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 | 785 | if(p1[i] == 0 && p2[i] ==0) |
778 | 786 | result[i] = 1; |
779 | 787 | else |
... | ... | @@ -797,7 +805,7 @@ public: |
797 | 805 | T* temp = (T*)malloc(X() * Y() * sizeof(T)); //allocate memory for the certain band |
798 | 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 | 809 | if (temp[i] < threshold) |
802 | 810 | p[i] = 0; |
803 | 811 | else |
... | ... | @@ -817,17 +825,17 @@ public: |
817 | 825 | std::ofstream target(outfile.c_str(), std::ios::binary); |
818 | 826 | |
819 | 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 | 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 | 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 | 840 | if(p[i * X() + k] == 0) |
833 | 841 | temp[j * X() + k] = 0; |
... | ... | @@ -849,9 +857,9 @@ public: |
849 | 857 | std::ofstream target(outfile.c_str(), std::ios::binary); |
850 | 858 | |
851 | 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 | 864 | //allocate temporary memory for a XZ slice |
857 | 865 | T* slice = (T*) malloc(L); |
... | ... | @@ -860,18 +868,18 @@ public: |
860 | 868 | T* spec = (T*) malloc(B * sizeof(T)); |
861 | 869 | |
862 | 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 | 873 | read_plane_y(slice, y); //retrieve an ZX page, store in "slice" |
866 | 874 | |
867 | 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 | 878 | //if the mask != 0 at that xy pixel |
871 | 879 | if (p[y * X() + x] != 0) //if the mask != 0 at that XY pixel |
872 | 880 | { |
873 | 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 | 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 | 904 | T* temp = (T*)malloc(sizeof(T) * XZ); |
897 | 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 | 908 | getY(temp, i); |
901 | 909 | //initialize x-line |
902 | - for (unsigned j = 0; j < X(); j++){ | |
910 | + for (unsigned long long j = 0; j < X(); j++){ | |
903 | 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 | 916 | line[k] += temp[c] / (T)Z(); |
909 | 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 | 921 | p[j + i * X()] = line[j]; |
914 | 922 | } |
915 | 923 | } |
... | ... | @@ -925,7 +933,7 @@ public: |
925 | 933 | unsigned long long XZ = X() * Z(); |
926 | 934 | unsigned long long XY = X() * Y(); |
927 | 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 | 937 | p[j] = 0; |
930 | 938 | } |
931 | 939 | //calculate vaild number in a band |
... | ... | @@ -1038,9 +1046,9 @@ public: |
1038 | 1046 | //set the start position for the cropped region |
1039 | 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 | 1053 | file.read((char *)(temp + z * samples), sizeof(T) * samples); |
1046 | 1054 | file.seekg(jumpb, std::ios::cur); //go to the next band | ... | ... |
stim/envi/binary.h
... | ... | @@ -25,7 +25,7 @@ protected: |
25 | 25 | std::string name; //file name |
26 | 26 | |
27 | 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 | 29 | unsigned char* mask; //pointer to a character array: 0 = background, 1 = foreground (or valid data) |
30 | 30 | |
31 | 31 | double progress; //stores the progress on the current operation (accessible using a thread) |
... | ... | @@ -33,30 +33,13 @@ protected: |
33 | 33 | |
34 | 34 | /// Private initialization function used to set default parameters in the data structure. |
35 | 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 | 37 | header = 0; //initialize the header size to zero |
38 | 38 | mask = NULL; |
39 | 39 | |
40 | 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 | 43 | /// Private helper function that returns the size of the file on disk using system functions. |
61 | 44 | long long int get_file_size(){ |
62 | 45 | #ifdef _WIN32 |
... | ... | @@ -122,7 +105,7 @@ protected: |
122 | 105 | |
123 | 106 | public: |
124 | 107 | |
125 | - unsigned int get_progress(){ | |
108 | + double get_progress(){ | |
126 | 109 | return progress; |
127 | 110 | } |
128 | 111 | |
... | ... | @@ -135,9 +118,9 @@ public: |
135 | 118 | /// @param filename is the name of the binary file |
136 | 119 | /// @param r is a STIM vector specifying the size of the binary file along each dimension |
137 | 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 | 124 | R[i] = r[i]; |
142 | 125 | |
143 | 126 | header = h; //save the header size |
... | ... | @@ -154,17 +137,17 @@ public: |
154 | 137 | /// @param filename is the name of the binary file to be created |
155 | 138 | /// @param r is a STIM vector specifying the size of the file along each dimension |
156 | 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 | 142 | std::ofstream target(filename.c_str(), std::ios::binary); |
160 | 143 | |
161 | 144 | //initialize binary file |
162 | 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 | 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 | 151 | R[i] = r[i]; |
169 | 152 | |
170 | 153 | header = offset; //save the header size |
... | ... | @@ -178,7 +161,7 @@ public: |
178 | 161 | |
179 | 162 | /// @param p is a pointer to the data to be written |
180 | 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 | 166 | if(p == NULL){ |
184 | 167 | std::cout<<"ERROR: unable to write into file, empty pointer"<<std::endl; |
... | ... | @@ -195,7 +178,7 @@ public: |
195 | 178 | |
196 | 179 | /// @param p is a pointer to pre-allocated memory equal to the page size |
197 | 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 | 183 | if(PROGRESS) progress = 0; |
201 | 184 | |
... | ... | @@ -217,8 +200,8 @@ public: |
217 | 200 | /// @param p is a pointer to pre-allocated memory equal to the line size R[2] |
218 | 201 | /// @param x is the x coordinate |
219 | 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 | 206 | if(PROGRESS) progress = 0; |
224 | 207 | |
... | ... | @@ -244,7 +227,7 @@ public: |
244 | 227 | /// @param p is a pointer to pre-allocated memory equal to the line size R[2] |
245 | 228 | /// @param x is the y coordinate |
246 | 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 | 231 | //test to make sure the specified value is within range |
249 | 232 | if( y >= R[1] || z >= R[2] ){ |
250 | 233 | std::cout<<"ERROR: sample or line out of range"<<std::endl; |
... | ... | @@ -262,7 +245,7 @@ public: |
262 | 245 | /// @param p is a pointer to pre-allocated memory equal to the line size R[2] |
263 | 246 | /// @param x is the y coordinate |
264 | 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 | 249 | if(PROGRESS) progress = 0; |
267 | 250 | //test to make sure the specified value is within range |
268 | 251 | if( x >= R[0] || z >= R[2] ){ |
... | ... | @@ -271,7 +254,7 @@ public: |
271 | 254 | } |
272 | 255 | |
273 | 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 | 258 | file.read((char *)(p + i), sizeof(T)); //read the pixel |
276 | 259 | file.seekg((R[0] - 1) * sizeof(T), std::ios::cur); //seek to the next pixel in the line |
277 | 260 | if(PROGRESS) progress = (double)i / (double)R[1] * 100; |
... | ... | @@ -284,22 +267,22 @@ public: |
284 | 267 | |
285 | 268 | /// @param p is a pointer to pre-allocated memory of size R[1] * R[2] * sizeof(T) |
286 | 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 | 271 | if(PROGRESS) progress = 0; |
289 | 272 | if (n >= R[0]){ //make sure the number is within the possible range |
290 | 273 | std::cout<<"ERROR read_plane_0: page out of range"<<std::endl; |
291 | 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 | 278 | //seek to the start of the plane |
296 | 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 | 283 | file.read((char*)(p+i), sizeof(T)); |
301 | 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 | 288 | if(PROGRESS) progress = 100; |
... | ... | @@ -312,10 +295,10 @@ public: |
312 | 295 | |
313 | 296 | /// @param p is a pointer to pre-allocated memory of size R[0] * R[2] * sizeof(T) |
314 | 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 | 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 | 303 | if (n >= R[1]){ //make sure the bank number is right |
321 | 304 | std::cout<<"ERROR read_plane_1: page out of range"<<std::endl; |
... | ... | @@ -323,7 +306,7 @@ public: |
323 | 306 | } |
324 | 307 | |
325 | 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 | 310 | if(PROGRESS) progress = (double)i / R[2] * 100; |
328 | 311 | file.read((char *)(p + i * R[0]), L); |
329 | 312 | file.seekg( jump, std::ios::cur); |
... | ... | @@ -338,7 +321,7 @@ public: |
338 | 321 | |
339 | 322 | /// @param p is a pointer to pre-allocated memory of size R[0] * R[1] * sizeof(T) |
340 | 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 | 325 | return read_page(p, n, PROGRESS); |
343 | 326 | } |
344 | 327 | |
... | ... | @@ -346,7 +329,7 @@ public: |
346 | 329 | |
347 | 330 | /// @param p is a pointer to pre-allocated memory of size sizeof(T) |
348 | 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 | 333 | if(i >= R[0] * R[1] * R[2]){ |
351 | 334 | std::cout<<"ERROR read_pixel: n is out of range"<<std::endl; |
352 | 335 | return false; |
... | ... | @@ -363,14 +346,14 @@ public: |
363 | 346 | /// @param x is the x (0) axis coordinate |
364 | 347 | /// @param y is the y (1) axis coordinate |
365 | 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 | 351 | if(x < 0 || x >= R[0] || y < 0 || y >= R[1] || z < 0 || z > R[2]){ |
369 | 352 | std::cout<<"ERROR read_pixel: (x,y,z) is out of range"<<std::endl; |
370 | 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 | 357 | return read_pixel(p, i); |
375 | 358 | } |
376 | 359 | ... | ... |
stim/envi/bip.h
... | ... | @@ -3,7 +3,7 @@ |
3 | 3 | |
4 | 4 | #include "../envi/envi_header.h" |
5 | 5 | #include "../envi/bil.h" |
6 | -#include "../envi/binary.h" | |
6 | +#include "../envi/hsi.h" | |
7 | 7 | #include <cstring> |
8 | 8 | #include <utility> |
9 | 9 | |
... | ... | @@ -23,15 +23,15 @@ namespace stim{ |
23 | 23 | */ |
24 | 24 | template <typename T> |
25 | 25 | |
26 | -class bip: public binary<T> { | |
26 | +class bip: public hsi<T> { | |
27 | 27 | |
28 | 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 | 35 | return R[1]; |
36 | 36 | } |
37 | 37 | unsigned long long Y(){ |
... | ... | @@ -39,17 +39,18 @@ protected: |
39 | 39 | } |
40 | 40 | unsigned long long Z(){ |
41 | 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 | 45 | using binary<T>::progress; |
45 | 46 | |
46 | 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 | 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 | 54 | if(low_w == high_w) return low_v; //if the interval is of zero length, just return one of the bounds |
54 | 55 | double alpha = (w - low_w) / (high_w - low_w); //calculate the interpolation factor |
55 | 56 | return (1.0 - alpha) * low_v + alpha * high_v; //interpolate |
... | ... | @@ -104,7 +105,7 @@ protected: |
104 | 105 | v[n] = interp_spectrum(s, wavelengths[n]); //interpolate the measurement |
105 | 106 | } |
106 | 107 | return v; |
107 | - } | |
108 | + }*/ | |
108 | 109 | |
109 | 110 | public: |
110 | 111 | |
... | ... | @@ -113,6 +114,8 @@ public: |
113 | 114 | using binary<T>::R; |
114 | 115 | using binary<T>::read_line_0; |
115 | 116 | |
117 | + bip(){ hsi<T>::init_bip(); } | |
118 | + | |
116 | 119 | /// Open a data file for reading using the class interface. |
117 | 120 | |
118 | 121 | /// @param filename is the name of the binary file on disk |
... | ... | @@ -121,14 +124,19 @@ public: |
121 | 124 | /// @param B is the number of samples (bands) along dimension 3 |
122 | 125 | /// @param header_offset is the number of bytes (if any) in the binary header |
123 | 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 | 134 | //copy the wavelengths to the BSQ file structure |
127 | 135 | w = wavelengths; |
128 | 136 | //copy the offset to the structure |
129 | 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 | 144 | |
137 | 145 | /// @param p is a pointer to an allocated region of memory at least X * Y * sizeof(T) in size. |
138 | 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 | 148 | return binary<T>::read_plane_0(p, page, PROGRESS); |
141 | 149 | } |
142 | 150 | |
... | ... | @@ -148,9 +156,9 @@ public: |
148 | 156 | |
149 | 157 | //if there are no wavelengths in the BSQ file |
150 | 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 | 163 | unsigned page=0; //bands around the wavelength |
156 | 164 | |
... | ... | @@ -180,9 +188,9 @@ public: |
180 | 188 | p2=(T*)malloc( XY * sizeof(T)); |
181 | 189 | band_index(p1, page - 1); |
182 | 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 | 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 | 195 | free(p1); |
188 | 196 | free(p2); |
... | ... | @@ -200,7 +208,7 @@ public: |
200 | 208 | /// @param p is a pointer to pre-allocated memory at least B * sizeof(T) in size. |
201 | 209 | /// @param x is the x-coordinate (dimension 1) of the spectrum. |
202 | 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 | 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 | 219 | /// @param wavelength is the wavelength of X values to retrieve |
212 | 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 | 227 | //get the bands numbers around the wavelength |
220 | 228 | |
221 | 229 | //if wavelength is smaller than the first one in header file |
222 | 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 | 233 | p[j] = c[j * B]; |
226 | 234 | } |
... | ... | @@ -232,7 +240,7 @@ public: |
232 | 240 | page++; |
233 | 241 | //if wavelength is larger than the last wavelength in header file |
234 | 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 | 245 | p[j] = c[(j + 1) * B - 1]; |
238 | 246 | } |
... | ... | @@ -246,17 +254,17 @@ public: |
246 | 254 | p1=(T*)malloc( X() * sizeof(T)); //memory allocation |
247 | 255 | p2=(T*)malloc( X() * sizeof(T)); |
248 | 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 | 259 | p1[j] = c[j * B + page - 1]; |
252 | 260 | } |
253 | 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 | 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 | 268 | double r = (double) (wavelength - w[page-1]) / (double) (w[page] - w[page-1]); |
261 | 269 | p[i] = (p2[i] - p1[i]) * r + p1[i]; |
262 | 270 | } |
... | ... | @@ -266,7 +274,7 @@ public: |
266 | 274 | else //if the wavelength is equal to a wavelength in header file |
267 | 275 | { |
268 | 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 | 279 | p[j] = c[j * B + page]; |
272 | 280 | } |
... | ... | @@ -276,29 +284,30 @@ public: |
276 | 284 | } |
277 | 285 | |
278 | 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 | 289 | if ( n >= bandnum){ //make sure the pixel number is right |
282 | 290 | std::cout<<"ERROR: sample or line out of range"<<std::endl; |
283 | 291 | return false; |
284 | 292 | } |
285 | - unsigned B = Z(); | |
293 | + unsigned long long B = Z(); | |
286 | 294 | |
287 | 295 | T* temp = (T*) malloc(B * sizeof(T)); //allocate space for the raw pixel data |
288 | 296 | file.seekg(n * B * sizeof(T), std::ios::beg); //point to the certain pixel |
289 | 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 | 300 | p[i] = (double) temp[i]; //cast each element to a double value |
301 | + return true; | |
293 | 302 | } |
294 | 303 | |
295 | 304 | /// Retrieve a single pixel and stores it in pre-allocated memory. |
296 | 305 | |
297 | 306 | /// @param p is a pointer to pre-allocated memory at least sizeof(T) in size. |
298 | 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 | 311 | if ( n >= N){ //make sure the pixel number is right |
303 | 312 | std::cout<<"ERROR: sample or line out of range"<<std::endl; |
304 | 313 | return false; |
... | ... | @@ -310,7 +319,7 @@ public: |
310 | 319 | } |
311 | 320 | |
312 | 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 | 323 | return binary<T>::read_plane_2(p, y); |
315 | 324 | } |
316 | 325 | |
... | ... | @@ -330,7 +339,6 @@ public: |
330 | 339 | std::vector<T> base_vals; //allocate space for the values at each baseline point |
331 | 340 | double aw, bw; //surrounding baseline point wavelengths |
332 | 341 | T av, bv; //surrounding baseline point values |
333 | - double alpha; | |
334 | 342 | unsigned long long ai, bi; //surrounding baseline point band indices |
335 | 343 | for(unsigned long long n = 0; n < N; n++){ //for each pixel in the image |
336 | 344 | if(mask != NULL && !mask[n]){ //if the pixel isn't masked |
... | ... | @@ -393,14 +401,14 @@ public: |
393 | 401 | T* s = (T*)malloc(sizeof(T) * B); //allocate memory to store a pixel |
394 | 402 | T nv; //stores the value of the normalized band |
395 | 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 | 404 | if(mask != NULL && !mask[n]) //if the normalization band is below threshold |
399 | 405 | memset(s, 0, sizeof(T) * B); //set the output to zero |
400 | 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 | 411 | s[b] /= nv; //divide by the normalization value |
403 | - } | |
404 | 412 | } |
405 | 413 | |
406 | 414 | if(PROGRESS) progress = (double)(n+1) / N * 100; //set the current progress |
... | ... | @@ -419,23 +427,23 @@ public: |
419 | 427 | /// @param outname is the name of the output BIL file to be saved to disk. |
420 | 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 | 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 | 435 | T * p; //pointer to the current ZX slice for bip file |
428 | 436 | p = (T*)malloc(S); |
429 | 437 | T * q; //pointer to the current XZ slice for bil file |
430 | 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 | 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 | 447 | q[ks + j] = p[k + j * Z()]; |
440 | 448 | |
441 | 449 | if(PROGRESS) progress = (double)(i * Z() + k+1) / (Y() * Z()) * 100; |
... | ... | @@ -459,12 +467,12 @@ public: |
459 | 467 | /// @param result is a pointer to a pre-allocated array at least X * Y * sizeof(T) in size. |
460 | 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 | 471 | band(result, wavelength); //get band |
464 | 472 | |
465 | 473 | //perform the baseline correction |
466 | 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 | 476 | result[i] =(T) (result[i] - (rp[i] - lp[i]) * r - lp[i] ); |
469 | 477 | } |
470 | 478 | return true; |
... | ... | @@ -480,8 +488,8 @@ public: |
480 | 488 | |
481 | 489 | T* lp; |
482 | 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 | 493 | lp = (T*) malloc(S); //memory allocation |
486 | 494 | rp = (T*) malloc(S); |
487 | 495 | |
... | ... | @@ -510,8 +518,8 @@ public: |
510 | 518 | T* cur; //current band 1 |
511 | 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 | 524 | lp = (T*) malloc(S); //memory allocation |
517 | 525 | rp = (T*) malloc(S); |
... | ... | @@ -521,9 +529,9 @@ public: |
521 | 529 | memset(result, (char)0, S); |
522 | 530 | |
523 | 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 | 560 | //calculate the beginning and the ending part |
553 | 561 | baseline_band(lb, rb, lp, rp, rab, cur2); //ending part |
554 | 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 | 566 | baseline_band(lb, rb, lp, rp, lab, cur2); //beginnning part |
559 | 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 | 572 | //calculate the area |
565 | 573 | ai++; |
566 | - for(unsigned i = ai; i <= bi ;i++) | |
574 | + for(unsigned long long i = ai; i <= bi ;i++) | |
567 | 575 | { |
568 | 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 | 581 | std::swap(cur,cur2); //swap the band pointers |
574 | 582 | } |
... | ... | @@ -598,7 +606,7 @@ public: |
598 | 606 | height(lb1, rb1, pos1, p1); |
599 | 607 | height(lb2, rb2, pos2, p2); |
600 | 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 | 610 | if(p1[i] == 0 && p2[i] ==0) |
603 | 611 | result[i] = 1; |
604 | 612 | else |
... | ... | @@ -629,7 +637,7 @@ public: |
629 | 637 | area(lb1, rb1, lab1, rab1, p1); |
630 | 638 | height(lb2, rb2, pos, p2); |
631 | 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 | 641 | if(p1[i] == 0 && p2[i] ==0) |
634 | 642 | result[i] = 1; |
635 | 643 | else |
... | ... | @@ -662,7 +670,7 @@ public: |
662 | 670 | area(lb1, rb1, lab1, rab1, p1); |
663 | 671 | area(lb2, rb2, lab2, rab2, p2); |
664 | 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 | 674 | if(p1[i] == 0 && p2[i] ==0) |
667 | 675 | result[i] = 1; |
668 | 676 | else |
... | ... | @@ -687,8 +695,8 @@ public: |
687 | 695 | T* cur; //current band 1 |
688 | 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 | 701 | lp = (T*) malloc(S); //memory allocation |
694 | 702 | rp = (T*) malloc(S); |
... | ... | @@ -698,9 +706,9 @@ public: |
698 | 706 | memset(result, (char)0, S); |
699 | 707 | |
700 | 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 | 713 | //to make sure the left and the right bound are in the bandwidth |
706 | 714 | if (lb < w[0] || rb < w[0] || lb > w[n-1] || rb >w[n-1]){ |
... | ... | @@ -727,23 +735,23 @@ public: |
727 | 735 | //calculate the beginning and the ending part |
728 | 736 | baseline_band(lb, rb, lp, rp, rab, cur2); //ending part |
729 | 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 | 741 | baseline_band(lb, rb, lp, rp, lab, cur2); //beginnning part |
734 | 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 | 747 | //calculate f(x) times x |
740 | 748 | ai++; |
741 | - for(unsigned i = ai; i <= bi ;i++) | |
749 | + for(unsigned long long i = ai; i <= bi ;i++) | |
742 | 750 | { |
743 | 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 | 756 | std::swap(cur,cur2); //swap the band pointers |
749 | 757 | } |
... | ... | @@ -770,7 +778,7 @@ public: |
770 | 778 | x_area(lb, rb, lab, rab, p1); |
771 | 779 | area(lb, rb, lab, rab, p2); |
772 | 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 | 782 | if(p1[i] == 0 && p2[i] ==0) |
775 | 783 | result[i] = 1; |
776 | 784 | else |
... | ... | @@ -794,7 +802,7 @@ public: |
794 | 802 | T* temp = (T*)malloc(X() * Y() * sizeof(T)); //allocate memory for the certain band |
795 | 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 | 806 | if (temp[i] < threshold) |
799 | 807 | p[i] = 0; |
800 | 808 | else |
... | ... | @@ -814,17 +822,17 @@ public: |
814 | 822 | |
815 | 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 | 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 | 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 | 837 | if (p[i * X() + j] == 0) //if the mask value is zero |
830 | 838 | temp[j * Z() + k] = 0; //set the pixel value to zero |
... | ... | @@ -850,15 +858,15 @@ public: |
850 | 858 | std::ofstream target(outfile.c_str(), std::ios::binary); |
851 | 859 | |
852 | 860 | //allocate space for a single spectrum |
853 | - unsigned long B = Z(); | |
861 | + unsigned long long B = Z(); | |
854 | 862 | T* spectrum = (T*) malloc(B * sizeof(T)); |
855 | 863 | |
856 | 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 | 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 | 871 | //if the current pixel isn't masked |
864 | 872 | if( mask[x] == 0){ |
... | ... | @@ -879,9 +887,8 @@ public: |
879 | 887 | |
880 | 888 | //write this pixel out |
881 | 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 | 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 | 904 | // open an output stream |
898 | 905 | std::ofstream target(outfile.c_str(), std::ios::binary); |
... | ... | @@ -901,7 +908,7 @@ public: |
901 | 908 | file.seekg(0, std::ios::beg); |
902 | 909 | |
903 | 910 | //allocate space for a single spectrum |
904 | - unsigned long B = Z(); | |
911 | + unsigned long long B = Z(); | |
905 | 912 | T* spectrum = (T*) malloc(B * sizeof(T)); |
906 | 913 | |
907 | 914 | //allocate space for a spectrum of zeros |
... | ... | @@ -909,11 +916,11 @@ public: |
909 | 916 | memset(zeros, 0, B * sizeof(T)); |
910 | 917 | |
911 | 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 | 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 | 925 | //if the current pixel isn't masked |
919 | 926 | if( mask[x] == 0){ |
... | ... | @@ -951,24 +958,23 @@ public: |
951 | 958 | /// @param p is a pointer to pre-allocated memory of size [B * sizeof(T)] that stores the mean spectrum |
952 | 959 | /// @param mask is a pointer to memory of size [X * Y] that stores the mask value at each pixel location |
953 | 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 | 980 | free(temp); |
... | ... | @@ -976,6 +982,7 @@ public: |
976 | 982 | } |
977 | 983 | #ifdef CUDA_FOUND |
978 | 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 | 986 | bool co_matrix_cublas(double* co, double* avg, unsigned char *mask, bool PROGRESS = false){ |
980 | 987 | |
981 | 988 | cudaError_t cudaStat; |
... | ... | @@ -994,7 +1001,7 @@ public: |
994 | 1001 | cudaStat = cudaMalloc(&A_dev, B * B * sizeof(double)); //allocate space on the CUDA device for the covariance matrix |
995 | 1002 | cudaStat = cudaMemset(A_dev, 0, B * B * sizeof(double)); //initialize the covariance matrix to zero (0) |
996 | 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 | 1006 | double ger_alpha = 1.0/(double)XY; //scale the outer product by the inverse of the number of samples (mean outer product) |
1000 | 1007 | double axpy_alpha = -1; //multiplication factor for the average spectrum (in order to perform a subtraction) |
... | ... | @@ -1007,22 +1014,22 @@ public: |
1007 | 1014 | for (unsigned long long xy = 0; xy < XY; xy++){ //for each pixel |
1008 | 1015 | if (mask == NULL || mask[xy] != 0){ |
1009 | 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 | 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 | 1027 | cudaFree(A_dev); //clean up allocated device memory |
1021 | 1028 | cudaFree(s_dev); |
1022 | 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 | 1033 | co[B * i + j] = co[B * j + i]; |
1027 | 1034 | } |
1028 | 1035 | } |
... | ... | @@ -1046,14 +1053,13 @@ public: |
1046 | 1053 | unsigned long long XY = X() * Y(); |
1047 | 1054 | unsigned long long B = Z(); |
1048 | 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 | 1059 | //initialize covariance matrix |
1053 | 1060 | memset(co, 0, B * B * sizeof(double)); |
1054 | 1061 | |
1055 | 1062 | //calculate covariance matrix |
1056 | - T i_diff; //stores (temp[i] - avg[i]) to speed math | |
1057 | 1063 | double* co_half = (double*) malloc(B * B * sizeof(double)); //allocate space for a higher-precision intermediate matrix |
1058 | 1064 | double* temp_precise = (double*) malloc(B * sizeof(double)); |
1059 | 1065 | memset(co_half, 0, B * B * sizeof(double)); //initialize the high-precision matrix with zeros |
... | ... | @@ -1083,10 +1089,10 @@ public: |
1083 | 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 | 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 | 1097 | //memory allocation |
1092 | 1098 | unsigned long long XY = X() * Y(); |
... | ... | @@ -1096,15 +1102,17 @@ public: |
1096 | 1102 | T* rs = (T*)malloc(sizeof(T) * M); //allocate space for the projected spectrum |
1097 | 1103 | double* bv; //pointer to the current projection vector |
1098 | 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 | 1116 | target.write(reinterpret_cast<const char*>(rs), sizeof(T) * M); //write the projected vector |
1109 | 1117 | if(PROGRESS) progress = (double)(xy+1) / XY * 100; |
1110 | 1118 | } |
... | ... | @@ -1135,7 +1143,7 @@ public: |
1135 | 1143 | for(unsigned long long c = 0; c < C; c++){ //for each basis vector coefficient |
1136 | 1144 | bv = &basis[c * B]; //assign 'bv' to the beginning of the basis vector |
1137 | 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 | 2 | #define STIM_BSQ_H |
3 | 3 | |
4 | 4 | #include "../envi/envi_header.h" |
5 | -#include "../envi/binary.h" | |
5 | +#include "../envi/hsi.h" | |
6 | 6 | #include "../envi/bil.h" |
7 | 7 | #include <cstring> |
8 | 8 | #include <utility> |
... | ... | @@ -22,27 +22,27 @@ namespace stim{ |
22 | 22 | */ |
23 | 23 | template <typename T> |
24 | 24 | |
25 | -class bsq: public binary<T> { | |
25 | +class bsq: public hsi<T> { | |
26 | 26 | |
27 | 27 | |
28 | 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 | 33 | using binary<T>::R; |
34 | 34 | |
35 | - unsigned long X(){ | |
35 | + /*unsigned long long X(){ | |
36 | 36 | return R[0]; |
37 | 37 | } |
38 | - unsigned long Y(){ | |
38 | + unsigned long long Y(){ | |
39 | 39 | return R[1]; |
40 | 40 | } |
41 | - unsigned long Z(){ | |
41 | + unsigned long long Z(){ | |
42 | 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 | 46 | using binary<T>::progress; |
47 | 47 | |
48 | 48 | public: |
... | ... | @@ -51,8 +51,8 @@ public: |
51 | 51 | using binary<T>::file; |
52 | 52 | using binary<T>::read_line_2; |
53 | 53 | using binary<T>::read_plane_2; |
54 | - //using binary<T>::getSlice; | |
55 | 54 | |
55 | + bsq(){ hsi<T>::init_bsq(); } | |
56 | 56 | |
57 | 57 | /// Open a data file for reading using the class interface. |
58 | 58 | |
... | ... | @@ -62,21 +62,26 @@ public: |
62 | 62 | /// @param B is the number of samples (bands) along dimension 3 |
63 | 63 | /// @param header_offset is the number of bytes (if any) in the binary header |
64 | 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 | 72 | //copy the wavelengths to the BSQ file structure |
68 | 73 | w = wavelengths; |
69 | 74 | //copy the wavelengths to the structure |
70 | 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 | 80 | /// Retrieve a single band (based on index) and stores it in pre-allocated memory. |
76 | 81 | |
77 | 82 | /// @param p is a pointer to an allocated region of memory at least X * Y * sizeof(T) in size. |
78 | 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 | 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 | 93 | if(PROGRESS) progress = 0; |
89 | 94 | //if there are no wavelengths in the BSQ file |
90 | 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 | 102 | //get the two neighboring bands (above and below 'wavelength') |
... | ... | @@ -122,9 +127,9 @@ public: |
122 | 127 | p2=(T*)malloc( XY * sizeof(T)); |
123 | 128 | band_index(p1, page - 1); |
124 | 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 | 134 | free(p1); |
130 | 135 | free(p2); |
... | ... | @@ -142,7 +147,7 @@ public: |
142 | 147 | /// @param p is a pointer to pre-allocated memory at least B * sizeof(T) in size. |
143 | 148 | /// @param x is the x-coordinate (dimension 1) of the spectrum. |
144 | 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 | 151 | return read_line_2(p, x, y, PROGRESS); |
147 | 152 | } |
148 | 153 | |
... | ... | @@ -150,16 +155,16 @@ public: |
150 | 155 | |
151 | 156 | /// @param p is a pointer to pre-allocated memory at least sizeof(T) in size. |
152 | 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 | 161 | if ( n >= bandnum){ //make sure the pixel number is right |
157 | 162 | std::cout<<"ERROR: sample or line out of range"<<std::endl; |
158 | 163 | return false; |
159 | 164 | } |
160 | 165 | |
161 | 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 | 169 | file.read((char *)(p + i), sizeof(T)); |
165 | 170 | file.seekg((bandnum - 1) * sizeof(T), std::ios::cur); //go to the next band |
... | ... | @@ -174,20 +179,20 @@ public: |
174 | 179 | /// @param wls is the list of baseline points based on band labels. |
175 | 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 | 184 | std::ofstream target(outname.c_str(), std::ios::binary); //open the target binary file |
180 | 185 | std::string headername = outname + ".hdr"; //the header file name |
181 | 186 | |
182 | 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 | 192 | double ai, bi; //stores the two baseline points wavelength surrounding the current band |
188 | 193 | double ci; //stores the current band's wavelength |
189 | 194 | |
190 | - unsigned control=0; | |
195 | + unsigned long long control=0; | |
191 | 196 | |
192 | 197 | T * a; //pointers to the high and low band images |
193 | 198 | T * b; |
... | ... | @@ -222,7 +227,7 @@ public: |
222 | 227 | band(b, bi); |
223 | 228 | |
224 | 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 | 232 | //update baseline points, if necessary |
228 | 233 | if( w[cii] >= bi && cii != B - 1) { |
... | ... | @@ -255,7 +260,7 @@ public: |
255 | 260 | ci = w[cii]; |
256 | 261 | |
257 | 262 | //perform the baseline correction |
258 | - for(unsigned i=0; i < XY; i++){ | |
263 | + for(unsigned long long i=0; i < XY; i++){ | |
259 | 264 | if(mask != NULL && !mask[i]) //if the pixel is excluded by a mask |
260 | 265 | c[i] = 0; //set the value to zero |
261 | 266 | else{ |
... | ... | @@ -287,9 +292,9 @@ public: |
287 | 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 | 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 | 299 | std::ofstream target(outname.c_str(), std::ios::binary); //open the target binary file |
295 | 300 | std::string headername = outname + ".hdr"; //the header file name |
... | ... | @@ -302,10 +307,10 @@ public: |
302 | 307 | |
303 | 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 | 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 | 315 | if(mask != NULL && !mask[i]) |
311 | 316 | c[i] = (T)0.0; |
... | ... | @@ -333,26 +338,24 @@ public: |
333 | 338 | bool bil(std::string outname, bool PROGRESS = false) |
334 | 339 | { |
335 | 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 | 343 | std::ofstream target(outname.c_str(), std::ios::binary); |
340 | 344 | std::string headername = outname + ".hdr"; |
341 | 345 | |
342 | - unsigned int L = X(); | |
346 | + unsigned long long L = X(); | |
343 | 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 | 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 | 354 | file.read((char *)line, sizeof(T) * X()); //read a line |
351 | 355 | target.write((char*)line, sizeof(T) * X()); //write the line to the output file |
352 | 356 | file.seekg(jump, std::ios::cur); //seek to the next band |
353 | 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 | 361 | free(line); |
... | ... | @@ -371,12 +374,12 @@ public: |
371 | 374 | /// @param result is a pointer to a pre-allocated array at least X * Y * sizeof(T) in size. |
372 | 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 | 378 | band(result, wavelength); //get band |
376 | 379 | |
377 | 380 | //perform the baseline correction |
378 | 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 | 383 | result[i] =(T) (result[i] - (rp[i] - lp[i]) * r - lp[i] ); |
381 | 384 | } |
382 | 385 | return true; |
... | ... | @@ -392,8 +395,8 @@ public: |
392 | 395 | |
393 | 396 | T* lp; |
394 | 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 | 400 | lp = (T*) malloc(S); //memory allocation |
398 | 401 | rp = (T*) malloc(S); |
399 | 402 | |
... | ... | @@ -422,8 +425,8 @@ public: |
422 | 425 | T* cur; //current band 1 |
423 | 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 | 431 | lp = (T*) malloc(S); //memory allocation |
429 | 432 | rp = (T*) malloc(S); |
... | ... | @@ -433,9 +436,9 @@ public: |
433 | 436 | memset(result, (char)0, S); |
434 | 437 | |
435 | 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 | 467 | //calculate the beginning and the ending part |
465 | 468 | baseline_band(lb, rb, lp, rp, rab, cur2); //ending part |
466 | 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 | 473 | baseline_band(lb, rb, lp, rp, lab, cur2); //beginnning part |
471 | 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 | 479 | //calculate the area |
477 | 480 | ai++; |
478 | - for(unsigned i = ai; i <= bi ;i++) | |
481 | + for(unsigned long long i = ai; i <= bi ;i++) | |
479 | 482 | { |
480 | 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 | 488 | std::swap(cur,cur2); //swap the band pointers |
486 | 489 | } |
... | ... | @@ -510,7 +513,7 @@ public: |
510 | 513 | height(lb1, rb1, pos1, p1); |
511 | 514 | height(lb2, rb2, pos2, p2); |
512 | 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 | 517 | if(p1[i] == 0 && p2[i] ==0) |
515 | 518 | result[i] = 1; |
516 | 519 | else |
... | ... | @@ -541,7 +544,7 @@ public: |
541 | 544 | area(lb1, rb1, lab1, rab1, p1); |
542 | 545 | height(lb2, rb2, pos, p2); |
543 | 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 | 548 | if(p1[i] == 0 && p2[i] ==0) |
546 | 549 | result[i] = 1; |
547 | 550 | else |
... | ... | @@ -574,7 +577,7 @@ public: |
574 | 577 | area(lb1, rb1, lab1, rab1, p1); |
575 | 578 | area(lb2, rb2, lab2, rab2, p2); |
576 | 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 | 581 | if(p1[i] == 0 && p2[i] ==0) |
579 | 582 | result[i] = 1; |
580 | 583 | else |
... | ... | @@ -599,8 +602,8 @@ public: |
599 | 602 | T* cur; //current band 1 |
600 | 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 | 608 | lp = (T*) malloc(S); //memory allocation |
606 | 609 | rp = (T*) malloc(S); |
... | ... | @@ -610,9 +613,9 @@ public: |
610 | 613 | memset(result, (char)0, S); |
611 | 614 | |
612 | 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 | 620 | //to make sure the left and the right bound are in the bandwidth |
618 | 621 | if (lb < w[0] || rb < w[0] || lb > w[n-1] || rb >w[n-1]){ |
... | ... | @@ -639,23 +642,23 @@ public: |
639 | 642 | //calculate the beginning and the ending part |
640 | 643 | baseline_band(lb, rb, lp, rp, rab, cur2); //ending part |
641 | 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 | 648 | baseline_band(lb, rb, lp, rp, lab, cur2); //beginnning part |
646 | 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 | 654 | //calculate f(x) times x |
652 | 655 | ai++; |
653 | - for(unsigned i = ai; i <= bi ;i++) | |
656 | + for(unsigned long long i = ai; i <= bi ;i++) | |
654 | 657 | { |
655 | 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 | 663 | std::swap(cur,cur2); //swap the band pointers |
661 | 664 | } |
... | ... | @@ -682,7 +685,7 @@ public: |
682 | 685 | x_area(lb, rb, lab, rab, p1); |
683 | 686 | area(lb, rb, lab, rab, p2); |
684 | 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 | 689 | if(p1[i] == 0 && p2[i] ==0) |
687 | 690 | result[i] = 1; |
688 | 691 | else |
... | ... | @@ -706,13 +709,13 @@ public: |
706 | 709 | T* temp = (T*)malloc(X() * Y() * sizeof(T)); //allocate memory for the certain band |
707 | 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 | 713 | if (temp[i] < threshold) |
711 | 714 | p[i] = 0; |
712 | 715 | else |
713 | 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 | 721 | free(temp); |
... | ... | @@ -728,15 +731,15 @@ public: |
728 | 731 | |
729 | 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 | 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 | 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 | 744 | if(p[j] == 0){ //if the mask is 0 at that pixel |
742 | 745 | temp[j] = 0; //set temp to zero |
... | ... | @@ -787,56 +790,24 @@ public: |
787 | 790 | |
788 | 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 | 794 | /// Saves to disk only those spectra corresponding to mask values != 0 |
824 | 795 | /// @param outfile is the name of the sifted ENVI file to be written to disk |
825 | 796 | /// @param unsigned char* p is the mask file used for sifting |
826 | 797 | bool sift(std::string outfile, unsigned char* p, bool PROGRESS = false){ |
827 | 798 | std::ofstream target(outfile.c_str(), std::ios::binary); |
828 | 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 | 802 | unsigned long long B = Z(); |
832 | 803 | |
833 | 804 | T * temp = (T*)malloc(L); //allocate memory for a band |
834 | 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 | 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 | 812 | if (p[j] != 0){ //if the mask is != 0 at that pixel |
842 | 813 | temp_vox[0] = temp[j]; |
... | ... | @@ -844,9 +815,7 @@ public: |
844 | 815 | } |
845 | 816 | else{ |
846 | 817 | continue; |
847 | - } | |
848 | - | |
849 | - | |
818 | + } | |
850 | 819 | } |
851 | 820 | if(PROGRESS) progress = (double)(i+1)/ B * 100; |
852 | 821 | } |
... | ... | @@ -859,7 +828,7 @@ public: |
859 | 828 | } |
860 | 829 | |
861 | 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 | 833 | //create a binary output stream |
865 | 834 | std::ofstream target(outfile.c_str(), std::ios::binary); |
... | ... | @@ -873,9 +842,9 @@ public: |
873 | 842 | std::cout<<"started sifting"<<std::endl; |
874 | 843 | |
875 | 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 | 849 | // allocate memory for a sifted band |
881 | 850 | T * sifted = (T*)malloc(P * sizeof(T)); //allocate memory for a band |
... | ... | @@ -884,16 +853,16 @@ public: |
884 | 853 | T* unsifted = (T*) malloc(XY * sizeof(T)); |
885 | 854 | |
886 | 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 | 858 | //set the unsifted index value to zero |
890 | - unsigned long i = 0; | |
859 | + unsigned long long i = 0; | |
891 | 860 | |
892 | 861 | //retrieve the sifted band (masked pixels only) |
893 | 862 | band_index(sifted, b); |
894 | 863 | |
895 | 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 | 866 | if( p[xi] == 0 ) |
898 | 867 | unsifted[xi] = 0; |
899 | 868 | else{ |
... | ... | @@ -923,13 +892,13 @@ public: |
923 | 892 | T* temp = (T*)malloc(sizeof(T) * XY); |
924 | 893 | //initialize p |
925 | 894 | band_index(p, 0); |
926 | - for (unsigned j = 0; j < XY; j++){ | |
895 | + for (unsigned long long j = 0; j < XY; j++){ | |
927 | 896 | p[j] /= (T)Z(); |
928 | 897 | } |
929 | 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 | 900 | band_index(temp, i); |
932 | - for (unsigned j = 0; j < XY; j++){ | |
901 | + for (unsigned long long j = 0; j < XY; j++){ | |
933 | 902 | p[j] += temp[j]/(T)Z(); |
934 | 903 | } |
935 | 904 | } |
... | ... | @@ -966,54 +935,7 @@ public: |
966 | 935 | free(temp); |
967 | 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 | 939 | /// Crop a region of the image and save it to a new file. |
1018 | 940 | |
1019 | 941 | /// @param outfile is the file name for the new cropped image |
... | ... | @@ -1055,7 +977,7 @@ public: |
1055 | 977 | //for each band |
1056 | 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 | 982 | file.read((char *)(temp + y * samples), sizeof(T) * samples); |
1061 | 983 | file.seekg(jumpl, std::ios::cur); //go to the next band | ... | ... |
stim/envi/envi.h
... | ... | @@ -69,7 +69,7 @@ public: |
69 | 69 | } |
70 | 70 | |
71 | 71 | /// Returns the progress of the current processing operation as a percentage |
72 | - unsigned int progress(){ | |
72 | + double progress(){ | |
73 | 73 | |
74 | 74 | if(header.interleave == envi_header::BSQ){ //if the infile is bsq file |
75 | 75 | if(header.data_type ==envi_header::float32) |
... | ... | @@ -105,31 +105,29 @@ public: |
105 | 105 | } |
106 | 106 | |
107 | 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 | 110 | file = NULL; //set file to a NULL pointer |
111 | 111 | |
112 | 112 | if(header.interleave == envi_header::BSQ){ |
113 | 113 | if(header.data_type ==envi_header::float32) |
114 | - return(file = new bsq<float>()); | |
114 | + file = new bsq<float>(); | |
115 | 115 | else if(header.data_type == envi_header::float64) |
116 | - return(file = new bsq<double>()); | |
116 | + file = new bsq<double>(); | |
117 | 117 | } |
118 | 118 | else if(header.interleave == envi_header::BIP){ |
119 | 119 | if(header.data_type ==envi_header::float32) |
120 | - return(file = new bip<float>()); | |
120 | + file = new bip<float>(); | |
121 | 121 | else if(header.data_type == envi_header::float64) |
122 | - return(file = new bip<double>()); | |
122 | + file = new bip<double>(); | |
123 | 123 | } |
124 | 124 | else if(header.interleave == envi_header::BIL){ |
125 | 125 | if(header.data_type ==envi_header::float32) |
126 | - return(file = new bil<float>()); | |
126 | + file = new bil<float>(); | |
127 | 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 | 133 | /// Open a previously opened ENVI file |
... | ... | @@ -179,11 +177,13 @@ public: |
179 | 177 | /// @param filename is the name of the ENVI binary file |
180 | 178 | /// @param header is an ENVI header structure |
181 | 179 | bool open(std::string filename, stim::envi_header h){ |
182 | - allocate(); | |
180 | + | |
183 | 181 | |
184 | 182 | header = h; //store the header |
185 | 183 | fname = filename; //save the filename |
186 | 184 | |
185 | + allocate(); | |
186 | + | |
187 | 187 | return open(); //open the ENVI file; |
188 | 188 | |
189 | 189 | |
... | ... | @@ -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 | 298 | if(header.interleave == envi_header::BSQ){ //if the infile is bsq file |
299 | 299 | std::cout<<"ERROR: BSQ projection not supported"<<std::endl; |
300 | 300 | exit(1); |
... | ... | @@ -307,9 +307,9 @@ public: |
307 | 307 | |
308 | 308 | else if(header.interleave == envi_header::BIP){ //if the infile is bip file |
309 | 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 | 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 | 313 | else{ |
314 | 314 | std::cout<<"ERROR: unidentified data type"<<std::endl; |
315 | 315 | exit(1); |
... | ... | @@ -318,6 +318,8 @@ public: |
318 | 318 | |
319 | 319 | stim::envi_header out_hdr = header; |
320 | 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 | 323 | out_hdr.save(outfile + ".hdr"); //save the output header |
322 | 324 | } |
323 | 325 | |
... | ... | @@ -577,9 +579,9 @@ public: |
577 | 579 | { |
578 | 580 | |
579 | 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 | 585 | if( p[i] > 0 ) nnz++; |
584 | 586 | |
585 | 587 | //create a new header |
... | ... | @@ -625,12 +627,10 @@ public: |
625 | 627 | std::cout << "ERROR: unidentified file type" << std::endl; |
626 | 628 | exit(1); |
627 | 629 | } |
628 | - | |
629 | - | |
630 | 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 | 635 | //create a new header |
636 | 636 | envi_header new_header = header; |
... | ... | @@ -976,7 +976,7 @@ public: |
976 | 976 | /// @param ptr is a pointer to pre-allocated memory of size B*sizeof(T) |
977 | 977 | /// @param x is the x-coordinate of the spectrum |
978 | 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 | 981 | if(header.interleave == envi_header::BSQ){ //if the infile is bsq file |
982 | 982 | if(header.data_type ==envi_header::float32) |
... | ... | @@ -1015,7 +1015,7 @@ public: |
1015 | 1015 | |
1016 | 1016 | /// @param p is a pointer to an allocated region of memory at least X * Y * sizeof(T) in size. |
1017 | 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 | 1019 | if (header.interleave == envi_header::BSQ){ //if the infile is bsq file |
1020 | 1020 | if (header.data_type == envi_header::float32) |
1021 | 1021 | return ((bsq<float>*)file)->band_index((float*)ptr, b); | ... | ... |
stim/envi/envi_header.h
... | ... | @@ -23,10 +23,10 @@ struct envi_header |
23 | 23 | |
24 | 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 | 30 | std::string file_type; //should be "ENVI Standard" |
31 | 31 | |
32 | 32 | envi_header::dataType data_type; //data representation; common value is 4 (32-bit float) |
... | ... | @@ -81,7 +81,7 @@ struct envi_header |
81 | 81 | if(line.length() == 0) |
82 | 82 | return line; |
83 | 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 | 85 | for(start_i=0; start_i < line.length(); start_i++) |
86 | 86 | if(line[start_i] != 32) |
87 | 87 | { |
... | ... | @@ -307,7 +307,7 @@ struct envi_header |
307 | 307 | } |
308 | 308 | |
309 | 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 | 311 | if(wavelengths && bands != wavelengths) |
312 | 312 | { |
313 | 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 | 110 | \ No newline at end of file | ... | ... |
stim/image/CImg.h
... | ... | @@ -54,7 +54,7 @@ |
54 | 54 | |
55 | 55 | // Set version number of the library. |
56 | 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 | 2340 | char *_message; |
2341 | 2341 | CImgException() { _message = new char[1]; *_message = 0; } |
2342 | 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 | 2344 | const int size = std::strlen(e._message); |
2345 | 2345 | _message = new char[size + 1]; |
2346 | 2346 | std::strncpy(_message,e._message,size); |
... | ... | @@ -2364,7 +2364,7 @@ namespace cimg_library_suffixed { |
2364 | 2364 | char *_message; |
2365 | 2365 | CImgAbortException() { _message = new char[1]; *_message = 0; } |
2366 | 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 | 2368 | const int size = std::strlen(e._message); |
2369 | 2369 | _message = new char[size + 1]; |
2370 | 2370 | std::strncpy(_message,e._message,size); |
... | ... | @@ -2442,7 +2442,7 @@ namespace cimg_library_suffixed { |
2442 | 2442 | static bool is_inf(const T) { return false; } |
2443 | 2443 | static bool is_nan(const T) { return false; } |
2444 | 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 | 2446 | static T inf() { return max(); } |
2447 | 2447 | static T cut(const double val) { return val<(double)min()?min():val>(double)max()?max():(T)val; } |
2448 | 2448 | static const char* format() { return "%s"; } |
... | ... | @@ -13726,8 +13726,9 @@ namespace cimg_library_suffixed { |
13726 | 13726 | char *user_function; |
13727 | 13727 | |
13728 | 13728 | unsigned int mempos, mem_img_median, debug_indent, init_size, result_dim; |
13729 | + bool is_parallelizable, need_input_copy; | |
13729 | 13730 | double *result; |
13730 | - const char *const calling_function; | |
13731 | + const char *const calling_function, *s_op, *ss_op; | |
13731 | 13732 | typedef double (*mp_func)(_cimg_math_parser&); |
13732 | 13733 | |
13733 | 13734 | #define _cimg_mp_is_constant(arg) (memtype[arg]==1) // Is constant? |
... | ... | @@ -13737,12 +13738,14 @@ namespace cimg_library_suffixed { |
13737 | 13738 | #define _cimg_mp_is_vector(arg) (memtype[arg]>1) // Is vector? |
13738 | 13739 | #define _cimg_mp_vector_size(arg) (_cimg_mp_is_scalar(arg)?0U:(unsigned int)memtype[arg] - 1) // Vector size |
13739 | 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 | 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 | 13749 | #define _cimg_mp_constant(val) _cimg_mp_return(constant(val)) |
13747 | 13750 | #define _cimg_mp_scalar0(op) _cimg_mp_return(scalar0(op)) |
13748 | 13751 | #define _cimg_mp_scalar1(op,i1) _cimg_mp_return(scalar1(op,i1)) |
... | ... | @@ -13763,19 +13766,22 @@ namespace cimg_library_suffixed { |
13763 | 13766 | code(_code),imgin(img_input),listin(list_input?*list_input:CImgList<T>::const_empty()), |
13764 | 13767 | imgout(img_output?*img_output:CImg<T>::empty()),listout(list_output?*list_output:CImgList<T>::empty()), |
13765 | 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 | 13771 | if (!expression || !*expression) |
13769 | 13772 | throw CImgArgumentException("[_cimg_math_parser] " |
13770 | 13773 | "CImg<%s>::%s: Empty expression.", |
13771 | 13774 | pixel_type(),_cimg_mp_calling_function); |
13772 | 13775 | const char *_expression = expression; |
13773 | - while (*_expression && *_expression<=' ') ++_expression; | |
13776 | + while (*_expression && (*_expression<=' ' || *_expression==';')) ++_expression; | |
13774 | 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 | 13782 | // Ease the retrieval of previous non-space characters afterwards. |
13777 | 13783 | pexpr.assign(expr._width); |
13778 | - const char *ps; | |
13784 | + | |
13779 | 13785 | char c, *pe = pexpr._data; |
13780 | 13786 | for (ps = expr._data, c = ' '; *ps; ++ps) { |
13781 | 13787 | if (*ps!=' ') c = *ps; |
... | ... | @@ -13854,6 +13860,7 @@ namespace cimg_library_suffixed { |
13854 | 13860 | // [11] = xm, [12] = ym, [13] = zm, [14] = cm, [15] = xM, [16] = yM, [17] = zM, [18]=cM, [19]=i0...[28]=i9, |
13855 | 13861 | |
13856 | 13862 | // Compile expression into a serie of opcodes. |
13863 | + s_op = ""; ss_op = expr._data; | |
13857 | 13864 | const unsigned int ind_result = compile(expr._data,expr._data + expr._width - 1,0,0); |
13858 | 13865 | p_code_end = code.end(); |
13859 | 13866 | |
... | ... | @@ -13867,6 +13874,7 @@ namespace cimg_library_suffixed { |
13867 | 13874 | reserved_label.assign(); |
13868 | 13875 | expr.assign(); |
13869 | 13876 | pexpr.assign(); |
13877 | + opcode.assign(); | |
13870 | 13878 | opcode._width = opcode._depth = opcode._spectrum = 1; |
13871 | 13879 | opcode._is_shared = true; |
13872 | 13880 | |
... | ... | @@ -13888,7 +13896,7 @@ namespace cimg_library_suffixed { |
13888 | 13896 | imgin(CImg<T>::const_empty()),listin(CImgList<T>::const_empty()), |
13889 | 13897 | imgout(CImg<T>::empty()),listout(CImgList<T>::empty()), |
13890 | 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 | 13900 | mem.assign(1 + _cimg_mp_c,1,1,1,0); // Allow to skip 'is_empty?' test in operator()() |
13893 | 13901 | result = mem._data; |
13894 | 13902 | } |
... | ... | @@ -13896,8 +13904,9 @@ namespace cimg_library_suffixed { |
13896 | 13904 | _cimg_math_parser(const _cimg_math_parser& mp): |
13897 | 13905 | mem(mp.mem),code(mp.code),p_code_begin(mp.p_code_begin),p_code_end(mp.p_code_end), |
13898 | 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 | 13910 | #ifdef cimg_use_openmp |
13902 | 13911 | mem[17] = omp_get_thread_num(); |
13903 | 13912 | #endif |
... | ... | @@ -13905,30 +13914,8 @@ namespace cimg_library_suffixed { |
13905 | 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 | 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 | 13919 | if (depth>256) { |
13933 | 13920 | cimg::strellipsize(expr,64); |
13934 | 13921 | throw CImgArgumentException("[_cimg_math_parser] " |
... | ... | @@ -13954,10 +13941,15 @@ namespace cimg_library_suffixed { |
13954 | 13941 | if (se<=ss || !*ss) { |
13955 | 13942 | cimg::strellipsize(expr,64); |
13956 | 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 | 13953 | const unsigned int depth1 = depth + 1; |
13962 | 13954 | unsigned int pos, p1, p2, p3, arg1, arg2, arg3, arg4, arg5, arg6; |
13963 | 13955 | char |
... | ... | @@ -13966,7 +13958,6 @@ namespace cimg_library_suffixed { |
13966 | 13958 | *const ss5 = ss + 5, *const ss6 = ss + 6, *const ss7 = ss + 7, *const ss8 = ss + 8, |
13967 | 13959 | *s, *ps, *ns, *s0, *s1, *s2, *s3, sep = 0, end = 0; |
13968 | 13960 | double val, val1, val2; |
13969 | - const char *s_op; | |
13970 | 13961 | mp_func op; |
13971 | 13962 | |
13972 | 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 | 14013 | if (reserved_label['i']!=~0U) _cimg_mp_return(reserved_label['i']); |
14023 | 14014 | _cimg_mp_scalar0(mp_i); |
14024 | 14015 | case 'I' : |
14016 | + _cimg_mp_op("Variable 'I'"); | |
14025 | 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 | 14020 | pos = vector(imgin._spectrum); |
14028 | 14021 | CImg<uptrT>::vector((uptrT)mp_Joff,pos,0,0).move_to(code); |
14029 | 14022 | _cimg_mp_return(pos); |
14030 | 14023 | case 'R' : |
14031 | 14024 | if (reserved_label['R']!=~0U) _cimg_mp_return(reserved_label['R']); |
14025 | + need_input_copy = true; | |
14032 | 14026 | _cimg_mp_scalar6(mp_ixyzc,_cimg_mp_x,_cimg_mp_y,_cimg_mp_z,0,0,0); |
14033 | 14027 | case 'G' : |
14034 | 14028 | if (reserved_label['G']!=~0U) _cimg_mp_return(reserved_label['G']); |
14029 | + need_input_copy = true; | |
14035 | 14030 | _cimg_mp_scalar6(mp_ixyzc,_cimg_mp_x,_cimg_mp_y,_cimg_mp_z,1,0,0); |
14036 | 14031 | case 'B' : |
14037 | 14032 | if (reserved_label['B']!=~0U) _cimg_mp_return(reserved_label['B']); |
14033 | + need_input_copy = true; | |
14038 | 14034 | _cimg_mp_scalar6(mp_ixyzc,_cimg_mp_x,_cimg_mp_y,_cimg_mp_z,2,0,0); |
14039 | 14035 | case 'A' : |
14040 | 14036 | if (reserved_label['A']!=~0U) _cimg_mp_return(reserved_label['A']); |
14037 | + need_input_copy = true; | |
14041 | 14038 | _cimg_mp_scalar6(mp_ixyzc,_cimg_mp_x,_cimg_mp_y,_cimg_mp_z,3,0,0); |
14042 | 14039 | } |
14043 | 14040 | else if (ss2==se) { // Two-chars variable |
... | ... | @@ -14048,6 +14045,7 @@ namespace cimg_library_suffixed { |
14048 | 14045 | if (*ss1>='0' && *ss1<='9') { // i0...i9 |
14049 | 14046 | pos = 19 + *ss1 - '0'; |
14050 | 14047 | if (reserved_label[pos]!=~0U) _cimg_mp_return(reserved_label[pos]); |
14048 | + need_input_copy = true; | |
14051 | 14049 | _cimg_mp_scalar6(mp_ixyzc,_cimg_mp_x,_cimg_mp_y,_cimg_mp_z,pos - 19,0,0); |
14052 | 14050 | } |
14053 | 14051 | switch (*ss1) { |
... | ... | @@ -14109,7 +14107,7 @@ namespace cimg_library_suffixed { |
14109 | 14107 | cimg::strpare(variable_name); |
14110 | 14108 | const unsigned int l_variable_name = (unsigned int)std::strlen(variable_name); |
14111 | 14109 | char *const ve1 = ss + l_variable_name - 1; |
14112 | - s_op = "Operator '='"; | |
14110 | + _cimg_mp_op("Operator '='"); | |
14113 | 14111 | |
14114 | 14112 | // Assign image value (direct). |
14115 | 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 | 14115 | is_relative = *ss=='j' || *ss=='J'; |
14118 | 14116 | |
14119 | 14117 | if (*ss1=='[' && *ve1==']') { // i/j/I/J[_#ind,offset] = value |
14118 | + is_parallelizable = false; | |
14120 | 14119 | if (*ss2=='#') { // Index specified |
14121 | 14120 | s0 = ss3; while (s0<ve1 && (*s0!=',' || level[s0 - expr._data]!=clevel1)) ++s0; |
14122 | 14121 | p1 = compile(ss3,s0++,depth1,0); |
14122 | + _cimg_mp_check_list(true); | |
14123 | 14123 | } else { p1 = ~0U; s0 = ss2; } |
14124 | 14124 | arg1 = compile(s0,ve1,depth1,0); // Offset |
14125 | 14125 | arg2 = compile(s + 1,se,depth1,0); // Value to assign |
... | ... | @@ -14130,9 +14130,9 @@ namespace cimg_library_suffixed { |
14130 | 14130 | p3 = (unsigned int)cimg::mod((int)mem[p1],listin.width()); |
14131 | 14131 | p2 = listin[p3]._spectrum; |
14132 | 14132 | } |
14133 | - _cimg_mp_check_vector0(p2,s_op); | |
14133 | + _cimg_mp_check_vector0(p2); | |
14134 | 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 | 14137 | if (p_ref) { |
14138 | 14138 | *p_ref = _cimg_mp_is_vector(arg2)?4:2; |
... | ... | @@ -14172,9 +14172,11 @@ namespace cimg_library_suffixed { |
14172 | 14172 | } |
14173 | 14173 | |
14174 | 14174 | if (*ss1=='(' && *ve1==')') { // i/j/I/J(_#ind,_x,_y,_z,_c) = value |
14175 | + is_parallelizable = false; | |
14175 | 14176 | if (*ss2=='#') { // Index specified |
14176 | 14177 | s0 = ss3; while (s0<ve1 && (*s0!=',' || level[s0 - expr._data]!=clevel1)) ++s0; |
14177 | 14178 | p1 = compile(ss3,s0++,depth1,0); |
14179 | + _cimg_mp_check_list(true); | |
14178 | 14180 | } else { p1 = ~0U; s0 = ss2; } |
14179 | 14181 | arg1 = is_relative?0U:(unsigned int)_cimg_mp_x; |
14180 | 14182 | arg2 = is_relative?0U:(unsigned int)_cimg_mp_y; |
... | ... | @@ -14184,9 +14186,9 @@ namespace cimg_library_suffixed { |
14184 | 14186 | if (s0<ve1) { // X or [ X,_Y,_Z,_C ] |
14185 | 14187 | s1 = s0; while (s1<ve1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1; |
14186 | 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 | 14190 | p2 = _cimg_mp_vector_size(arg1); // Vector size |
14189 | - arg1 = arg1 + 1; | |
14191 | + ++arg1; | |
14190 | 14192 | if (p2>1) { |
14191 | 14193 | arg2 = arg1 + 1; |
14192 | 14194 | if (p2>2) { |
... | ... | @@ -14212,9 +14214,9 @@ namespace cimg_library_suffixed { |
14212 | 14214 | p3 = (unsigned int)cimg::mod((int)mem[p1],listin.width()); |
14213 | 14215 | p2 = listin[p3]._spectrum; |
14214 | 14216 | } |
14215 | - _cimg_mp_check_vector0(p2,s_op); | |
14217 | + _cimg_mp_check_vector0(p2); | |
14216 | 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 | 14221 | if (p_ref) { |
14220 | 14222 | *p_ref = _cimg_mp_is_vector(arg5)?5:3; |
... | ... | @@ -14272,7 +14274,7 @@ namespace cimg_library_suffixed { |
14272 | 14274 | arg1 = ~0U; // Vector slot |
14273 | 14275 | arg2 = compile(++s0,ve1,depth1,0); // Index |
14274 | 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 | 14279 | if (variable_name[1]) { // Multi-char variable |
14278 | 14280 | cimglist_for(variable_def,i) if (!std::strcmp(variable_name,variable_def[i])) { |
... | ... | @@ -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 | 14314 | s0 = ve1; while (s0>ss && *s0!='(') --s0; |
14313 | 14315 | is_sth = std::strncmp(variable_name,"debug(",6) && |
14314 | 14316 | std::strncmp(variable_name,"print(",6); // is_valid_function_name? |
... | ... | @@ -14454,7 +14456,7 @@ namespace cimg_library_suffixed { |
14454 | 14456 | } |
14455 | 14457 | |
14456 | 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 | 14460 | if (_cimg_mp_is_vector(arg1)) { // Vector |
14459 | 14461 | if (_cimg_mp_is_vector(arg2)) // From vector |
14460 | 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 | 14480 | arg2 = compile(s + 1,se,depth1,0); // Value to assign |
14479 | 14481 | |
14480 | 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 | 14484 | arg3 = ref[1]; // Vector slot |
14483 | 14485 | arg4 = ref[2]; // Index |
14484 | 14486 | if (p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int)); |
... | ... | @@ -14488,7 +14490,8 @@ namespace cimg_library_suffixed { |
14488 | 14490 | } |
14489 | 14491 | |
14490 | 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 | 14495 | p1 = ref[1]; // Index |
14493 | 14496 | is_relative = (bool)ref[2]; |
14494 | 14497 | arg3 = ref[3]; // Offset |
... | ... | @@ -14506,7 +14509,8 @@ namespace cimg_library_suffixed { |
14506 | 14509 | } |
14507 | 14510 | |
14508 | 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 | 14514 | p1 = ref[1]; // Index |
14511 | 14515 | is_relative = (bool)ref[2]; |
14512 | 14516 | arg3 = ref[3]; // X |
... | ... | @@ -14527,7 +14531,8 @@ namespace cimg_library_suffixed { |
14527 | 14531 | } |
14528 | 14532 | |
14529 | 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 | 14536 | p1 = ref[1]; // Index |
14532 | 14537 | is_relative = (bool)ref[2]; |
14533 | 14538 | arg3 = ref[3]; // Offset |
... | ... | @@ -14553,7 +14558,8 @@ namespace cimg_library_suffixed { |
14553 | 14558 | } |
14554 | 14559 | |
14555 | 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 | 14563 | p1 = ref[1]; // Index |
14558 | 14564 | is_relative = (bool)ref[2]; |
14559 | 14565 | arg3 = ref[3]; // X |
... | ... | @@ -14581,7 +14587,7 @@ namespace cimg_library_suffixed { |
14581 | 14587 | } |
14582 | 14588 | |
14583 | 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 | 14591 | if (_cimg_mp_is_vector(arg2)) // From vector |
14586 | 14592 | CImg<uptrT>::vector((uptrT)mp_vector_copy,arg1,arg2,(uptrT)_cimg_mp_vector_size(arg1)). |
14587 | 14593 | move_to(code); |
... | ... | @@ -14592,7 +14598,7 @@ namespace cimg_library_suffixed { |
14592 | 14598 | } |
14593 | 14599 | |
14594 | 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 | 14602 | CImg<uptrT>::vector((uptrT)mp_copy,arg1,arg2).move_to(code); |
14597 | 14603 | _cimg_mp_return(arg1); |
14598 | 14604 | |
... | ... | @@ -14615,28 +14621,28 @@ namespace cimg_library_suffixed { |
14615 | 14621 | for (s = se2, ps = se3, ns = ps - 1; s>ss1; --s, --ps, --ns) // Here, ns = ps - 1 |
14616 | 14622 | if (*s=='=' && (*ps=='*' || *ps=='/' || *ps=='^') && *ns==*ps && |
14617 | 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 | 14626 | ref.assign(7); |
14621 | 14627 | arg1 = compile(ss,ns,depth1,ref); // Vector slot |
14622 | 14628 | arg2 = compile(s + 1,se,depth1,0); // Right operand |
14623 | 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 | 14633 | if (_cimg_mp_is_vector(arg2)) { // Complex **= complex or Matrix **= matrix |
14628 | 14634 | if (*ps=='*') { |
14629 | 14635 | if (_cimg_mp_vector_size(arg1)==2 && _cimg_mp_vector_size(arg2)==2) |
14630 | 14636 | CImg<uptrT>::vector((uptrT)mp_complex_mul,arg1,arg1,arg2).move_to(code); |
14631 | 14637 | else { |
14632 | - _cimg_mp_check_matrix_square(arg2,2,s_op); | |
14638 | + _cimg_mp_check_matrix_square(arg2,2); | |
14633 | 14639 | p3 = _cimg_mp_vector_size(arg1); |
14634 | 14640 | p2 = (unsigned int)std::sqrt((float)_cimg_mp_vector_size(arg2)); |
14635 | 14641 | p1 = p3/p2; |
14636 | 14642 | if (p1*p2!=p3) { |
14637 | 14643 | *se = saved_char; cimg::strellipsize(expr,64); |
14638 | 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 | 14646 | "('%s' and '%s') do not match, in expression '%s%s%s'.", |
14641 | 14647 | pixel_type(),_cimg_mp_calling_function,s_op, |
14642 | 14648 | s_type(arg1)._data,s_type(arg2)._data, |
... | ... | @@ -14651,16 +14657,14 @@ namespace cimg_library_suffixed { |
14651 | 14657 | else |
14652 | 14658 | CImg<uptrT>::vector((uptrT)mp_complex_pow_vv,arg1,arg1,arg2).move_to(code); |
14653 | 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 | 14665 | // Write computed value back in image if necessary. |
14663 | 14666 | if (*ref==4) { // Image value (vector): I/J[_#ind,off] **= value |
14667 | + is_parallelizable = false; | |
14664 | 14668 | p1 = ref[1]; // Index |
14665 | 14669 | is_relative = (bool)ref[2]; |
14666 | 14670 | arg3 = ref[3]; // Offset |
... | ... | @@ -14676,6 +14680,7 @@ namespace cimg_library_suffixed { |
14676 | 14680 | } |
14677 | 14681 | |
14678 | 14682 | } else if (*ref==5) { // Image value (vector): I/J(_#ind,_x,_y,_z,_c) **= value |
14683 | + is_parallelizable = false; | |
14679 | 14684 | p1 = ref[1]; // Index |
14680 | 14685 | is_relative = (bool)ref[2]; |
14681 | 14686 | arg3 = ref[3]; // X |
... | ... | @@ -14702,16 +14707,16 @@ namespace cimg_library_suffixed { |
14702 | 14707 | (*ps=='>' && *ns=='>') || (*ps=='<' && *ns=='<')) && |
14703 | 14708 | level[s - expr._data]==clevel) { // Self-operators (+=,-=,*=,/=,%=,>>=,<<=,&=,^=,|=) |
14704 | 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 | 14721 | s1 = *ps=='>' || *ps=='<'?ns:ps; |
14717 | 14722 | |
... | ... | @@ -14725,7 +14730,7 @@ namespace cimg_library_suffixed { |
14725 | 14730 | } |
14726 | 14731 | |
14727 | 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 | 14734 | arg3 = ref[1]; // Vector slot |
14730 | 14735 | arg4 = ref[2]; // Index |
14731 | 14736 | if (p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int)); |
... | ... | @@ -14736,7 +14741,8 @@ namespace cimg_library_suffixed { |
14736 | 14741 | } |
14737 | 14742 | |
14738 | 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 | 14746 | p1 = ref[1]; // Index |
14741 | 14747 | is_relative = (bool)ref[2]; |
14742 | 14748 | arg3 = ref[3]; // Offset |
... | ... | @@ -14755,7 +14761,8 @@ namespace cimg_library_suffixed { |
14755 | 14761 | } |
14756 | 14762 | |
14757 | 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 | 14766 | p1 = ref[1]; // Index |
14760 | 14767 | is_relative = (bool)ref[2]; |
14761 | 14768 | arg3 = ref[3]; // X |
... | ... | @@ -14777,17 +14784,13 @@ namespace cimg_library_suffixed { |
14777 | 14784 | } |
14778 | 14785 | |
14779 | 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 | 14789 | p1 = ref[1]; // Index |
14782 | 14790 | is_relative = (bool)ref[2]; |
14783 | 14791 | arg3 = ref[3]; // Offset |
14784 | 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 | 14794 | if (p1!=~0U) { |
14792 | 14795 | if (!listout) _cimg_mp_return(arg1); |
14793 | 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 | 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 | 14809 | p1 = ref[1]; // Index |
14806 | 14810 | is_relative = (bool)ref[2]; |
14807 | 14811 | arg3 = ref[3]; // X |
14808 | 14812 | arg4 = ref[4]; // Y |
14809 | 14813 | arg5 = ref[5]; // Z |
14810 | 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 | 14816 | if (p1!=~0U) { |
14818 | 14817 | if (!listout) _cimg_mp_return(arg1); |
14819 | 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 | 14826 | } |
14828 | 14827 | |
14829 | 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 | 14832 | _cimg_mp_return(arg1); |
14838 | 14833 | } |
14839 | 14834 | |
14840 | 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 | 14837 | CImg<uptrT>::vector((uptrT)op,arg1,arg2).move_to(code); |
14843 | 14838 | _cimg_mp_return(arg1); |
14844 | 14839 | } |
... | ... | @@ -14857,17 +14852,19 @@ namespace cimg_library_suffixed { |
14857 | 14852 | |
14858 | 14853 | for (s = ss1; s<se1; ++s) |
14859 | 14854 | if (*s=='?' && level[s - expr._data]==clevel) { // Ternary operator 'cond?expr1:expr2' |
14860 | - s_op = "Operator '?:'"; | |
14855 | + _cimg_mp_op("Operator '?:'"); | |
14861 | 14856 | s1 = s + 1; while (s1<se1 && (*s1!=':' || level[s1 - expr._data]!=clevel)) ++s1; |
14862 | 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 | 14863 | p2 = code._width; |
14864 | 14864 | arg2 = compile(s + 1,*s1!=':'?se:s1,depth1,0); |
14865 | 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 | 14868 | arg4 = _cimg_mp_is_vector(arg2)?_cimg_mp_vector_size(arg2):0; // Output vector size (or 0 if scalar) |
14872 | 14869 | if (arg4) pos = vector(arg4); else pos = scalar(); |
14873 | 14870 | CImg<uptrT>::vector((uptrT)mp_if,pos,arg1,arg2,arg3, |
... | ... | @@ -14877,12 +14874,12 @@ namespace cimg_library_suffixed { |
14877 | 14874 | |
14878 | 14875 | for (s = se3, ns = se2; s>ss; --s, --ns) |
14879 | 14876 | if (*s=='|' && *ns=='|' && level[s - expr._data]==clevel) { // Logical or ('||') |
14880 | - s_op = "Operator '||'"; | |
14877 | + _cimg_mp_op("Operator '||'"); | |
14881 | 14878 | arg1 = compile(ss,s,depth1,0); |
14882 | 14879 | p2 = code._width; |
14883 | 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 | 14883 | if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) |
14887 | 14884 | _cimg_mp_constant(mem[arg1] || mem[arg2]); |
14888 | 14885 | pos = scalar(); |
... | ... | @@ -14893,12 +14890,12 @@ namespace cimg_library_suffixed { |
14893 | 14890 | |
14894 | 14891 | for (s = se3, ns = se2; s>ss; --s, --ns) |
14895 | 14892 | if (*s=='&' && *ns=='&' && level[s - expr._data]==clevel) { // Logical and ('&&') |
14896 | - s_op = "Operator '&&'"; | |
14893 | + _cimg_mp_op("Operator '&&'"); | |
14897 | 14894 | arg1 = compile(ss,s,depth1,0); |
14898 | 14895 | p2 = code._width; |
14899 | 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 | 14899 | if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) |
14903 | 14900 | _cimg_mp_constant(mem[arg1] && mem[arg2]); |
14904 | 14901 | pos = scalar(); |
... | ... | @@ -14909,9 +14906,10 @@ namespace cimg_library_suffixed { |
14909 | 14906 | |
14910 | 14907 | for (s = se2; s>ss; --s) |
14911 | 14908 | if (*s=='|' && level[s - expr._data]==clevel) { // Bitwise or ('|') |
14909 | + _cimg_mp_op("Operator '|'"); | |
14912 | 14910 | arg1 = compile(ss,s,depth1,0); |
14913 | 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 | 14913 | if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_bitwise_or,arg1,arg2); |
14916 | 14914 | if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_bitwise_or,arg1,arg2); |
14917 | 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 | 14920 | |
14923 | 14921 | for (s = se2; s>ss; --s) |
14924 | 14922 | if (*s=='&' && level[s - expr._data]==clevel) { // Bitwise and ('&') |
14923 | + _cimg_mp_op("Operator '&'"); | |
14925 | 14924 | arg1 = compile(ss,s,depth1,0); |
14926 | 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 | 14927 | if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_bitwise_and,arg1,arg2); |
14929 | 14928 | if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_bitwise_and,arg1,arg2); |
14930 | 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 | 14934 | |
14936 | 14935 | for (s = se3, ns = se2; s>ss; --s, --ns) |
14937 | 14936 | if (*s=='!' && *ns=='=' && level[s - expr._data]==clevel) { // Not equal to ('!=') |
14937 | + _cimg_mp_op("Operator '!='"); | |
14938 | 14938 | arg1 = compile(ss,s,depth1,0); |
14939 | 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 | 14941 | if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_neq,arg1,arg2); |
14942 | 14942 | if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_neq,arg1,arg2); |
14943 | 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 | 14947 | |
14948 | 14948 | for (s = se3, ns = se2; s>ss; --s, --ns) |
14949 | 14949 | if (*s=='=' && *ns=='=' && level[s - expr._data]==clevel) { // Equal to ('==') |
14950 | + _cimg_mp_op("Operator '=='"); | |
14950 | 14951 | arg1 = compile(ss,s,depth1,0); |
14951 | 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 | 14954 | if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_eq,arg1,arg2); |
14954 | 14955 | if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_eq,arg1,arg2); |
14955 | 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 | 14960 | |
14960 | 14961 | for (s = se3, ns = se2; s>ss; --s, --ns) |
14961 | 14962 | if (*s=='<' && *ns=='=' && level[s - expr._data]==clevel) { // Less or equal than ('<=') |
14963 | + _cimg_mp_op("Operator '<='"); | |
14962 | 14964 | arg1 = compile(ss,s,depth1,0); |
14963 | 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 | 14967 | if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_lte,arg1,arg2); |
14966 | 14968 | if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_lte,arg1,arg2); |
14967 | 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 | 14973 | |
14972 | 14974 | for (s = se3, ns = se2; s>ss; --s, --ns) |
14973 | 14975 | if (*s=='>' && *ns=='=' && level[s - expr._data]==clevel) { // Greater or equal than ('>=') |
14976 | + _cimg_mp_op("Operator '>='"); | |
14974 | 14977 | arg1 = compile(ss,s,depth1,0); |
14975 | 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 | 14980 | if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_gte,arg1,arg2); |
14978 | 14981 | if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_gte,arg1,arg2); |
14979 | 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 | 14986 | |
14984 | 14987 | for (s = se2, ns = se1, ps = se3; s>ss; --s, --ns, --ps) |
14985 | 14988 | if (*s=='<' && *ns!='<' && *ps!='<' && level[s - expr._data]==clevel) { // Less than ('<') |
14989 | + _cimg_mp_op("Operator '<'"); | |
14986 | 14990 | arg1 = compile(ss,s,depth1,0); |
14987 | 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 | 14993 | if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_lt,arg1,arg2); |
14990 | 14994 | if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_lt,arg1,arg2); |
14991 | 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 | 14999 | |
14996 | 15000 | for (s = se2, ns = se1, ps = se3; s>ss; --s, --ns, --ps) |
14997 | 15001 | if (*s=='>' && *ns!='>' && *ps!='>' && level[s - expr._data]==clevel) { // Greather than ('>') |
15002 | + _cimg_mp_op("Operator '>'"); | |
14998 | 15003 | arg1 = compile(ss,s,depth1,0); |
14999 | 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 | 15006 | if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_gt,arg1,arg2); |
15002 | 15007 | if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_gt,arg1,arg2); |
15003 | 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 | 15012 | |
15008 | 15013 | for (s = se3, ns = se2; s>ss; --s, --ns) |
15009 | 15014 | if (*s=='<' && *ns=='<' && level[s - expr._data]==clevel) { // Left bit shift ('<<') |
15015 | + _cimg_mp_op("Operator '<<'"); | |
15010 | 15016 | arg1 = compile(ss,s,depth1,0); |
15011 | 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 | 15019 | if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) |
15014 | 15020 | _cimg_mp_vector2_vv(mp_bitwise_left_shift,arg1,arg2); |
15015 | 15021 | if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) |
... | ... | @@ -15023,9 +15029,10 @@ namespace cimg_library_suffixed { |
15023 | 15029 | |
15024 | 15030 | for (s = se3, ns = se2; s>ss; --s, --ns) |
15025 | 15031 | if (*s=='>' && *ns=='>' && level[s - expr._data]==clevel) { // Right bit shift ('>>') |
15032 | + _cimg_mp_op("Operator '>>'"); | |
15026 | 15033 | arg1 = compile(ss,s,depth1,0); |
15027 | 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 | 15036 | if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) |
15030 | 15037 | _cimg_mp_vector2_vv(mp_bitwise_right_shift,arg1,arg2); |
15031 | 15038 | if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) |
... | ... | @@ -15043,9 +15050,10 @@ namespace cimg_library_suffixed { |
15043 | 15050 | (*ps!='e' || !(ps - pexpr._data>ss - expr._data && (*(ps - 1)=='.' || (*(ps - 1)>='0' && |
15044 | 15051 | *(ps - 1)<='9')))) && |
15045 | 15052 | level[s - expr._data]==clevel) { // Addition ('+') |
15053 | + _cimg_mp_op("Operator '+'"); | |
15046 | 15054 | arg1 = compile(ss,s,depth1,0); |
15047 | 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 | 15057 | if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_add,arg1,arg2); |
15050 | 15058 | if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_add,arg1,arg2); |
15051 | 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 | 15069 | (*ps!='e' || !(ps - pexpr._data>ss - expr._data && (*(ps - 1)=='.' || (*(ps - 1)>='0' && |
15062 | 15070 | *(ps - 1)<='9')))) && |
15063 | 15071 | level[s - expr._data]==clevel) { // Subtraction ('-') |
15072 | + _cimg_mp_op("Operator '-'"); | |
15064 | 15073 | arg1 = compile(ss,s,depth1,0); |
15065 | 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 | 15076 | if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_sub,arg1,arg2); |
15068 | 15077 | if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_sub,arg1,arg2); |
15069 | 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 | 15083 | |
15075 | 15084 | for (s = se3, ns = se2; s>ss; --s, --ns) |
15076 | 15085 | if (*s=='*' && *ns=='*' && level[s - expr._data]==clevel) { // Complex/matrix multiplication ('**') |
15077 | - s_op = "Operator '**'"; | |
15086 | + _cimg_mp_op("Operator '**'"); | |
15078 | 15087 | arg1 = compile(ss,s,depth1,0); |
15079 | 15088 | arg2 = compile(s + 2,se,depth1,0); |
15080 | 15089 | if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) { |
... | ... | @@ -15089,7 +15098,7 @@ namespace cimg_library_suffixed { |
15089 | 15098 | if (arg4*p2!=p1) { |
15090 | 15099 | *se = saved_char; cimg::strellipsize(expr,64); |
15091 | 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 | 15102 | "('%s' and '%s') do not match, in expression '%s%s%s'.", |
15094 | 15103 | pixel_type(),_cimg_mp_calling_function,s_op, |
15095 | 15104 | s_type(arg1)._data,s_type(arg2)._data, |
... | ... | @@ -15110,11 +15119,11 @@ namespace cimg_library_suffixed { |
15110 | 15119 | |
15111 | 15120 | for (s = se3, ns = se2; s>ss; --s, --ns) |
15112 | 15121 | if (*s=='/' && *ns=='/' && level[s - expr._data]==clevel) { // Complex division ('//') |
15113 | - s_op = "Operator '//'"; | |
15122 | + _cimg_mp_op("Operator '//'"); | |
15114 | 15123 | arg1 = compile(ss,s,depth1,0); |
15115 | 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 | 15127 | if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) { |
15119 | 15128 | pos = vector(2); |
15120 | 15129 | CImg<uptrT>::vector((uptrT)mp_complex_div_vv,pos,arg1,arg2).move_to(code); |
... | ... | @@ -15131,9 +15140,10 @@ namespace cimg_library_suffixed { |
15131 | 15140 | } |
15132 | 15141 | |
15133 | 15142 | for (s = se2; s>ss; --s) if (*s=='*' && level[s - expr._data]==clevel) { // Multiplication ('*') |
15143 | + _cimg_mp_op("Operator '*'"); | |
15134 | 15144 | arg1 = compile(ss,s,depth1,0); |
15135 | 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 | 15147 | if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_mul,arg1,arg2); |
15138 | 15148 | if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_mul,arg1,arg2); |
15139 | 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 | 15153 | |
15144 | 15154 | |
15145 | 15155 | for (s = se2; s>ss; --s) if (*s=='/' && level[s - expr._data]==clevel) { // Division ('/') |
15156 | + _cimg_mp_op("Operator '/'"); | |
15146 | 15157 | arg1 = compile(ss,s,depth1,0); |
15147 | 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 | 15160 | if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_div,arg1,arg2); |
15150 | 15161 | if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_div,arg1,arg2); |
15151 | 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 | 15166 | |
15156 | 15167 | for (s = se2, ns = se1; s>ss; --s, --ns) |
15157 | 15168 | if (*s=='%' && *ns!='^' && level[s - expr._data]==clevel) { // Modulo ('%') |
15169 | + _cimg_mp_op("Operator '%'"); | |
15158 | 15170 | arg1 = compile(ss,s,depth1,0); |
15159 | 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 | 15173 | if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_modulo,arg1,arg2); |
15162 | 15174 | if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_modulo,arg1,arg2); |
15163 | 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 | 15179 | } |
15168 | 15180 | |
15169 | 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 | 15184 | _cimg_mp_return(compile(ss1,se,depth1,0)); |
15185 | + } | |
15172 | 15186 | |
15173 | 15187 | if (*ss=='-' && (*ss1!='-' || (ss2<se && *ss2>='0' && *ss2<='9'))) { // Unary minus ('-') |
15188 | + _cimg_mp_op("Operator '-'"); | |
15174 | 15189 | arg1 = compile(ss1,se,depth1,0); |
15175 | 15190 | if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_minus,arg1); |
15176 | 15191 | if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(-mem[arg1]); |
... | ... | @@ -15178,6 +15193,7 @@ namespace cimg_library_suffixed { |
15178 | 15193 | } |
15179 | 15194 | |
15180 | 15195 | if (*ss=='!') { // Logical not ('!') |
15196 | + _cimg_mp_op("Operator '!'"); | |
15181 | 15197 | arg1 = compile(ss1,se,depth1,0); |
15182 | 15198 | if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_logical_not,arg1); |
15183 | 15199 | if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(!mem[arg1]); |
... | ... | @@ -15185,6 +15201,7 @@ namespace cimg_library_suffixed { |
15185 | 15201 | } |
15186 | 15202 | |
15187 | 15203 | if (*ss=='~') { // Bitwise not ('~') |
15204 | + _cimg_mp_op("Operator '~'"); | |
15188 | 15205 | arg1 = compile(ss1,se,depth1,0); |
15189 | 15206 | if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_bitwise_not,arg1); |
15190 | 15207 | if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(~(unsigned long)mem[arg1]); |
... | ... | @@ -15194,11 +15211,11 @@ namespace cimg_library_suffixed { |
15194 | 15211 | |
15195 | 15212 | for (s = se3, ns = se2; s>ss; --s, --ns) |
15196 | 15213 | if (*s=='^' && *ns=='^' && level[s - expr._data]==clevel) { // Complex power ('^^') |
15197 | - s_op = "Operator '^^'"; | |
15214 | + _cimg_mp_op("Operator '^^'"); | |
15198 | 15215 | arg1 = compile(ss,s,depth1,0); |
15199 | 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 | 15219 | pos = (_cimg_mp_is_vector(arg1) || _cimg_mp_is_vector(arg2))?vector(2):0; |
15203 | 15220 | if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) { |
15204 | 15221 | CImg<uptrT>::vector((uptrT)mp_complex_pow_vv,pos,arg1,arg2).move_to(code); |
... | ... | @@ -15226,9 +15243,10 @@ namespace cimg_library_suffixed { |
15226 | 15243 | |
15227 | 15244 | for (s = se2; s>ss; --s) |
15228 | 15245 | if (*s=='^' && level[s - expr._data]==clevel) { // Power ('^') |
15246 | + _cimg_mp_op("Operator '^'"); | |
15229 | 15247 | arg1 = compile(ss,s,depth1,0); |
15230 | 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 | 15250 | if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_pow,arg1,arg2); |
15233 | 15251 | if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_pow,arg1,arg2); |
15234 | 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 | 15264 | |
15247 | 15265 | is_sth = ss1<se1 && (*ss=='+' || *ss=='-') && *ss1==*ss; // is pre-? |
15248 | 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 | 15274 | ref.assign(7); |
15253 | 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 | 15296 | } |
15275 | 15297 | |
15276 | 15298 | if (*ref==2) { // Image value (scalar): i/j[_#ind,off]++ |
15299 | + is_parallelizable = false; | |
15277 | 15300 | p1 = ref[1]; // Index |
15278 | 15301 | is_relative = (bool)ref[2]; |
15279 | 15302 | arg3 = ref[3]; // Offset |
... | ... | @@ -15292,6 +15315,7 @@ namespace cimg_library_suffixed { |
15292 | 15315 | } |
15293 | 15316 | |
15294 | 15317 | if (*ref==3) { // Image value (scalar): i/j(_#ind,_x,_y,_z,_c)++ |
15318 | + is_parallelizable = false; | |
15295 | 15319 | p1 = ref[1]; // Index |
15296 | 15320 | is_relative = (bool)ref[2]; |
15297 | 15321 | arg3 = ref[3]; // X |
... | ... | @@ -15313,13 +15337,12 @@ namespace cimg_library_suffixed { |
15313 | 15337 | } |
15314 | 15338 | |
15315 | 15339 | if (*ref==4) { // Image value (vector): I/J[_#ind,off]++ |
15340 | + is_parallelizable = false; | |
15316 | 15341 | p1 = ref[1]; // Index |
15317 | 15342 | is_relative = (bool)ref[2]; |
15318 | 15343 | arg3 = ref[3]; // Offset |
15319 | 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 | 15346 | if (p1!=~0U) { |
15324 | 15347 | if (!listout) _cimg_mp_return(pos); |
15325 | 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 | 15356 | } |
15334 | 15357 | |
15335 | 15358 | if (*ref==5) { // Image value (vector): I/J(_#ind,_x,_y,_z,_c)++ |
15359 | + is_parallelizable = false; | |
15336 | 15360 | p1 = ref[1]; // Index |
15337 | 15361 | is_relative = (bool)ref[2]; |
15338 | 15362 | arg3 = ref[3]; // X |
15339 | 15363 | arg4 = ref[4]; // Y |
15340 | 15364 | arg5 = ref[5]; // Z |
15341 | 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 | 15367 | if (p1!=~0U) { |
15346 | 15368 | if (!listout) _cimg_mp_return(pos); |
15347 | 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 | 15377 | } |
15356 | 15378 | |
15357 | 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 | 15381 | _cimg_mp_return(pos); |
15362 | 15382 | } |
15363 | 15383 | |
... | ... | @@ -15382,7 +15402,7 @@ namespace cimg_library_suffixed { |
15382 | 15402 | |
15383 | 15403 | // Array-like access to vectors and image values 'i/j[_#ind,offset,_boundary]' and 'vector[offset]'. |
15384 | 15404 | if (*se1==']' && *ss!='[') { |
15385 | - s_op = "Operator '[]'"; | |
15405 | + _cimg_mp_op("Operator '[]'"); | |
15386 | 15406 | is_relative = *ss=='j' || *ss=='J'; |
15387 | 15407 | |
15388 | 15408 | if ((*ss=='I' || *ss=='J') && *ss1=='[' && |
... | ... | @@ -15390,10 +15410,11 @@ namespace cimg_library_suffixed { |
15390 | 15410 | if (*ss2=='#') { // Index specified |
15391 | 15411 | s0 = ss3; while (s0<se1 && (*s0!=',' || level[s0 - expr._data]!=clevel1)) ++s0; |
15392 | 15412 | p1 = compile(ss3,s0++,depth1,0); |
15413 | + _cimg_mp_check_list(false); | |
15393 | 15414 | } else { p1 = ~0U; s0 = ss2; } |
15394 | 15415 | s1 = s0; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1; |
15395 | 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 | 15418 | if (p_ref && arg2==~0U) { |
15398 | 15419 | *p_ref = 4; |
15399 | 15420 | p_ref[1] = p1; |
... | ... | @@ -15408,12 +15429,13 @@ namespace cimg_library_suffixed { |
15408 | 15429 | p3 = (unsigned int)cimg::mod((int)mem[p1],listin.width()); |
15409 | 15430 | p2 = listin[p3]._spectrum; |
15410 | 15431 | } |
15411 | - _cimg_mp_check_vector0(p2,s_op); | |
15432 | + _cimg_mp_check_vector0(p2); | |
15412 | 15433 | pos = vector(p2); |
15413 | 15434 | if (p1!=~0U) { |
15414 | 15435 | CImg<uptrT>::vector((uptrT)(is_relative?mp_list_Joff:mp_list_Ioff), |
15415 | 15436 | pos,p1,arg1,arg2==~0U?reserved_label[30]:arg2).move_to(code); |
15416 | 15437 | } else { |
15438 | + need_input_copy = true; | |
15417 | 15439 | CImg<uptrT>::vector((uptrT)(is_relative?mp_Joff:mp_Ioff), |
15418 | 15440 | pos,arg1,arg2==~0U?reserved_label[30]:arg2).move_to(code); |
15419 | 15441 | } |
... | ... | @@ -15428,7 +15450,7 @@ namespace cimg_library_suffixed { |
15428 | 15450 | } else { p1 = ~0U; s0 = ss2; } |
15429 | 15451 | s1 = s0; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1; |
15430 | 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 | 15454 | if (p_ref && arg2==~0U) { |
15433 | 15455 | *p_ref = 2; |
15434 | 15456 | p_ref[1] = p1; |
... | ... | @@ -15442,6 +15464,7 @@ namespace cimg_library_suffixed { |
15442 | 15464 | pos = scalar3(is_relative?mp_list_joff:mp_list_ioff,p1,arg1,arg2==~0U?reserved_label[30]:arg2); |
15443 | 15465 | } else { |
15444 | 15466 | if (!imgin) _cimg_mp_return(0); |
15467 | + need_input_copy = true; | |
15445 | 15468 | pos = scalar2(is_relative?mp_joff:mp_ioff,arg1,arg2==~0U?reserved_label[30]:arg2); |
15446 | 15469 | } |
15447 | 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 | 15479 | if (s1<se1) { // Two arguments -> sub-vector extraction |
15457 | 15480 | arg2 = compile(++s0,s1,depth1,0); |
15458 | 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 | 15484 | p1 = (unsigned int)mem[arg2]; |
15462 | 15485 | p2 = (unsigned int)mem[arg3]; |
15463 | 15486 | p3 = _cimg_mp_vector_size(arg1); |
... | ... | @@ -15527,12 +15550,14 @@ namespace cimg_library_suffixed { |
15527 | 15550 | if (*se1==')') { |
15528 | 15551 | if (*ss=='(') _cimg_mp_return(compile(ss1,se1,depth1,p_ref)); // Simple parentheses |
15529 | 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 | 15556 | if ((*ss=='I' || *ss=='J') && *ss1=='(') { // Image value as scalar |
15533 | 15557 | if (*ss2=='#') { // Index specified |
15534 | 15558 | s0 = ss3; while (s0<se1 && (*s0!=',' || level[s0 - expr._data]!=clevel1)) ++s0; |
15535 | 15559 | p1 = compile(ss3,s0++,depth1,0); |
15560 | + _cimg_mp_check_list(false); | |
15536 | 15561 | } else { p1 = ~0U; s0 = ss2; } |
15537 | 15562 | arg1 = is_relative?0U:(unsigned int)_cimg_mp_x; |
15538 | 15563 | arg2 = is_relative?0U:(unsigned int)_cimg_mp_y; |
... | ... | @@ -15541,9 +15566,9 @@ namespace cimg_library_suffixed { |
15541 | 15566 | if (s0<se1) { |
15542 | 15567 | s1 = s0; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1; |
15543 | 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 | 15570 | p2 = _cimg_mp_vector_size(arg1); |
15546 | - arg1 = arg1 + 1; | |
15571 | + ++arg1; | |
15547 | 15572 | if (p2>1) { |
15548 | 15573 | arg2 = arg1 + 1; |
15549 | 15574 | if (p2>2) arg3 = arg2 + 1; |
... | ... | @@ -15551,7 +15576,7 @@ namespace cimg_library_suffixed { |
15551 | 15576 | if (s1<se1) { |
15552 | 15577 | s2 = ++s1; while (s2<se1 && (*s2!=',' || level[s2 - expr._data]!=clevel1)) ++s2; |
15553 | 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 | 15581 | } else if (s1<se1) { |
15557 | 15582 | s2 = ++s1; while (s2<se1 && (*s2!=',' || level[s2 - expr._data]!=clevel1)) ++s2; |
... | ... | @@ -15562,7 +15587,7 @@ namespace cimg_library_suffixed { |
15562 | 15587 | if (s3<se1) { |
15563 | 15588 | s2 = ++s3; while (s2<se1 && (*s2!=',' || level[s2 - expr._data]!=clevel1)) ++s2; |
15564 | 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 | 15610 | p3 = (unsigned int)cimg::mod((int)mem[p1],listin.width()); |
15586 | 15611 | p2 = listin[p3]._spectrum; |
15587 | 15612 | } |
15588 | - _cimg_mp_check_vector0(p2,"operator '()'"); | |
15613 | + _cimg_mp_check_vector0(p2); | |
15589 | 15614 | pos = vector(p2); |
15590 | 15615 | if (p1!=~0U) |
15591 | 15616 | CImg<uptrT>::vector((uptrT)(is_relative?mp_list_Jxyz:mp_list_Ixyz), |
15592 | 15617 | pos,p1,arg1,arg2,arg3, |
15593 | 15618 | arg4==~0U?reserved_label[29]:arg4, |
15594 | 15619 | arg5==~0U?reserved_label[30]:arg5).move_to(code); |
15595 | - else | |
15620 | + else { | |
15621 | + need_input_copy = true; | |
15596 | 15622 | CImg<uptrT>::vector((uptrT)(is_relative?mp_Jxyz:mp_Ixyz), |
15597 | 15623 | pos,arg1,arg2,arg3, |
15598 | 15624 | arg4==~0U?reserved_label[29]:arg4, |
15599 | 15625 | arg5==~0U?reserved_label[30]:arg5).move_to(code); |
15626 | + } | |
15600 | 15627 | _cimg_mp_return(pos); |
15601 | 15628 | } |
15602 | 15629 | |
... | ... | @@ -15614,9 +15641,9 @@ namespace cimg_library_suffixed { |
15614 | 15641 | if (s0<se1) { |
15615 | 15642 | s1 = s0; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1; |
15616 | 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 | 15645 | p2 = _cimg_mp_vector_size(arg1); |
15619 | - arg1 = arg1 + 1; | |
15646 | + ++arg1; | |
15620 | 15647 | if (p2>1) { |
15621 | 15648 | arg2 = arg1 + 1; |
15622 | 15649 | if (p2>2) { |
... | ... | @@ -15627,7 +15654,7 @@ namespace cimg_library_suffixed { |
15627 | 15654 | if (s1<se1) { |
15628 | 15655 | s2 = ++s1; while (s2<se1 && (*s2!=',' || level[s2 - expr._data]!=clevel1)) ++s2; |
15629 | 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 | 15659 | } else if (s1<se1) { |
15633 | 15660 | s2 = ++s1; while (s2<se1 && (*s2!=',' || level[s2 - expr._data]!=clevel1)) ++s2; |
... | ... | @@ -15641,7 +15668,7 @@ namespace cimg_library_suffixed { |
15641 | 15668 | if (s2<se1) { |
15642 | 15669 | s3 = ++s2; while (s3<se1 && (*s3!=',' || level[s3 - expr._data]!=clevel1)) ++s3; |
15643 | 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 | 15697 | arg6==~0U?reserved_label[30]:arg6); |
15671 | 15698 | } else { |
15672 | 15699 | if (!imgin) _cimg_mp_return(0); |
15700 | + need_input_copy = true; | |
15673 | 15701 | pos = scalar6(is_relative?mp_jxyzc:mp_ixyzc, |
15674 | 15702 | arg1,arg2,arg3,arg4, |
15675 | 15703 | arg5==~0U?reserved_label[29]:arg5, |
... | ... | @@ -15683,6 +15711,7 @@ namespace cimg_library_suffixed { |
15683 | 15711 | switch (*ss) { |
15684 | 15712 | case 'a' : |
15685 | 15713 | if (!std::strncmp(ss,"abs(",4)) { // Absolute value |
15714 | + _cimg_mp_op("Function 'abs()'"); | |
15686 | 15715 | arg1 = compile(ss4,se1,depth1,0); |
15687 | 15716 | if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_abs,arg1); |
15688 | 15717 | if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(cimg::abs(mem[arg1])); |
... | ... | @@ -15690,6 +15719,7 @@ namespace cimg_library_suffixed { |
15690 | 15719 | } |
15691 | 15720 | |
15692 | 15721 | if (!std::strncmp(ss,"acos(",5)) { // Arccos |
15722 | + _cimg_mp_op("Function 'acos()'"); | |
15693 | 15723 | arg1 = compile(ss5,se1,depth1,0); |
15694 | 15724 | if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_acos,arg1); |
15695 | 15725 | if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::acos(mem[arg1])); |
... | ... | @@ -15697,6 +15727,7 @@ namespace cimg_library_suffixed { |
15697 | 15727 | } |
15698 | 15728 | |
15699 | 15729 | if (!std::strncmp(ss,"asin(",5)) { // Arcsin |
15730 | + _cimg_mp_op("Function 'asin()'"); | |
15700 | 15731 | arg1 = compile(ss5,se1,depth1,0); |
15701 | 15732 | if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_asin,arg1); |
15702 | 15733 | if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::asin(mem[arg1])); |
... | ... | @@ -15704,6 +15735,7 @@ namespace cimg_library_suffixed { |
15704 | 15735 | } |
15705 | 15736 | |
15706 | 15737 | if (!std::strncmp(ss,"atan(",5)) { // Arctan |
15738 | + _cimg_mp_op("Function 'atan()'"); | |
15707 | 15739 | arg1 = compile(ss5,se1,depth1,0); |
15708 | 15740 | if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_atan,arg1); |
15709 | 15741 | if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::atan(mem[arg1])); |
... | ... | @@ -15711,10 +15743,11 @@ namespace cimg_library_suffixed { |
15711 | 15743 | } |
15712 | 15744 | |
15713 | 15745 | if (!std::strncmp(ss,"atan2(",6)) { // Arctan2 |
15746 | + _cimg_mp_op("Function 'atan2()'"); | |
15714 | 15747 | s1 = ss6; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1; |
15715 | 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 | 15751 | if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_atan2,arg1,arg2); |
15719 | 15752 | if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_atan2,arg1,arg2); |
15720 | 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 | 15759 | |
15727 | 15760 | case 'c' : |
15728 | 15761 | if (!std::strncmp(ss,"cabs(",5)) { // Complex absolute value |
15762 | + _cimg_mp_op("Function 'cabs()'"); | |
15729 | 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 | 15765 | _cimg_mp_scalar2(mp_hypot,arg1 + 1,arg1 + 2); |
15732 | 15766 | } |
15733 | 15767 | |
15734 | 15768 | if (!std::strncmp(ss,"carg(",5)) { // Complex argument |
15769 | + _cimg_mp_op("Function 'carg()'"); | |
15735 | 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 | 15772 | _cimg_mp_scalar2(mp_atan2,arg1 + 2,arg1 + 1); |
15738 | 15773 | } |
15739 | 15774 | |
15740 | 15775 | if (!std::strncmp(ss,"cbrt(",5)) { // Cubic root |
15776 | + _cimg_mp_op("Function 'cbrt()'"); | |
15741 | 15777 | arg1 = compile(ss5,se1,depth1,0); |
15742 | 15778 | if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_cbrt,arg1); |
15743 | 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 | 15781 | } |
15746 | 15782 | |
15747 | 15783 | if (!std::strncmp(ss,"cconj(",6)) { // Complex conjugate |
15784 | + _cimg_mp_op("Function 'cconj()'"); | |
15748 | 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 | 15787 | pos = vector(2); |
15751 | 15788 | CImg<uptrT>::vector((uptrT)mp_complex_conj,pos,arg1).move_to(code); |
15752 | 15789 | _cimg_mp_return(pos); |
15753 | 15790 | } |
15754 | 15791 | |
15755 | 15792 | if (!std::strncmp(ss,"cexp(",5)) { // Complex exponential |
15793 | + _cimg_mp_op("Function 'cexp()'"); | |
15756 | 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 | 15796 | pos = vector(2); |
15759 | 15797 | CImg<uptrT>::vector((uptrT)mp_complex_exp,pos,arg1).move_to(code); |
15760 | 15798 | _cimg_mp_return(pos); |
15761 | 15799 | } |
15762 | 15800 | |
15763 | 15801 | if (!std::strncmp(ss,"clog(",5)) { // Complex logarithm |
15802 | + _cimg_mp_op("Function 'clog()'"); | |
15764 | 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 | 15805 | pos = vector(2); |
15767 | 15806 | CImg<uptrT>::vector((uptrT)mp_complex_log,pos,arg1).move_to(code); |
15768 | 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 | 15842 | if (!std::strncmp(ss,"cos(",4)) { // Cosine |
15843 | + _cimg_mp_op("Function 'cos()'"); | |
15772 | 15844 | arg1 = compile(ss4,se1,depth1,0); |
15773 | 15845 | if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_cos,arg1); |
15774 | 15846 | if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::cos(mem[arg1])); |
... | ... | @@ -15776,30 +15848,161 @@ namespace cimg_library_suffixed { |
15776 | 15848 | } |
15777 | 15849 | |
15778 | 15850 | if (!std::strncmp(ss,"cosh(",5)) { // Hyperbolic cosine |
15851 | + _cimg_mp_op("Function 'cosh()'"); | |
15779 | 15852 | arg1 = compile(ss5,se1,depth1,0); |
15780 | 15853 | if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_cosh,arg1); |
15781 | 15854 | if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::cosh(mem[arg1])); |
15782 | 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 | 15987 | if (!std::strncmp(ss,"cross(",6)) { // Cross product |
15786 | - s_op = "Function 'cross()"; | |
15988 | + _cimg_mp_op("Function 'cross()'"); | |
15787 | 15989 | s1 = ss6; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1; |
15788 | 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 | 15994 | pos = vector(3); |
15793 | 15995 | CImg<uptrT>::vector((uptrT)mp_cross,pos,arg1,arg2).move_to(code); |
15794 | 15996 | _cimg_mp_return(pos); |
15795 | 15997 | } |
15796 | 15998 | |
15797 | 15999 | if (!std::strncmp(ss,"cut(",4)) { // Cut |
16000 | + _cimg_mp_op("Function 'cut()'"); | |
15798 | 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 | 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 | 16006 | if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector3_vss(mp_cut,arg1,arg2,arg3); |
15804 | 16007 | if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2) && _cimg_mp_is_constant(arg3)) { |
15805 | 16008 | val = mem[arg1]; |
... | ... | @@ -15813,6 +16016,7 @@ namespace cimg_library_suffixed { |
15813 | 16016 | |
15814 | 16017 | case 'd' : |
15815 | 16018 | if (!std::strncmp(ss,"date(",5)) { // Date and file date |
16019 | + _cimg_mp_op("Function 'date()'"); | |
15816 | 16020 | s1 = ss5; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1; |
15817 | 16021 | arg1 = 0; |
15818 | 16022 | is_sth = s1!=se1; // is_fdate |
... | ... | @@ -15820,12 +16024,13 @@ namespace cimg_library_suffixed { |
15820 | 16024 | (cimg_sscanf(ss5,"%u%c",&arg1,&sep)!=2 || sep!=')')) is_sth = true; |
15821 | 16025 | if (is_sth) { |
15822 | 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 | 16028 | } else val = (double)cimg::date(arg1); |
15825 | 16029 | _cimg_mp_constant(val); |
15826 | 16030 | } |
15827 | 16031 | |
15828 | 16032 | if (!std::strncmp(ss,"debug(",6)) { // Print debug info |
16033 | + _cimg_mp_op("Function 'debug()'"); | |
15829 | 16034 | p1 = code._width; |
15830 | 16035 | arg1 = compile(ss6,se1,depth1,p_ref); |
15831 | 16036 | *se1 = 0; |
... | ... | @@ -15835,52 +16040,233 @@ namespace cimg_library_suffixed { |
15835 | 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 | 16061 | if (!std::strncmp(ss,"dot(",4)) { // Dot product |
15839 | - s_op = "Function 'dot()'"; | |
16062 | + _cimg_mp_op("Function 'dot()'"); | |
15840 | 16063 | s1 = ss4; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1; |
15841 | 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 | 16068 | if (_cimg_mp_is_vector(arg1)) _cimg_mp_scalar3(mp_dot,arg1,arg2,_cimg_mp_vector_size(arg1)); |
15846 | 16069 | _cimg_mp_scalar2(mp_mul,arg1,arg2); |
15847 | 16070 | } |
15848 | 16071 | |
15849 | 16072 | if (!std::strncmp(ss,"dowhile",7) && (*ss7=='(' || (*ss7 && *ss7<=' ' && *ss8=='('))) { // Do..while |
16073 | + _cimg_mp_op("Function 'dowhile()'"); | |
15850 | 16074 | if (*ss7<=' ') cimg::swap(*ss7,*ss8); // Allow space before opening brace |
15851 | 16075 | s1 = ss8; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1; |
15852 | 16076 | p1 = code._width; |
15853 | 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 | 16080 | CImg<uptrT>::vector((uptrT)mp_dowhile,arg1,arg2,code._width - p1).move_to(code,p1); |
15858 | 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 | 16224 | break; |
15861 | 16225 | |
15862 | 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 | 16237 | if (!std::strncmp(ss,"exp(",4)) { // Exponential |
16238 | + _cimg_mp_op("Function 'exp()'"); | |
15864 | 16239 | arg1 = compile(ss4,se1,depth1,0); |
15865 | 16240 | if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_exp,arg1); |
15866 | 16241 | if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::exp(mem[arg1])); |
15867 | 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 | 16254 | break; |
15870 | 16255 | |
15871 | 16256 | case 'f' : |
15872 | 16257 | if (*ss1=='o' && *ss2=='r' && (*ss3=='(' || (*ss3 && *ss3<=' ' && *ss4=='('))) { // For loop |
16258 | + _cimg_mp_op("Function 'for()'"); | |
15873 | 16259 | if (*ss3<=' ') cimg::swap(*ss3,*ss4); // Allow space before opening brace |
15874 | 16260 | s1 = ss4; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1; |
15875 | 16261 | s2 = s1 + 1; while (s2<se1 && (*s2!=',' || level[s2 - expr._data]!=clevel1)) ++s2; |
15876 | 16262 | s3 = s2 + 1; while (s3<se1 && (*s3!=',' || level[s3 - expr._data]!=clevel1)) ++s3; |
15877 | 16263 | compile(ss4,s1,depth1,0); |
15878 | 16264 | p1 = code._width; |
15879 | - arg1 = compile(s1 + 1,s2,depth1,0); | |
16265 | + arg1 = compile(++s1,s2,depth1,0); | |
15880 | 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 | 16270 | arg2 = _cimg_mp_is_vector(pos)?_cimg_mp_vector_size(pos):0; // Output vector size (or 0 if scalar) |
15885 | 16271 | CImg<uptrT>::vector((uptrT)mp_whiledo,pos,arg1,p2 - p1,code._width - p2,arg2).move_to(code,p1); |
15886 | 16272 | _cimg_mp_return(pos); |
... | ... | @@ -15889,14 +16275,11 @@ namespace cimg_library_suffixed { |
15889 | 16275 | |
15890 | 16276 | case 'g' : |
15891 | 16277 | if (!std::strncmp(ss,"gauss(",6)) { // Gaussian function |
16278 | + _cimg_mp_op("Function 'gauss()'"); | |
15892 | 16279 | s1 = ss6; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1; |
15893 | 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 | 16283 | if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector2_vs(mp_gauss,arg1,arg2); |
15901 | 16284 | if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) { |
15902 | 16285 | val1 = mem[arg1]; |
... | ... | @@ -15909,12 +16292,12 @@ namespace cimg_library_suffixed { |
15909 | 16292 | |
15910 | 16293 | case 'h' : |
15911 | 16294 | if (!std::strncmp(ss,"hypot(",6)) { // Hypothenuse |
15912 | - s_op = "Function 'hypot()'"; | |
16295 | + _cimg_mp_op("Function 'hypot()'"); | |
15913 | 16296 | s1 = ss6; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1; |
15914 | 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 | 16301 | if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) { |
15919 | 16302 | val1 = cimg::abs(mem[arg1]); |
15920 | 16303 | val2 = cimg::abs(mem[arg2]); |
... | ... | @@ -15928,19 +16311,21 @@ namespace cimg_library_suffixed { |
15928 | 16311 | |
15929 | 16312 | case 'i' : |
15930 | 16313 | if (*ss1=='f' && (*ss2=='(' || (*ss2 && *ss2<=' ' && *ss3=='('))) { // If..then[..else.] |
15931 | - s_op = "Function 'if()'"; | |
16314 | + _cimg_mp_op("Function 'if()'"); | |
15932 | 16315 | if (*ss2<=' ') cimg::swap(*ss2,*ss3); // Allow space before opening brace |
15933 | 16316 | s1 = ss3; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1; |
15934 | 16317 | s2 = s1 + 1; while (s2<se1 && (*s2!=',' || level[s2 - expr._data]!=clevel1)) ++s2; |
15935 | 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 | 16324 | p2 = code._width; |
15937 | - arg2 = compile(s1 + 1,s2,depth1,0); | |
16325 | + arg2 = compile(++s1,s2,depth1,0); | |
15938 | 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 | 16329 | arg4 = _cimg_mp_is_vector(arg2)?_cimg_mp_vector_size(arg2):0; // Output vector size (or 0 if scalar) |
15945 | 16330 | if (arg4) pos = vector(arg4); else pos = scalar(); |
15946 | 16331 | CImg<uptrT>::vector((uptrT)mp_if,pos,arg1,arg2,arg3, |
... | ... | @@ -15949,12 +16334,13 @@ namespace cimg_library_suffixed { |
15949 | 16334 | } |
15950 | 16335 | |
15951 | 16336 | if (!std::strncmp(ss,"init(",5)) { // Init |
16337 | + _cimg_mp_op("Function 'init()'"); | |
15952 | 16338 | if (ss0!=expr._data || code.width()) { // (only allowed as the first instruction) |
15953 | 16339 | *se = saved_char; cimg::strellipsize(expr,64); |
15954 | 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 | 16342 | "beginning of expression '%s%s%s'.", |
15957 | - pixel_type(),_cimg_mp_calling_function, | |
16343 | + pixel_type(),_cimg_mp_calling_function,s_op, | |
15958 | 16344 | (ss - 4)>expr._data?"...":"", |
15959 | 16345 | (ss - 4)>expr._data?ss - 4:expr._data, |
15960 | 16346 | se<&expr.back()?"...":""); |
... | ... | @@ -15965,15 +16351,27 @@ namespace cimg_library_suffixed { |
15965 | 16351 | } |
15966 | 16352 | |
15967 | 16353 | if (!std::strncmp(ss,"int(",4)) { // Integer cast |
16354 | + _cimg_mp_op("Function 'int()'"); | |
15968 | 16355 | arg1 = compile(ss4,se1,depth1,0); |
15969 | 16356 | if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_int,arg1); |
15970 | 16357 | if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant((long)mem[arg1]); |
15971 | 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 | 16371 | if (*ss1=='s') { // Family of 'is_?()' functions |
15975 | 16372 | |
15976 | 16373 | if (!std::strncmp(ss,"isbool(",7)) { // Is boolean? |
16374 | + _cimg_mp_op("Function 'isbool()'"); | |
15977 | 16375 | if (ss7==se1) _cimg_mp_return(0); |
15978 | 16376 | arg1 = compile(ss7,se1,depth1,0); |
15979 | 16377 | if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_isbool,arg1); |
... | ... | @@ -15982,6 +16380,7 @@ namespace cimg_library_suffixed { |
15982 | 16380 | } |
15983 | 16381 | |
15984 | 16382 | if (!std::strncmp(ss,"isdir(",6)) { // Is directory? |
16383 | + _cimg_mp_op("Function 'isdir()'"); | |
15985 | 16384 | *se1 = 0; |
15986 | 16385 | is_sth = cimg::is_directory(ss6); |
15987 | 16386 | *se1 = ')'; |
... | ... | @@ -15989,6 +16388,7 @@ namespace cimg_library_suffixed { |
15989 | 16388 | } |
15990 | 16389 | |
15991 | 16390 | if (!std::strncmp(ss,"isfile(",7)) { // Is file? |
16391 | + _cimg_mp_op("Function 'isfile()'"); | |
15992 | 16392 | *se1 = 0; |
15993 | 16393 | is_sth = cimg::is_file(ss7); |
15994 | 16394 | *se1 = ')'; |
... | ... | @@ -15996,6 +16396,8 @@ namespace cimg_library_suffixed { |
15996 | 16396 | } |
15997 | 16397 | |
15998 | 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 | 16401 | pos = scalar(); |
16000 | 16402 | CImg<uptrT>::vector((uptrT)mp_isin,pos).move_to(_opcode); |
16001 | 16403 | for (s = ss5; s<se; ++s) { |
... | ... | @@ -16014,6 +16416,7 @@ namespace cimg_library_suffixed { |
16014 | 16416 | } |
16015 | 16417 | |
16016 | 16418 | if (!std::strncmp(ss,"isinf(",6)) { // Is infinite? |
16419 | + _cimg_mp_op("Function 'isinf()'"); | |
16017 | 16420 | if (ss6==se1) _cimg_mp_return(0); |
16018 | 16421 | arg1 = compile(ss6,se1,depth1,0); |
16019 | 16422 | if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_isinf,arg1); |
... | ... | @@ -16022,6 +16425,7 @@ namespace cimg_library_suffixed { |
16022 | 16425 | } |
16023 | 16426 | |
16024 | 16427 | if (!std::strncmp(ss,"isint(",6)) { // Is integer? |
16428 | + _cimg_mp_op("Function 'isint()'"); | |
16025 | 16429 | if (ss6==se1) _cimg_mp_return(0); |
16026 | 16430 | arg1 = compile(ss6,se1,depth1,0); |
16027 | 16431 | if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_isint,arg1); |
... | ... | @@ -16030,6 +16434,7 @@ namespace cimg_library_suffixed { |
16030 | 16434 | } |
16031 | 16435 | |
16032 | 16436 | if (!std::strncmp(ss,"isnan(",6)) { // Is NaN? |
16437 | + _cimg_mp_op("Function 'isnan()'"); | |
16033 | 16438 | if (ss6==se1) _cimg_mp_return(0); |
16034 | 16439 | arg1 = compile(ss6,se1,depth1,0); |
16035 | 16440 | if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_isnan,arg1); |
... | ... | @@ -16038,6 +16443,7 @@ namespace cimg_library_suffixed { |
16038 | 16443 | } |
16039 | 16444 | |
16040 | 16445 | if (!std::strncmp(ss,"isval(",6)) { // Is value? |
16446 | + _cimg_mp_op("Function 'isval()'"); | |
16041 | 16447 | val = 0; |
16042 | 16448 | if (cimg_sscanf(ss6,"%lf%c%c",&val,&sep,&end)==2 && sep==')') _cimg_mp_return(1); |
16043 | 16449 | _cimg_mp_return(0); |
... | ... | @@ -16048,6 +16454,7 @@ namespace cimg_library_suffixed { |
16048 | 16454 | |
16049 | 16455 | case 'l' : |
16050 | 16456 | if (!std::strncmp(ss,"log(",4)) { // Natural logarithm |
16457 | + _cimg_mp_op("Function 'log()'"); | |
16051 | 16458 | arg1 = compile(ss4,se1,depth1,0); |
16052 | 16459 | if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_log,arg1); |
16053 | 16460 | if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::log(mem[arg1])); |
... | ... | @@ -16055,6 +16462,7 @@ namespace cimg_library_suffixed { |
16055 | 16462 | } |
16056 | 16463 | |
16057 | 16464 | if (!std::strncmp(ss,"log2(",5)) { // Base-2 logarithm |
16465 | + _cimg_mp_op("Function 'log2()'"); | |
16058 | 16466 | arg1 = compile(ss5,se1,depth1,0); |
16059 | 16467 | if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_log2,arg1); |
16060 | 16468 | if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(cimg::log2(mem[arg1])); |
... | ... | @@ -16062,6 +16470,7 @@ namespace cimg_library_suffixed { |
16062 | 16470 | } |
16063 | 16471 | |
16064 | 16472 | if (!std::strncmp(ss,"log10(",6)) { // Base-10 logarithm |
16473 | + _cimg_mp_op("Function 'log10()'"); | |
16065 | 16474 | arg1 = compile(ss6,se1,depth1,0); |
16066 | 16475 | if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_log10,arg1); |
16067 | 16476 | if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::log10(mem[arg1])); |
... | ... | @@ -16070,59 +16479,16 @@ namespace cimg_library_suffixed { |
16070 | 16479 | break; |
16071 | 16480 | |
16072 | 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 | 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 | 16492 | p1 = _cimg_mp_vector_size(arg1); |
16127 | 16493 | p2 = _cimg_mp_vector_size(arg2); |
16128 | 16494 | p3 = (unsigned int)mem[arg3]; |
... | ... | @@ -16131,7 +16497,7 @@ namespace cimg_library_suffixed { |
16131 | 16497 | if (arg4*arg5!=p1 || arg5*p3!=p2) { |
16132 | 16498 | *se = saved_char; cimg::strellipsize(expr,64); |
16133 | 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 | 16501 | "do not match for third argument 'nb_colsB=%u', " |
16136 | 16502 | "in expression '%s%s%s'.", |
16137 | 16503 | pixel_type(),_cimg_mp_calling_function,s_op, |
... | ... | @@ -16144,95 +16510,12 @@ namespace cimg_library_suffixed { |
16144 | 16510 | CImg<uptrT>::vector((uptrT)mp_matrix_mul,pos,arg1,arg2,arg4,arg5,p3).move_to(code); |
16145 | 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 | 16513 | break; |
16232 | 16514 | |
16233 | 16515 | case 'n' : |
16234 | 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 | 16519 | arg1 = 0; |
16237 | 16520 | for (s = ss5; s<se; ++s) { |
16238 | 16521 | ns = s; while (ns<se && (*ns!=',' || level[ns - expr._data]!=clevel1) && |
... | ... | @@ -16244,6 +16527,7 @@ namespace cimg_library_suffixed { |
16244 | 16527 | |
16245 | 16528 | if ((cimg_sscanf(ss,"norm%u%c",&(arg1=~0U),&sep)==2 && sep=='(') || |
16246 | 16529 | !std::strncmp(ss,"norminf(",8)) { // Lp norm |
16530 | + _cimg_mp_op("Function 'normP()'"); | |
16247 | 16531 | pos = scalar(); |
16248 | 16532 | switch (arg1) { |
16249 | 16533 | case 0 : CImg<uptrT>::vector((uptrT)mp_norm0,pos).move_to(_opcode); break; |
... | ... | @@ -16272,6 +16556,7 @@ namespace cimg_library_suffixed { |
16272 | 16556 | |
16273 | 16557 | case 'p' : |
16274 | 16558 | if (!std::strncmp(ss,"print(",6)) { // Print expression |
16559 | + _cimg_mp_op("Function 'print()'"); | |
16275 | 16560 | pos = compile(ss6,se1,depth1,p_ref); |
16276 | 16561 | *se1 = 0; |
16277 | 16562 | if (_cimg_mp_is_vector(pos)) // Vector |
... | ... | @@ -16287,14 +16572,11 @@ namespace cimg_library_suffixed { |
16287 | 16572 | |
16288 | 16573 | case 'r' : |
16289 | 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 | 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 | 16580 | if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector2_vs(*ss2=='l'?mp_rol:mp_ror,arg1,arg2); |
16299 | 16581 | if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) |
16300 | 16582 | _cimg_mp_constant(*ss2=='l'?cimg::rol(mem[arg1],(unsigned int)mem[arg2]): |
... | ... | @@ -16302,19 +16584,56 @@ namespace cimg_library_suffixed { |
16302 | 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 | 16624 | if (!std::strncmp(ss,"round(",6)) { // Value rounding |
16306 | - s_op = "Function 'round()'"; | |
16625 | + _cimg_mp_op("Function 'round()'"); | |
16307 | 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 | 16628 | arg2 = 1; |
16310 | 16629 | arg3 = 0; |
16311 | 16630 | if (s1<se1) { |
16312 | 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 | 16637 | if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector3_vss(mp_round,arg1,arg2,arg3); |
16319 | 16638 | if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2) && _cimg_mp_is_constant(arg3)) |
16320 | 16639 | _cimg_mp_constant(cimg::round(mem[arg1],mem[arg2],(int)mem[arg3])); |
... | ... | @@ -16324,6 +16643,7 @@ namespace cimg_library_suffixed { |
16324 | 16643 | |
16325 | 16644 | case 's' : |
16326 | 16645 | if (!std::strncmp(ss,"sign(",5)) { // Sign |
16646 | + _cimg_mp_op("Function 'sign()'"); | |
16327 | 16647 | arg1 = compile(ss5,se1,depth1,0); |
16328 | 16648 | if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_sign,arg1); |
16329 | 16649 | if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(cimg::sign(mem[arg1])); |
... | ... | @@ -16331,6 +16651,7 @@ namespace cimg_library_suffixed { |
16331 | 16651 | } |
16332 | 16652 | |
16333 | 16653 | if (!std::strncmp(ss,"sin(",4)) { // Sine |
16654 | + _cimg_mp_op("Function 'sin()'"); | |
16334 | 16655 | arg1 = compile(ss4,se1,depth1,0); |
16335 | 16656 | if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_sin,arg1); |
16336 | 16657 | if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::sin(mem[arg1])); |
... | ... | @@ -16338,13 +16659,23 @@ namespace cimg_library_suffixed { |
16338 | 16659 | } |
16339 | 16660 | |
16340 | 16661 | if (!std::strncmp(ss,"sinc(",5)) { // Sine cardinal |
16662 | + _cimg_mp_op("Function 'sinc()'"); | |
16341 | 16663 | arg1 = compile(ss5,se1,depth1,0); |
16342 | 16664 | if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_sinc,arg1); |
16343 | 16665 | if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(cimg::sinc(mem[arg1])); |
16344 | 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 | 16677 | if (!std::strncmp(ss,"sinh(",5)) { // Hyperbolic sine |
16678 | + _cimg_mp_op("Function 'sinh()'"); | |
16348 | 16679 | arg1 = compile(ss5,se1,depth1,0); |
16349 | 16680 | if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_sinh,arg1); |
16350 | 16681 | if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::sinh(mem[arg1])); |
... | ... | @@ -16352,24 +16683,76 @@ namespace cimg_library_suffixed { |
16352 | 16683 | } |
16353 | 16684 | |
16354 | 16685 | if (!std::strncmp(ss,"size(",5)) { // Vector size. |
16686 | + _cimg_mp_op("Function 'size()'"); | |
16355 | 16687 | arg1 = compile(ss5,se1,depth1,0); |
16356 | 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 | 16723 | if (!std::strncmp(ss,"sort(",5)) { // Sort vector |
16360 | - s_op = "Function 'sort()'"; | |
16724 | + _cimg_mp_op("Function 'sort()'"); | |
16361 | 16725 | s1 = ss6; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1; |
16362 | 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 | 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 | 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 | 16751 | _cimg_mp_return(pos); |
16370 | 16752 | } |
16371 | 16753 | |
16372 | 16754 | if (!std::strncmp(ss,"sqr(",4)) { // Square |
16755 | + _cimg_mp_op("Function 'sqr()'"); | |
16373 | 16756 | arg1 = compile(ss4,se1,depth1,0); |
16374 | 16757 | if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_sqr,arg1); |
16375 | 16758 | if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(cimg::sqr(mem[arg1])); |
... | ... | @@ -16377,6 +16760,7 @@ namespace cimg_library_suffixed { |
16377 | 16760 | } |
16378 | 16761 | |
16379 | 16762 | if (!std::strncmp(ss,"sqrt(",5)) { // Square root |
16763 | + _cimg_mp_op("Function 'sqrt()'"); | |
16380 | 16764 | arg1 = compile(ss5,se1,depth1,0); |
16381 | 16765 | if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_sqrt,arg1); |
16382 | 16766 | if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::sqrt(mem[arg1])); |
... | ... | @@ -16386,6 +16770,7 @@ namespace cimg_library_suffixed { |
16386 | 16770 | |
16387 | 16771 | case 't' : |
16388 | 16772 | if (!std::strncmp(ss,"tan(",4)) { // Tangent |
16773 | + _cimg_mp_op("Function 'tan()'"); | |
16389 | 16774 | arg1 = compile(ss4,se1,depth1,0); |
16390 | 16775 | if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_tan,arg1); |
16391 | 16776 | if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::tan(mem[arg1])); |
... | ... | @@ -16393,20 +16778,57 @@ namespace cimg_library_suffixed { |
16393 | 16778 | } |
16394 | 16779 | |
16395 | 16780 | if (!std::strncmp(ss,"tanh(",5)) { // Hyperbolic tangent |
16781 | + _cimg_mp_op("Function 'tanh()'"); | |
16396 | 16782 | arg1 = compile(ss5,se1,depth1,0); |
16397 | 16783 | if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_tanh,arg1); |
16398 | 16784 | if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::tanh(mem[arg1])); |
16399 | 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 | 16822 | break; |
16402 | 16823 | |
16403 | 16824 | case 'u' : |
16404 | 16825 | if (*ss1=='(') { // Random value with uniform distribution |
16826 | + _cimg_mp_op("Function 'u()'"); | |
16405 | 16827 | if (*ss2==')') _cimg_mp_scalar2(mp_u,0,1); |
16406 | 16828 | s1 = ss2; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1; |
16407 | 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 | 16832 | if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_u,arg1,arg2); |
16411 | 16833 | if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_u,arg1,arg2); |
16412 | 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 | 16839 | case 'v' : |
16418 | 16840 | if ((cimg_sscanf(ss,"vector%u%c",&(arg1=~0U),&sep)==2 && sep=='(' && arg1>0) || |
16419 | 16841 | !std::strncmp(ss,"vector(",7)) { // Vector |
16842 | + _cimg_mp_op("Function 'vector()'"); | |
16420 | 16843 | arg2 = 0; // Number of specified values. |
16421 | 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 | 16846 | ns = s; while (ns<se && (*ns!=',' || level[ns - expr._data]!=clevel1) && |
16424 | 16847 | (*ns!=')' || level[ns - expr._data]!=clevel)) ++ns; |
16425 | 16848 | arg3 = compile(s,ns,depth1,0); |
... | ... | @@ -16431,7 +16854,7 @@ namespace cimg_library_suffixed { |
16431 | 16854 | s = ns; |
16432 | 16855 | } |
16433 | 16856 | if (arg1==~0U) arg1 = arg2; |
16434 | - _cimg_mp_check_vector0(arg1,"Function 'vector()'"); | |
16857 | + _cimg_mp_check_vector0(arg1); | |
16435 | 16858 | pos = vector(arg1); |
16436 | 16859 | _opcode.insert(CImg<uptrT>::vector((uptrT)mp_vector_init,pos,arg1),0); |
16437 | 16860 | (_opcode>'y').move_to(code); |
... | ... | @@ -16441,13 +16864,14 @@ namespace cimg_library_suffixed { |
16441 | 16864 | |
16442 | 16865 | case 'w' : |
16443 | 16866 | if (!std::strncmp(ss,"whiledo",7) && (*ss7=='(' || (*ss7 && *ss7<=' ' && *ss8=='('))) { // While...do |
16867 | + _cimg_mp_op("Function 'whiledo()'"); | |
16444 | 16868 | if (*ss7<=' ') cimg::swap(*ss7,*ss8); // Allow space before opening brace |
16445 | 16869 | s1 = ss8; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1; |
16446 | 16870 | p1 = code._width; |
16447 | 16871 | arg1 = compile(ss8,s1,depth1,0); |
16448 | 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 | 16875 | arg2 = _cimg_mp_is_vector(pos)?_cimg_mp_vector_size(pos):0; // Output vector size (or 0 if scalar) |
16452 | 16876 | CImg<uptrT>::vector((uptrT)mp_whiledo,pos,arg1,p2 - p1,code._width - p2,arg2).move_to(code,p1); |
16453 | 16877 | _cimg_mp_return(pos); |
... | ... | @@ -16457,15 +16881,31 @@ namespace cimg_library_suffixed { |
16457 | 16881 | |
16458 | 16882 | if (!std::strncmp(ss,"min(",4) || !std::strncmp(ss,"max(",4) || |
16459 | 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 | 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 | 16897 | pos = scalar(); |
16463 | - is_sth = *ss=='a' && ss[3]!='('; | |
16464 | 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 | 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 | 16909 | ns = s; while (ns<se && (*ns!=',' || level[ns - expr._data]!=clevel1) && |
16470 | 16910 | (*ns!=')' || level[ns - expr._data]!=clevel)) ++ns; |
16471 | 16911 | arg2 = compile(s,ns,depth1,0); |
... | ... | @@ -16480,7 +16920,7 @@ namespace cimg_library_suffixed { |
16480 | 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 | 16924 | s0 = strchr(ss,'('); |
16485 | 16925 | if (s0) { |
16486 | 16926 | variable_name.assign(ss,s0 - ss + 1).back() = 0; |
... | ... | @@ -16512,7 +16952,7 @@ namespace cimg_library_suffixed { |
16512 | 16952 | if (p1!=p2+1) { // Number of specified argument do not fit |
16513 | 16953 | *se = saved_char; cimg::strellipsize(variable_name,64); cimg::strellipsize(expr,64); |
16514 | 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 | 16956 | "match function declaration (%u argument%s required), " |
16517 | 16957 | "in expression '%s%s%s'.", |
16518 | 16958 | pixel_type(),_cimg_mp_calling_function,variable_name._data, |
... | ... | @@ -16550,6 +16990,7 @@ namespace cimg_library_suffixed { |
16550 | 16990 | |
16551 | 16991 | // Vector specification using initializer '[ ... ]'. |
16552 | 16992 | if (*ss=='[' && *se1==']') { |
16993 | + _cimg_mp_op("Operator '[]'"); | |
16553 | 16994 | arg1 = 0; // Number of specified values. |
16554 | 16995 | if (*ss1!=']') for (s = ss1; s<se; ++s) { |
16555 | 16996 | ns = s; while (ns<se && (*ns!=',' || level[ns - expr._data]!=clevel1) && |
... | ... | @@ -16562,7 +17003,7 @@ namespace cimg_library_suffixed { |
16562 | 17003 | } else { CImg<uptrT>::vector(arg2).move_to(_opcode); ++arg1; } |
16563 | 17004 | s = ns; |
16564 | 17005 | } |
16565 | - _cimg_mp_check_vector0(arg1,"operator '[]'"); | |
17006 | + _cimg_mp_check_vector0(arg1); | |
16566 | 17007 | pos = vector(arg1); |
16567 | 17008 | _opcode.insert(CImg<uptrT>::vector((uptrT)mp_vector_init,pos,arg1),0); |
16568 | 17009 | (_opcode>'y').move_to(code); |
... | ... | @@ -16702,7 +17143,7 @@ namespace cimg_library_suffixed { |
16702 | 17143 | // Reached an unknown item -> error. |
16703 | 17144 | is_sth = true; // is_valid_variable_name |
16704 | 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 | 17147 | if (!is_varchar(*ns)) { is_sth = false; break; } |
16707 | 17148 | |
16708 | 17149 | *se = saved_char; cimg::strellipsize(variable_name,64); cimg::strellipsize(expr,64); |
... | ... | @@ -16883,7 +17324,7 @@ namespace cimg_library_suffixed { |
16883 | 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 | 17328 | if (mempos + siz>=mem._width) { |
16888 | 17329 | mem.resize(2*mem._width + siz,1,1,1,0); |
16889 | 17330 | memtype.resize(mem._width,1,1,1,0); |
... | ... | @@ -16895,7 +17336,14 @@ namespace cimg_library_suffixed { |
16895 | 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 | 17347 | const unsigned int |
16900 | 17348 | siz = _cimg_mp_vector_size(arg), |
16901 | 17349 | pos = vector(siz); |
... | ... | @@ -16903,11 +17351,36 @@ namespace cimg_library_suffixed { |
16903 | 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 | 17374 | unsigned int vector1_v(const mp_func op, const unsigned int arg1) { |
16907 | 17375 | const unsigned int |
16908 | 17376 | siz = _cimg_mp_vector_size(arg1), |
16909 | 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 | 17384 | return pos; |
16912 | 17385 | } |
16913 | 17386 | |
... | ... | @@ -16915,7 +17388,12 @@ namespace cimg_library_suffixed { |
16915 | 17388 | const unsigned int |
16916 | 17389 | siz = _cimg_mp_vector_size(arg1), |
16917 | 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 | 17397 | return pos; |
16920 | 17398 | } |
16921 | 17399 | |
... | ... | @@ -16923,7 +17401,12 @@ namespace cimg_library_suffixed { |
16923 | 17401 | const unsigned int |
16924 | 17402 | siz = _cimg_mp_vector_size(arg1), |
16925 | 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 | 17410 | return pos; |
16928 | 17411 | } |
16929 | 17412 | |
... | ... | @@ -16931,7 +17414,12 @@ namespace cimg_library_suffixed { |
16931 | 17414 | const unsigned int |
16932 | 17415 | siz = _cimg_mp_vector_size(arg2), |
16933 | 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 | 17423 | return pos; |
16936 | 17424 | } |
16937 | 17425 | |
... | ... | @@ -16940,22 +17428,29 @@ namespace cimg_library_suffixed { |
16940 | 17428 | const unsigned int |
16941 | 17429 | siz = _cimg_mp_vector_size(arg1), |
16942 | 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 | 17437 | return pos; |
16945 | 17438 | } |
16946 | 17439 | |
16947 | 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 | 17442 | const bool is_strictly_positive, |
16950 | 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 | 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 | 17449 | *se = saved_char; cimg::strellipsize(expr,64); |
16955 | 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 | 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 | 17454 | s_arg,*s_arg?"argument":"Argument",s_type(arg)._data, |
16960 | 17455 | is_strictly_positive?"strictly ":"", |
16961 | 17456 | (ss - 4)>expr._data?"...":"", |
... | ... | @@ -16965,9 +17460,9 @@ namespace cimg_library_suffixed { |
16965 | 17460 | } |
16966 | 17461 | |
16967 | 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 | 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 | 17466 | const unsigned int |
16972 | 17467 | siz = _cimg_mp_vector_size(arg), |
16973 | 17468 | n = (unsigned int)std::sqrt((float)siz); |
... | ... | @@ -16977,9 +17472,9 @@ namespace cimg_library_suffixed { |
16977 | 17472 | else s_arg = !n_arg?"":n_arg==1?"First ":n_arg==2?"Second ":n_arg==3?"Third ":"One "; |
16978 | 17473 | *se = saved_char; cimg::strellipsize(expr,64); |
16979 | 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 | 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 | 17478 | s_arg,*s_op=='F'?(*s_arg?"argument":"Argument"):(*s_arg?"operand":"Operand"), |
16984 | 17479 | s_type(arg)._data, |
16985 | 17480 | (ss - 4)>expr._data?"...":"", |
... | ... | @@ -16992,7 +17487,7 @@ namespace cimg_library_suffixed { |
16992 | 17487 | // Bits of 'mode' tells what types are allowed: |
16993 | 17488 | // { 1 = scalar | 2 = vectorN }. |
16994 | 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 | 17491 | const unsigned int mode, const unsigned int N, |
16997 | 17492 | const char *const ss, char *const se, const char saved_char) { |
16998 | 17493 | const bool |
... | ... | @@ -17004,7 +17499,9 @@ namespace cimg_library_suffixed { |
17004 | 17499 | if (!cond) { |
17005 | 17500 | const char *s_arg; |
17006 | 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 | 17505 | CImg<charT> sb_type(32); |
17009 | 17506 | if (mode==1) cimg_snprintf(sb_type,sb_type._width,"'scalar'"); |
17010 | 17507 | else if (mode==2) { |
... | ... | @@ -17016,9 +17513,9 @@ namespace cimg_library_suffixed { |
17016 | 17513 | } |
17017 | 17514 | *se = saved_char; cimg::strellipsize(expr,64); |
17018 | 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 | 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 | 17519 | s_arg,*s_op=='F'?(*s_arg?"argument":"Argument"):(*s_arg?"operand":"Operand"), |
17023 | 17520 | s_type(arg)._data,sb_type._data, |
17024 | 17521 | (ss - 4)>expr._data?"...":"", |
... | ... | @@ -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 | 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 | 17544 | const char *const ss, char *const se, const char saved_char) { |
17033 | 17545 | if (!dim) { |
17034 | 17546 | *se = saved_char; cimg::strellipsize(expr,64); |
17035 | 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 | 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 | 17551 | (ss - 4)>expr._data?"...":"", |
17040 | 17552 | (ss - 4)>expr._data?ss - 4:expr._data, |
17041 | 17553 | se<&expr.back()?"...":""); |
17042 | 17554 | } else if (dim==~0U) { |
17043 | 17555 | *se = saved_char; cimg::strellipsize(expr,64); |
17044 | 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 | 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 | 17560 | (ss - 4)>expr._data?"...":"", |
17049 | 17561 | (ss - 4)>expr._data?ss - 4:expr._data, |
17050 | 17562 | se<&expr.back()?"...":""); |
... | ... | @@ -17253,6 +17765,26 @@ namespace cimg_library_suffixed { |
17253 | 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 | 17788 | static double mp_cross(_cimg_math_parser& mp) { |
17257 | 17789 | CImg<doubleT> |
17258 | 17790 | vout(&_mp_arg(1) + 1,1,3,1,1,true), |
... | ... | @@ -17268,52 +17800,56 @@ namespace cimg_library_suffixed { |
17268 | 17800 | } |
17269 | 17801 | |
17270 | 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 | 17803 | CImg<charT> expr(mp.opcode._height - 3); |
17277 | 17804 | const uptrT *ptrs = mp.opcode._data + 3; |
17278 | 17805 | cimg_for(expr,ptrd,char) *ptrd = (char)*(ptrs++); |
17279 | 17806 | cimg::strellipsize(expr); |
17280 | 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 | 17845 | std::fprintf(cimg::output(), |
17302 | 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 | 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 | 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 | 17853 | return mp.mem[g_target]; |
17318 | 17854 | } |
17319 | 17855 | |
... | ... | @@ -17321,6 +17857,24 @@ namespace cimg_library_suffixed { |
17321 | 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 | 17878 | static double mp_dot(_cimg_math_parser& mp) { |
17325 | 17879 | const unsigned int siz = (unsigned int)mp.opcode[4]; |
17326 | 17880 | return CImg<doubleT>(&_mp_arg(2) + 1,1,siz,1,1,true). |
... | ... | @@ -17346,8 +17900,36 @@ namespace cimg_library_suffixed { |
17346 | 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 | 17935 | static double mp_eq(_cimg_math_parser& mp) { |
... | ... | @@ -17358,6 +17940,13 @@ namespace cimg_library_suffixed { |
17358 | 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 | 17950 | static double mp_g(_cimg_math_parser& mp) { |
17362 | 17951 | cimg::unused(mp); |
17363 | 17952 | return cimg::grand(); |
... | ... | @@ -17424,6 +18013,14 @@ namespace cimg_library_suffixed { |
17424 | 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 | 18024 | static double mp_ioff(_cimg_math_parser& mp) { |
17428 | 18025 | const unsigned int |
17429 | 18026 | boundary_conditions = (unsigned int)_mp_arg(3); |
... | ... | @@ -17713,9 +18310,8 @@ namespace cimg_library_suffixed { |
17713 | 18310 | z = (int)_mp_arg(5), c = (int)_mp_arg(6); |
17714 | 18311 | const double val = _mp_arg(1); |
17715 | 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 | 18314 | img(x,y,z,c) = (T)val; |
17718 | - } | |
17719 | 18315 | return val; |
17720 | 18316 | } |
17721 | 18317 | |
... | ... | @@ -17744,9 +18340,8 @@ namespace cimg_library_suffixed { |
17744 | 18340 | z = (int)(oz + _mp_arg(5)), c = (int)(oc + _mp_arg(6)); |
17745 | 18341 | const double val = _mp_arg(1); |
17746 | 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 | 18344 | img(x,y,z,c) = (T)val; |
17749 | - } | |
17750 | 18345 | return val; |
17751 | 18346 | } |
17752 | 18347 | |
... | ... | @@ -18099,46 +18694,6 @@ namespace cimg_library_suffixed { |
18099 | 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 | 18697 | static double mp_matrix_mul(_cimg_math_parser& mp) { |
18143 | 18698 | double *ptrd = &_mp_arg(1) + 1; |
18144 | 18699 | const double |
... | ... | @@ -18152,48 +18707,110 @@ namespace cimg_library_suffixed { |
18152 | 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 | 18710 | static double mp_max(_cimg_math_parser& mp) { |
18192 | 18711 | double val = _mp_arg(2); |
18193 | 18712 | for (unsigned int i = 3; i<mp.opcode._height; ++i) val = cimg::max(val,_mp_arg(i)); |
18194 | 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 | 18814 | static double mp_min(_cimg_math_parser& mp) { |
18198 | 18815 | double val = _mp_arg(2); |
18199 | 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 | 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 | 18830 | static double mp_med(_cimg_math_parser& mp) { |
18208 | 18831 | CImg<doubleT> vals(mp.opcode._height - 2); |
18209 | 18832 | double *p = vals.data(); |
... | ... | @@ -18278,13 +18901,26 @@ namespace cimg_library_suffixed { |
18278 | 18901 | } |
18279 | 18902 | |
18280 | 18903 | static double mp_print(_cimg_math_parser& mp) { |
18904 | + cimg::mutex(6); | |
18281 | 18905 | CImg<charT> expr(mp.opcode._height - 2); |
18282 | 18906 | const uptrT *ptrs = mp.opcode._data + 2; |
18283 | 18907 | cimg_for(expr,ptrd,char) *ptrd = (char)*(ptrs++); |
18284 | 18908 | cimg::strellipsize(expr); |
18285 | 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 | 18924 | return val; |
18289 | 18925 | } |
18290 | 18926 | |
... | ... | @@ -18300,6 +18936,26 @@ namespace cimg_library_suffixed { |
18300 | 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 | 18959 | static double mp_round(_cimg_math_parser& mp) { |
18304 | 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 | 19059 | z = (int)_mp_arg(4), c = (int)_mp_arg(5); |
18404 | 19060 | const double val = _mp_arg(1); |
18405 | 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 | 19063 | img(x,y,z,c) = (T)val; |
18408 | - } | |
18409 | 19064 | return val; |
18410 | 19065 | } |
18411 | 19066 | |
... | ... | @@ -18432,9 +19087,8 @@ namespace cimg_library_suffixed { |
18432 | 19087 | z = (int)(oz + _mp_arg(4)), c = (int)(oc + _mp_arg(5)); |
18433 | 19088 | const double val = _mp_arg(1); |
18434 | 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 | 19091 | img(x,y,z,c) = (T)val; |
18437 | - } | |
18438 | 19092 | return val; |
18439 | 19093 | } |
18440 | 19094 | |
... | ... | @@ -18558,10 +19212,53 @@ namespace cimg_library_suffixed { |
18558 | 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 | 19233 | static double mp_sinh(_cimg_math_parser& mp) { |
18562 | 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 | 19262 | static double mp_sqr(_cimg_math_parser& mp) { |
18566 | 19263 | return cimg::sqr(_mp_arg(2)); |
18567 | 19264 | } |
... | ... | @@ -18570,10 +19267,23 @@ namespace cimg_library_suffixed { |
18570 | 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 | 19277 | static double mp_sub(_cimg_math_parser& mp) { |
18574 | 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 | 19287 | static double mp_tan(_cimg_math_parser& mp) { |
18578 | 19288 | return std::tan(_mp_arg(2)); |
18579 | 19289 | } |
... | ... | @@ -18582,10 +19292,33 @@ namespace cimg_library_suffixed { |
18582 | 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 | 19311 | static double mp_u(_cimg_math_parser& mp) { |
18586 | 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 | 19322 | static double mp_vector_copy(_cimg_math_parser& mp) { |
18590 | 19323 | std::memcpy(&_mp_arg(1) + 1,&_mp_arg(2) + 1,sizeof(double)*mp.opcode[3]); |
18591 | 19324 | return cimg::type<double>::nan(); |
... | ... | @@ -18704,15 +19437,6 @@ namespace cimg_library_suffixed { |
18704 | 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 | 19440 | static double mp_vector_print(_cimg_math_parser& mp) { |
18717 | 19441 | CImg<charT> expr(mp.opcode._height - 3); |
18718 | 19442 | const uptrT *ptrs = mp.opcode._data + 3; |
... | ... | @@ -20185,7 +20909,8 @@ namespace cimg_library_suffixed { |
20185 | 20909 | case 's' : return (double)_spectrum; |
20186 | 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 | 20914 | *this,img_output,list_inputs,list_outputs); |
20190 | 20915 | return mp(x,y,z,c); |
20191 | 20916 | } |
... | ... | @@ -20229,7 +20954,8 @@ namespace cimg_library_suffixed { |
20229 | 20954 | case 's' : output.assign(1); *output = (t)_spectrum; |
20230 | 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 | 20959 | *this,img_output,list_inputs,list_outputs); |
20234 | 20960 | output.assign(1,cimg::max(1U,mp.result_dim)); |
20235 | 20961 | mp(x,y,z,c,output._data); |
... | ... | @@ -20823,13 +21549,13 @@ namespace cimg_library_suffixed { |
20823 | 21549 | "incompatible dimensions.", |
20824 | 21550 | cimg_instance, |
20825 | 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 | 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 | 21559 | #ifdef cimg_use_lapack |
20834 | 21560 | char TRANS = 'N'; |
20835 | 21561 | int INFO, N = _height, LWORK = 4*N, *const IPIV = new int[N]; |
... | ... | @@ -20865,6 +21591,11 @@ namespace cimg_library_suffixed { |
20865 | 21591 | #endif |
20866 | 21592 | } else { // Least-square solution for non-square systems. |
20867 | 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 | 21599 | char TRANS = 'N'; |
20869 | 21600 | int INFO, N = A._width, M = A._height, LWORK = -1, LDA = M, LDB = M, NRHS = _width; |
20870 | 21601 | Ttfloat WORK_QUERY; |
... | ... | @@ -22393,24 +23124,25 @@ namespace cimg_library_suffixed { |
22393 | 23124 | |
22394 | 23125 | CImg<T>& _fill(const char *const expression, const bool repeat_values, const bool allow_formula, |
22395 | 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 | 23128 | if (is_empty() || !expression || !*expression) return *this; |
22398 | 23129 | const unsigned int omode = cimg::exception_mode(); |
22399 | 23130 | cimg::exception_mode(0); |
22400 | 23131 | CImg<charT> is_error; |
22401 | 23132 | |
22402 | 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 | 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 | 23142 | bool do_in_parallel = false; |
22411 | 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 | 23146 | std::strlen(expression)>=6)) |
22415 | 23147 | do_in_parallel = true; |
22416 | 23148 | #endif |
... | ... | @@ -26443,18 +27175,20 @@ namespace cimg_library_suffixed { |
26443 | 27175 | \param boundary Boundary conditions. Can be <tt>{ 0=dirichlet | 1=neumann | 2=periodic }</tt>. |
26444 | 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 | 27180 | const float nangle = cimg::mod(angle,360.0f); |
26448 | 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 | 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 | 27188 | if (is_empty()) return *this; |
26455 | 27189 | CImg<T> res; |
26456 | 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 | 27192 | const int wm1 = width() - 1, hm1 = height() - 1; |
26459 | 27193 | const int iangle = (int)nangle/90; |
26460 | 27194 | switch (iangle) { |
... | ... | @@ -26487,7 +27221,7 @@ namespace cimg_library_suffixed { |
26487 | 27221 | w2 = 0.5f*_width, h2 = 0.5f*_height, |
26488 | 27222 | dw2 = 0.5f*(ux + vx), dh2 = 0.5f*(uy + vy); |
26489 | 27223 | res.assign((int)(ux + vx),(int)(uy + vy),_depth,_spectrum); |
26490 | - switch (boundary) { | |
27224 | + switch (boundary_conditions) { | |
26491 | 27225 | case 0 : { // Dirichlet boundaries. |
26492 | 27226 | switch (interpolation) { |
26493 | 27227 | case 2 : { // Cubic interpolation. |
... | ... | @@ -26577,7 +27311,7 @@ namespace cimg_library_suffixed { |
26577 | 27311 | "rotate(): Invalid specified border conditions %d " |
26578 | 27312 | "(should be { 0=dirichlet | 1=neumann | 2=periodic }).", |
26579 | 27313 | cimg_instance, |
26580 | - boundary); | |
27314 | + boundary_conditions); | |
26581 | 27315 | } |
26582 | 27316 | } |
26583 | 27317 | return res; |
... | ... | @@ -26593,13 +27327,13 @@ namespace cimg_library_suffixed { |
26593 | 27327 | \param interpolation_type Type of interpolation. Can be <tt>{ 0=nearest | 1=linear | 2=cubic }</tt>. |
26594 | 27328 | **/ |
26595 | 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 | 27334 | //! Rotate image with arbitrary angle, around a center point \newinstance. |
26601 | 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 | 27337 | if (interpolation>2) |
26604 | 27338 | throw CImgArgumentException(_cimg_instance |
26605 | 27339 | "rotate(): Invalid specified interpolation type %d " |
... | ... | @@ -26613,7 +27347,7 @@ namespace cimg_library_suffixed { |
26613 | 27347 | rad = (float)((angle*cimg::PI)/180.0), |
26614 | 27348 | ca = (float)std::cos(rad)/zoom, |
26615 | 27349 | sa = (float)std::sin(rad)/zoom; |
26616 | - switch (boundary) { | |
27350 | + switch (boundary_conditions) { | |
26617 | 27351 | case 0 : { |
26618 | 27352 | switch (interpolation) { |
26619 | 27353 | case 2 : { |
... | ... | @@ -26703,7 +27437,7 @@ namespace cimg_library_suffixed { |
26703 | 27437 | "rotate(): Invalid specified border conditions %d " |
26704 | 27438 | "(should be { 0=dirichlet | 1=neumann | 2=periodic }).", |
26705 | 27439 | cimg_instance, |
26706 | - boundary); | |
27440 | + boundary_conditions); | |
26707 | 27441 | } |
26708 | 27442 | return res; |
26709 | 27443 | } |
... | ... | @@ -29523,12 +30257,25 @@ namespace cimg_library_suffixed { |
29523 | 30257 | //! Compute watershed transform. |
29524 | 30258 | /** |
29525 | 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 | 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 | 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 | 30279 | if (is_empty()) return *this; |
29533 | 30280 | if (!is_sameXYZ(priority)) |
29534 | 30281 | throw CImgArgumentException(_cimg_instance |
... | ... | @@ -29538,29 +30285,62 @@ namespace cimg_library_suffixed { |
29538 | 30285 | priority._width,priority._height,priority._depth,priority._spectrum,priority._data); |
29539 | 30286 | if (_spectrum!=1) { |
29540 | 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 | 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 | 30293 | CImg<typename cimg::superset2<T,t,int>::type> Q; |
29547 | 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 | 30299 | // Find seed points and insert them in priority queue. |
30300 | + unsigned int nb_seeds = 0; | |
29550 | 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 | 30346 | // Start watershed computation. |
... | ... | @@ -29568,145 +30348,113 @@ namespace cimg_library_suffixed { |
29568 | 30348 | |
29569 | 30349 | // Get and remove point with maximal priority from the queue. |
29570 | 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 | 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 | 30400 | return *this; |
29667 | 30401 | } |
29668 | 30402 | |
29669 | 30403 | //! Compute watershed transform \newinstance. |
29670 | 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 | 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 | 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 | 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 | 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 | 30427 | return true; |
29688 | 30428 | } |
29689 | 30429 | |
29690 | 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 | 30435 | const float value = (*this)(0,0); |
29694 | 30436 | for (unsigned int pos = 0, left = 0, right = 0; |
29695 | 30437 | ((right=2*(pos + 1),(left=right - 1))<siz && value<(*this)(left,0)) || |
29696 | 30438 | (right<siz && value<(*this)(right,0));) { |
29697 | 30439 | if (right<siz) { |
29698 | 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 | 30445 | pos = left; |
29702 | 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 | 30451 | pos = right; |
29706 | 30452 | } |
29707 | 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 | 30458 | pos = left; |
29711 | 30459 | } |
29712 | 30460 | } |
... | ... | @@ -39484,11 +40232,11 @@ namespace cimg_library_suffixed { |
39484 | 40232 | lZ = sprite.depth() - (z0 + sprite.depth()>depth()?z0 + sprite.depth() - depth():0) + (bz?z0:0), |
39485 | 40233 | lC = sprite.spectrum() - (c0 + sprite.spectrum()>spectrum()?c0 + sprite.spectrum() - spectrum():0) + (bc?c0:0); |
39486 | 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 | 40240 | const uptrT |
39493 | 40241 | offX = (unsigned long)_width - lX, |
39494 | 40242 | soffX = (unsigned long)sprite._width - lX, |
... | ... | @@ -39528,11 +40276,11 @@ namespace cimg_library_suffixed { |
39528 | 40276 | lZ = sprite.depth() - (z0 + sprite.depth()>depth()?z0 + sprite.depth() - depth():0) + (bz?z0:0), |
39529 | 40277 | lC = sprite.spectrum() - (c0 + sprite.spectrum()>spectrum()?c0 + sprite.spectrum() - spectrum():0) + (bc?c0:0); |
39530 | 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 | 40284 | const unsigned long |
39537 | 40285 | offX = (unsigned long)_width - lX, |
39538 | 40286 | soffX = (unsigned long)sprite._width - lX, |
... | ... | @@ -39623,10 +40371,10 @@ namespace cimg_library_suffixed { |
39623 | 40371 | lZ = sprite.depth() - (z0 + sprite.depth()>depth()?z0 + sprite.depth() - depth():0) + (bz?z0:0), |
39624 | 40372 | lC = sprite.spectrum() - (c0 + sprite.spectrum()>spectrum()?c0 + sprite.spectrum() - spectrum():0) + (bc?c0:0); |
39625 | 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 | 40378 | ssize = (uptrT)mask.width()*mask.height()*mask.depth()*mask.spectrum(); |
39631 | 40379 | const ti *ptrs = sprite._data + coff; |
39632 | 40380 | const tm *ptrm = mask._data + coff; |
... | ... | @@ -43423,7 +44171,7 @@ namespace cimg_library_suffixed { |
43423 | 44171 | unsigned int cdx = 0, dx = 0, dy = 0; |
43424 | 44172 | int err = 0; |
43425 | 44173 | double val; |
43426 | - assign(256,256); | |
44174 | + assign(256,256,1,1,0); | |
43427 | 44175 | while ((err = std::fscanf(nfile,"%lf%255[^0-9eEinfa.+-]",&val,delimiter._data))>0) { |
43428 | 44176 | if (err>0) (*this)(cdx++,dy) = (T)val; |
43429 | 44177 | if (cdx>=_width) resize(3*_width/2,_height,1,1,0); |
... | ... | @@ -48536,7 +49284,7 @@ namespace cimg_library_suffixed { |
48536 | 49284 | **/ |
48537 | 49285 | const CImg<T>& save_tiff(const char *const filename, const unsigned int compression_type=0, |
48538 | 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 | 49288 | if (!filename) |
48541 | 49289 | throw CImgArgumentException(_cimg_instance |
48542 | 49290 | "save_tiff(): Specified filename is (null).", |
... | ... | @@ -48544,7 +49292,9 @@ namespace cimg_library_suffixed { |
48544 | 49292 | if (is_empty()) { cimg::fempty(0,filename); return *this; } |
48545 | 49293 | |
48546 | 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 | 49298 | if (tif) { |
48549 | 49299 | cimg_forZ(*this,z) _save_tiff(tif,z,z,compression_type,voxel_size,description); |
48550 | 49300 | TIFFClose(tif); |
... | ... | @@ -48554,7 +49304,7 @@ namespace cimg_library_suffixed { |
48554 | 49304 | filename); |
48555 | 49305 | return *this; |
48556 | 49306 | #else |
48557 | - cimg::unused(compression_type,voxel_size,description,is_bigtiff); | |
49307 | + cimg::unused(compression_type,voxel_size,description,use_bigtiff); | |
48558 | 49308 | return save_other(filename); |
48559 | 49309 | #endif |
48560 | 49310 | } |
... | ... | @@ -49078,9 +49828,9 @@ namespace cimg_library_suffixed { |
49078 | 49828 | if (is_empty()) { cimg::fempty(file,filename); return *this; } |
49079 | 49829 | |
49080 | 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 | 49834 | unsigned int nbdims, dims[5] = { 0 }; |
49085 | 49835 | bool saved = false; |
49086 | 49836 | _cimg_save_pandore_case(1,1,1,"unsigned char",2); |
... | ... | @@ -52584,7 +53334,7 @@ namespace cimg_library_suffixed { |
52584 | 53334 | *tmp = *str_pixeltype = *str_endian = 0; |
52585 | 53335 | unsigned int j, N, W, H, D, C; |
52586 | 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 | 53338 | err = cimg_sscanf(tmp,"%u%*c%255[A-Za-z_]%*c%255[sA-Za-z_ ]", |
52589 | 53339 | &N,str_pixeltype._data,str_endian._data); |
52590 | 53340 | if (err<2) { |
... | ... | @@ -53773,7 +54523,7 @@ namespace cimg_library_suffixed { |
53773 | 54523 | #define _cimg_save_cimg_case(Ts,Tss) \ |
53774 | 54524 | if (!saved && !cimg::strcasecmp(Ts,str_pixeltype)) { \ |
53775 | 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 | 54527 | W = H = D = C = 0; \ |
53778 | 54528 | if (cimg_sscanf(tmp,"%u %u %u %u",&W,&H,&D,&C)!=4) \ |
53779 | 54529 | throw CImgIOException(_cimglist_instance \ |
... | ... | @@ -53843,7 +54593,7 @@ namespace cimg_library_suffixed { |
53843 | 54593 | *tmp = *str_pixeltype = *str_endian = 0; |
53844 | 54594 | unsigned int j, N, W, H, D, C; |
53845 | 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 | 54597 | err = cimg_sscanf(tmp,"%u%*c%255[A-Za-z_]%*c%255[sA-Za-z_ ]",&N,str_pixeltype._data,str_endian._data); |
53848 | 54598 | if (err<2) { |
53849 | 54599 | if (!file) cimg::fclose(nfile); |
... | ... | @@ -53966,7 +54716,7 @@ namespace cimg_library_suffixed { |
53966 | 54716 | **/ |
53967 | 54717 | const CImgList<T>& save_tiff(const char *const filename, const unsigned int compression_type=0, |
53968 | 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 | 54720 | if (!filename) |
53971 | 54721 | throw CImgArgumentException(_cimglist_instance |
53972 | 54722 | "save_tiff(): Specified filename is (null).", |
... | ... | @@ -53974,14 +54724,17 @@ namespace cimg_library_suffixed { |
53974 | 54724 | if (is_empty()) { cimg::fempty(0,filename); return *this; } |
53975 | 54725 | |
53976 | 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 | 54728 | else cimglist_for(*this,l) { |
53979 | 54729 | CImg<charT> nfilename(1024); |
53980 | 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 | 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 | 54738 | if (tif) { |
53986 | 54739 | for (unsigned int dir = 0, l = 0; l<_width; ++l) { |
53987 | 54740 | const CImg<T>& img = (*this)[l]; | ... | ... |
stim/image/image.h
... | ... | @@ -35,7 +35,7 @@ public: |
35 | 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 | 39 | img = cimg_library::CImg<T>(x, y, z, c); |
40 | 40 | } |
41 | 41 | |
... | ... | @@ -50,13 +50,13 @@ public: |
50 | 50 | } |
51 | 51 | |
52 | 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 | 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 | 60 | non_interleaved[i + c * S] = buffer[i * channels + c]; |
61 | 61 | } |
62 | 62 | } |
... | ... | @@ -71,19 +71,19 @@ public: |
71 | 71 | |
72 | 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 | 77 | T* ptr = img.data(); |
78 | 78 | |
79 | 79 | //for each channel |
80 | - for(unsigned int c = 0; c < C; c++) | |
80 | + for(size_t c = 0; c < C; c++) | |
81 | 81 | //convert each pixel |
82 | - for(unsigned int x = 0; x < X; x++) | |
82 | + for(size_t x = 0; x < X; x++) | |
83 | 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 | 88 | //create a new image |
89 | 89 | image<T> single; |
... | ... | @@ -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 | 98 | return img(x, y, z, c); |
99 | 99 | } |
100 | 100 | |
... | ... | @@ -103,9 +103,9 @@ public: |
103 | 103 | /// @param v is the value used to set all values in the image |
104 | 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 | 109 | img.data()[x] = v; |
110 | 110 | |
111 | 111 | return *this; |
... | ... | @@ -117,10 +117,10 @@ public: |
117 | 117 | /// @param c is the channel number that the data will be copied to |
118 | 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 | 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 | 125 | //retreive a pointer to the raw image data |
126 | 126 | T* ptr = img.data() + channel_size * c; |
... | ... | @@ -129,7 +129,7 @@ public: |
129 | 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 | 134 | //create a new image |
135 | 135 | image<T> slice; |
... | ... | @@ -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 | 148 | return img.width(); |
149 | 149 | } |
150 | 150 | |
151 | - unsigned int height(){ | |
151 | + size_t height(){ | |
152 | 152 | return img.height(); |
153 | 153 | } |
154 | 154 | |
155 | - unsigned int depth(){ | |
155 | + size_t depth(){ | |
156 | 156 | return img.depth(); |
157 | 157 | } |
158 | 158 | |
... | ... | @@ -162,22 +162,22 @@ public: |
162 | 162 | } |
163 | 163 | |
164 | 164 | //returns the size (number of values) of the image |
165 | - unsigned long size(){ | |
165 | + size_t size(){ | |
166 | 166 | return img.size(); |
167 | 167 | } |
168 | 168 | |
169 | 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 | 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 | 182 | if(ptr[c * P + p] > 0){ |
183 | 183 | n++; |
... | ... | @@ -191,19 +191,19 @@ public: |
191 | 191 | } |
192 | 192 | |
193 | 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 | 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 | 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 | 208 | if(ptr[c * P + p] > 0){ |
209 | 209 | s[i] = p; |
... | ... | @@ -220,9 +220,9 @@ public: |
220 | 220 | /// Returns the maximum pixel value in the image |
221 | 221 | T maxv(){ |
222 | 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 | 227 | if (img.data()[i] > max) |
228 | 228 | { |
... | ... | @@ -236,9 +236,9 @@ public: |
236 | 236 | /// Returns the minimum pixel value in the image |
237 | 237 | T minv(){ |
238 | 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 | 243 | if (img.data()[i] < min) |
244 | 244 | { |
... | ... | @@ -276,8 +276,8 @@ public: |
276 | 276 | |
277 | 277 | image<T> result; |
278 | 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 | 281 | result.img = img.get_rotate (angle, cx, cy, zoom, interpolation, boundary); |
282 | 282 | //result.save("data_output/test_rotate_neum.bmp"); |
283 | 283 | |
... | ... | @@ -286,13 +286,13 @@ public: |
286 | 286 | |
287 | 287 | // leila's code for non_interleaving data in 3D |
288 | 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 | 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 | 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 | 76 | |
77 | 77 | } |
78 | 78 | |
79 | - int nargs() | |
79 | + size_t nargs() | |
80 | 80 | { |
81 | 81 | return vals.size(); |
82 | 82 | } |
... | ... | @@ -135,9 +135,9 @@ namespace stim{ |
135 | 135 | } |
136 | 136 | |
137 | 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 | 141 | //add the length of the option name |
142 | 142 | n += name.size(); |
143 | 143 | |
... | ... | @@ -148,7 +148,7 @@ namespace stim{ |
148 | 148 | n += 6; |
149 | 149 | |
150 | 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 | 152 | n += vals[v].size() + 1; |
153 | 153 | } |
154 | 154 | |
... | ... | @@ -160,7 +160,7 @@ namespace stim{ |
160 | 160 | |
161 | 161 | |
162 | 162 | //string output |
163 | - std::string toStr(int width = 0) | |
163 | + std::string toStr(size_t width = 0) | |
164 | 164 | { |
165 | 165 | std::stringstream ss; |
166 | 166 | |
... | ... | @@ -174,7 +174,7 @@ namespace stim{ |
174 | 174 | if(ansi) |
175 | 175 | left_part += "\033[1;32m"; |
176 | 176 | left_part += " ( = "; |
177 | - for(unsigned int v=0; v<vals.size(); v++) | |
177 | + for(size_t v=0; v<vals.size(); v++) | |
178 | 178 | left_part += vals[v] + std::string(" "); |
179 | 179 | left_part += ")"; |
180 | 180 | if(ansi) |
... | ... | @@ -191,7 +191,7 @@ namespace stim{ |
191 | 191 | ss<<std::left<<std::setw(width + color_size)<<left_part; |
192 | 192 | |
193 | 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 | 196 | if(d == 0) |
197 | 197 | ss<<desc[0]; |
... | ... | @@ -234,7 +234,7 @@ namespace stim{ |
234 | 234 | struct argsection |
235 | 235 | { |
236 | 236 | std::string name; |
237 | - unsigned int index; | |
237 | + size_t index; | |
238 | 238 | }; |
239 | 239 | |
240 | 240 | /**The arglist class implements command line arguments. |
... | ... | @@ -285,7 +285,7 @@ namespace stim{ |
285 | 285 | std::vector<std::string> args; |
286 | 286 | |
287 | 287 | //column width of the longest option |
288 | - int col_width; | |
288 | + size_t col_width; | |
289 | 289 | |
290 | 290 | //list of sections |
291 | 291 | std::vector<argsection> sections; |
... | ... | @@ -327,7 +327,7 @@ namespace stim{ |
327 | 327 | opt.set_ansi(ansi); |
328 | 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 | 333 | ///Specifies a section name that can be used to organize parameters in the output. |
... | ... | @@ -373,32 +373,28 @@ namespace stim{ |
373 | 373 | ///Retrieves the index for a supported argument, given that argument's name. |
374 | 374 | |
375 | 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 | 388 | ///Sets an argument to a specified value |
387 | 389 | |
388 | 390 | /// @param _name is the name of the argument to be set |
389 | 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 | 400 | ///Parses the command line |
... | ... | @@ -449,10 +445,9 @@ namespace stim{ |
449 | 445 | /// @param _name is the name of the argument |
450 | 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 | 451 | std::cout<<"ERROR - Unspecified parameter name: "<<_name<<std::endl; |
457 | 452 | exit(1); |
458 | 453 | } |
... | ... | @@ -463,12 +458,11 @@ namespace stim{ |
463 | 458 | ///Returns the number of parameters for a specified argument |
464 | 459 | |
465 | 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 | 466 | std::cout<<"ERROR - Unspecified parameter name: "<<_name<<std::endl; |
473 | 467 | exit(1); |
474 | 468 | } |
... | ... | @@ -477,14 +471,14 @@ namespace stim{ |
477 | 471 | } |
478 | 472 | |
479 | 473 | ///Returns the number of arguments that have been set |
480 | - unsigned int nargs(){ | |
474 | + size_t nargs(){ | |
481 | 475 | return args.size(); |
482 | 476 | } |
483 | 477 | |
484 | 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 | 482 | if(opts[i].is_set()) n++; //if a value is specified, increment the counter |
489 | 483 | return n; |
490 | 484 | } |
... | ... | @@ -492,7 +486,7 @@ namespace stim{ |
492 | 486 | ///Returns the name of an argument, given its index |
493 | 487 | |
494 | 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 | 490 | return args[a]; |
497 | 491 | } |
498 | 492 | |
... | ... | @@ -501,7 +495,7 @@ namespace stim{ |
501 | 495 | /// @param _name is the name of the requested argument |
502 | 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 | 500 | if(i < 0 || i >= opts.size()) |
507 | 501 | { | ... | ... |
stim/parser/filename.h
... | ... | @@ -305,7 +305,7 @@ public: |
305 | 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 | 310 | std::stringstream ss; |
311 | 311 | ss << std::setw(n) << std::setfill('0') << i; | ... | ... |
stim/visualization/colormap.h
... | ... | @@ -36,7 +36,7 @@ namespace stim{ |
36 | 36 | |
37 | 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 | 41 | /*unsigned char* non_interleaved = (unsigned char*)malloc(x_size * y_size * 3); |
42 | 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 | 216 | #endif |
217 | 217 | |
218 | 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 | 223 | //compute the normalized value on [minVal maxVal] |
224 | 224 | float a; |
... | ... | @@ -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 | 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 | 263 | if(cm == cmBrewer) |
... | ... | @@ -279,15 +279,15 @@ static void cpu2cpu(T* cpuSource, unsigned char* cpuDest, unsigned int nVals, T |
279 | 279 | if(a < 0) a = 0; |
280 | 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 | 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 | 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 | 313 | |
314 | 314 | |
315 | 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 | 318 | //allocate a color buffer |
319 | 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 | 329 | } |
330 | 330 | |
331 | 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 | 334 | //allocate a color buffer |
335 | 335 | unsigned char* cpuBuffer = (unsigned char*) malloc(sizeof(unsigned char) * 3 * x_size * y_size); | ... | ... |