[cimg] 05/11: Imported Upstream version 1.7.1+dfsg

Andreas Tille tille at debian.org
Tue May 3 09:03:08 UTC 2016


This is an automated email from the git hooks/post-receive script.

tille pushed a commit to branch master
in repository cimg.

commit 4aaf4bdef204039e6a19af5eef51c0ec28b53949
Author: Andreas Tille <tille at debian.org>
Date:   Tue May 3 10:47:03 2016 +0200

    Imported Upstream version 1.7.1+dfsg
---
 CImg.h                              | 12033 ++++++++++++++++++++++++----------
 README.txt                          |     1 +
 examples/CImg_demo.cpp              |    65 +-
 examples/Makefile                   |   128 +-
 examples/captcha.cpp                |     2 +-
 examples/img/CImg_demo.h            |  4101 +-----------
 examples/odykill.cpp                |    14 +-
 examples/wavelet_atrous.cpp         |   124 +-
 html/CImg_documentation.h           |    28 +-
 html/footer.html                    |     4 -
 html/footer_reference.html          |     3 -
 html/header.html                    |     8 +-
 html/header_reference.html          |     8 +-
 html/img/postcard54.jpg             |   Bin 0 -> 25464 bytes
 html/img/postcard55.jpg             |   Bin 0 -> 14124 bytes
 html/img/postcard56.jpg             |   Bin 0 -> 43128 bytes
 html/img/postcard57.jpg             |   Bin 0 -> 20102 bytes
 html/img/postcard58.jpg             |   Bin 0 -> 18893 bytes
 html/img/postcard59.jpg             |   Bin 0 -> 24580 bytes
 html/img/postcard60.jpg             |   Bin 0 -> 16121 bytes
 html/img/postcard61.jpg             |   Bin 0 -> 22115 bytes
 html/img/postcard62.jpg             |   Bin 0 -> 27065 bytes
 html/index.shtml                    |    30 +-
 html/style.css                      |   208 +-
 plugins/chlpca.h                    |     4 +-
 plugins/tiff_stream.h               |     2 +-
 resources/cimg_buildpackage         |    10 +-
 resources/compile_win_visualcpp.bat |     2 +-
 28 files changed, 8822 insertions(+), 7953 deletions(-)

diff --git a/CImg.h b/CImg.h
index 5ba4839..40ab0a5 100644
--- a/CImg.h
+++ b/CImg.h
@@ -54,7 +54,7 @@
 
 // Set version number of the library.
 #ifndef cimg_version
-#define cimg_version 165
+#define cimg_version 171
 
 /*-----------------------------------------------------------
  #
@@ -75,6 +75,7 @@
 #include <cstdarg>
 #include <cstring>
 #include <cmath>
+#include <cfloat>
 #include <climits>
 #include <ctime>
 #include <exception>
@@ -110,6 +111,7 @@
 #ifdef _MSC_VER
 #pragma warning(push)
 #pragma warning(disable:4127)
+#pragma warning(disable:4244)
 #pragma warning(disable:4311)
 #pragma warning(disable:4312)
 #pragma warning(disable:4512)
@@ -122,6 +124,7 @@
 #pragma warning(disable:4820)
 #pragma warning(disable:4996)
 #define _CRT_SECURE_NO_DEPRECATE 1
+#define _CRT_SECURE_NO_WARNINGS 1
 #define _CRT_NONSTDC_NO_DEPRECATE 1
 #endif
 
@@ -158,6 +161,9 @@
 #ifndef NOMINMAX
 #define NOMINMAX
 #endif
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
 #include <windows.h>
 #ifndef _WIN32_IE
 #define _WIN32_IE 0x0400
@@ -167,15 +173,34 @@
 #include <io.h>
 #endif
 
-// Look for C++11 features
+// Look for C++11 features.
 #if !defined(cimg_use_cpp11) && __cplusplus>201100
-#define cimg_use_cpp11
+#define cimg_use_cpp11 1
 #endif
-#ifdef cimg_use_cpp11
+#if defined(cimg_use_cpp11) && cimg_use_cpp11!=0
 #include <initializer_list>
 #include <utility>
 #endif
 
+// Define own types 'cimg_long/ulong' and 'cimg_int64/uint64' to ensure portability.
+// ( constrained to 'sizeof(cimg_ulong/cimg_long) = sizeof(void*)' and 'sizeof(cimg_int64/cimg_uint64)=8' ).
+#if cimg_OS==2
+#define cimg_uint64 unsigned __int64
+#define cimg_int64 __int64
+#define cimg_ulong UINT_PTR
+#define cimg_long INT_PTR
+#else
+#if UINTPTR_MAX==0xffffffff
+#define cimg_uint64 unsigned long long
+#define cimg_int64 long long
+#else
+#define cimg_uint64 unsigned long
+#define cimg_int64 long
+#endif
+#define cimg_ulong unsigned long
+#define cimg_long long
+#endif
+
 // Configure the 'abort' signal handler (does nothing by default).
 // A typical signal handler can be defined in your own source like this:
 // Without OpenMP support: #define cimg_test_abort() if (is_abort) throw CImgAbortException("")
@@ -188,6 +213,9 @@
 #ifndef cimg_test_abort
 #define cimg_test_abort()
 #endif
+#ifndef cimg_test_abort2
+#define cimg_test_abort2()
+#endif
 
 // Configure filename separator.
 //
@@ -212,7 +240,11 @@
 //
 // Define 'cimg_use_vt100' to allow output of color messages on VT100-compatible terminals.
 #ifndef cimg_verbosity
+#if cimg_OS==2
 #define cimg_verbosity 2
+#else
+#define cimg_verbosity 1
+#endif
 #elif !(cimg_verbosity==0 || cimg_verbosity==1 || cimg_verbosity==2 || cimg_verbosity==3 || cimg_verbosity==4)
 #error CImg Library: Configuration variable 'cimg_verbosity' is badly defined.
 #error (should be { 0=quiet | 1=console | 2=dialog | 3=console+warnings | 4=dialog+warnings }).
@@ -227,11 +259,7 @@
 #if cimg_OS==0
 #define cimg_display 0
 #elif cimg_OS==1
-#if defined(__MACOSX__) || defined(__APPLE__)
-#define cimg_display 1
-#else
 #define cimg_display 1
-#endif
 #elif cimg_OS==2
 #define cimg_display 2
 #endif
@@ -702,7 +730,7 @@ extern "C" {
 #define cimg_for(img,ptrs,T_ptrs) \
   for (T_ptrs *ptrs = (img)._data, *_max##ptrs = (img)._data + (img).size(); ptrs<_max##ptrs; ++ptrs)
 #define cimg_rof(img,ptrs,T_ptrs) for (T_ptrs *ptrs = (img)._data + (img).size() - 1; ptrs>=(img)._data; --ptrs)
-#define cimg_foroff(img,off) for (unsigned long off = 0, _max##off = (img).size(); off<_max##off; ++off)
+#define cimg_foroff(img,off) for (cimg_ulong off = 0, _max##off = (img).size(); off<_max##off; ++off)
 
 #define cimg_for1(bound,i) for (int i = 0; i<(int)(bound); ++i)
 #define cimg_forX(img,x) cimg_for1((img)._width,x)
@@ -2075,26 +2103,26 @@ namespace cimg_library_suffixed {
 
   // Declare cimg:: namespace.
   // This is an uncomplete namespace definition here. It only contains some
-  // necessary stuffs to ensure a correct declaration order of the classes and functions
+  // necessary stuff to ensure a correct declaration order of the classes and functions
   // defined afterwards.
   namespace cimg {
 
     // Define ascii sequences for colored terminal output.
 #ifdef cimg_use_vt100
-    const char t_normal[] = { 0x1b, '[', '0', ';', '0', ';', '0', 'm', 0 };
-    const char t_black[] = { 0x1b, '[', '0', ';', '3', '0', ';', '5', '9', 'm', 0 };
-    const char t_red[] = { 0x1b, '[', '0', ';', '3', '1', ';', '5', '9', 'm', 0 };
-    const char t_green[] = { 0x1b, '[', '0', ';', '3', '2', ';', '5', '9', 'm', 0 };
-    const char t_yellow[] = { 0x1b, '[', '0', ';', '3', '3', ';', '5', '9', 'm', 0 };
-    const char t_blue[] = { 0x1b, '[', '0', ';', '3', '4', ';', '5', '9', 'm', 0 };
-    const char t_magenta[] = { 0x1b, '[', '0', ';', '3', '5', ';', '5', '9', 'm', 0 };
-    const char t_cyan[] = { 0x1b, '[', '0', ';', '3', '6', ';', '5', '9', 'm', 0 };
-    const char t_white[] = { 0x1b, '[', '0', ';', '3', '7', ';', '5', '9', 'm', 0 };
-    const char t_bold[] = { 0x1b, '[', '1', 'm', 0 };
-    const char t_underscore[] = { 0x1b, '[', '4', 'm', 0 };
+    static const char t_normal[] = { 0x1b, '[', '0', ';', '0', ';', '0', 'm', 0 };
+    static const char t_black[] = { 0x1b, '[', '0', ';', '3', '0', ';', '5', '9', 'm', 0 };
+    static const char t_red[] = { 0x1b, '[', '0', ';', '3', '1', ';', '5', '9', 'm', 0 };
+    static const char t_green[] = { 0x1b, '[', '0', ';', '3', '2', ';', '5', '9', 'm', 0 };
+    static const char t_yellow[] = { 0x1b, '[', '0', ';', '3', '3', ';', '5', '9', 'm', 0 };
+    static const char t_blue[] = { 0x1b, '[', '0', ';', '3', '4', ';', '5', '9', 'm', 0 };
+    static const char t_magenta[] = { 0x1b, '[', '0', ';', '3', '5', ';', '5', '9', 'm', 0 };
+    static const char t_cyan[] = { 0x1b, '[', '0', ';', '3', '6', ';', '5', '9', 'm', 0 };
+    static const char t_white[] = { 0x1b, '[', '0', ';', '3', '7', ';', '5', '9', 'm', 0 };
+    static const char t_bold[] = { 0x1b, '[', '1', 'm', 0 };
+    static const char t_underscore[] = { 0x1b, '[', '4', 'm', 0 };
 #else
-    const char t_normal[] = { 0 };
-    const char *const t_black = cimg::t_normal,
+    static const char t_normal[] = { 0 };
+    static const char *const t_black = cimg::t_normal,
       *const t_red = cimg::t_normal,
       *const t_green = cimg::t_normal,
       *const t_yellow = cimg::t_normal,
@@ -2120,9 +2148,7 @@ namespace cimg_library_suffixed {
 
     inline unsigned int& _exception_mode(const unsigned int value, const bool is_set) {
       static unsigned int mode = cimg_verbosity;
-      cimg::mutex(0);
-      if (is_set) mode = value;
-      cimg::mutex(0,0);
+      if (is_set) { cimg::mutex(0); mode = value<4?value:4; cimg::mutex(0,0); }
       return mode;
     }
 
@@ -2209,6 +2235,31 @@ namespace cimg_library_suffixed {
       return _exception_mode(0,false);
     }
 
+    //! Set current \CImg openmp mode.
+    /**
+       The way openmp-based methods are handled by \CImg can be changed dynamically, using this function.
+       \param mode Desired openmp mode. Possible values are:
+       - \c 0: Never parallelize (quiet mode).
+       - \c 1: Always parallelize.
+       - \c 2: Adaptive parallelization mode (default behavior).
+     **/
+    inline unsigned int& _openmp_mode(const unsigned int value, const bool is_set) {
+      static unsigned int mode = 2;
+      if (is_set)  { cimg::mutex(0); mode = value<2?value:2; cimg::mutex(0,0); }
+      return mode;
+    }
+
+    inline unsigned int& openmp_mode(const unsigned int mode) {
+      return _openmp_mode(mode,true);
+    }
+
+    //! Return current \CImg openmp mode.
+    inline unsigned int& openmp_mode() {
+      return _openmp_mode(0,false);
+    }
+
+#define cimg_openmp_if(cond) if (cimg::openmp_mode()==1 || (cimg::openmp_mode()>1 && (cond)))
+
     // Display a simple dialog box, and wait for the user's response.
     inline int dialog(const char *const title, const char *const msg, const char *const button1_label="OK",
                       const char *const button2_label=0, const char *const button3_label=0,
@@ -2218,6 +2269,7 @@ namespace cimg_library_suffixed {
     // Evaluate math expression.
     inline double eval(const char *const expression,
                        const double x=0, const double y=0, const double z=0, const double c=0);
+
   }
 
   /*---------------------------------------
@@ -2292,25 +2344,37 @@ namespace cimg_library_suffixed {
   **/
   struct CImgException : public std::exception {
 #define _cimg_exception_err(etype,disp_flag) \
-  std::va_list ap; va_start(ap,format); cimg_vsnprintf(_message,16384,format,ap); va_end(ap); \
-  if (cimg::exception_mode()) { \
-    std::fprintf(cimg::output(),"\n%s[CImg] *** %s ***%s %s\n",cimg::t_red,etype,cimg::t_normal,_message); \
-    if (cimg_display && disp_flag && !(cimg::exception_mode()%2)) try { cimg::dialog(etype,_message,"Abort"); } \
-    catch (CImgException&) {} \
-    if (cimg::exception_mode()>=3) cimg_library_suffixed::cimg::info(); \
-  }
+  std::va_list ap, ap2; \
+  va_start(ap,format); va_start(ap2,format); \
+  int size = cimg_vsnprintf(0,0,format,ap2); \
+  if (size++>=0) { \
+    delete[] _message; \
+    _message = new char[size]; \
+    cimg_vsnprintf(_message,size,format,ap); \
+    if (cimg::exception_mode()) { \
+      std::fprintf(cimg::output(),"\n%s[CImg] *** %s ***%s %s\n",cimg::t_red,etype,cimg::t_normal,_message); \
+      if (cimg_display && disp_flag && !(cimg::exception_mode()%2)) try { cimg::dialog(etype,_message,"Abort"); } \
+      catch (CImgException&) {} \
+      if (cimg::exception_mode()>=3) cimg_library_suffixed::cimg::info(); \
+    } \
+  } \
+  va_end(ap); va_end(ap2); \
 
     char *_message;
-    CImgException() { _message = new char[16384]; *_message = 0; }
-    CImgException(const char *const format, ...) {
-      _message = new char[16384]; *_message = 0; _cimg_exception_err("CImgException",true);
-    }
-    CImgException(const CImgException& e) {
-      _message = new char[16384]; strncpy(_message,e._message,16383); _message[16383] = 0;
+    CImgException() { _message = new char[1]; *_message = 0; }
+    CImgException(const char *const format, ...):_message(0) { _cimg_exception_err("CImgException",true); }
+    CImgException(const CImgException& e):std::exception(e) {
+      const size_t size = std::strlen(e._message);
+      _message = new char[size + 1];
+      std::strncpy(_message,e._message,size);
+      _message[size] = 0;
     }
     ~CImgException() throw() { delete[] _message; }
     CImgException& operator=(const CImgException& e) {
-      strncpy(_message,e._message,16383); _message[16383] = 0;
+      const size_t size = std::strlen(e._message);
+      _message = new char[size + 1];
+      std::strncpy(_message,e._message,size);
+      _message[size] = 0;
       return *this;
     }
     //! Return a C-string containing the error message associated to the thrown exception.
@@ -2321,16 +2385,20 @@ namespace cimg_library_suffixed {
   // a computationally-intensive function has been aborted by an external signal.
   struct CImgAbortException : public std::exception {
     char *_message;
-    CImgAbortException() { _message = new char[16384]; *_message = 0; }
-    CImgAbortException(const char *const format, ...) {
-      _message = new char[16384]; *_message = 0; _cimg_exception_err("CImgAbortException",true);
-    }
-    CImgAbortException(const CImgAbortException& e) {
-      _message = new char[16384]; strncpy(_message,e._message,16383); _message[16383] = 0;
+    CImgAbortException() { _message = new char[1]; *_message = 0; }
+    CImgAbortException(const char *const format, ...):_message(0) { _cimg_exception_err("CImgAbortException",true); }
+    CImgAbortException(const CImgAbortException& e):std::exception(e) {
+      const size_t size = std::strlen(e._message);
+      _message = new char[size + 1];
+      std::strncpy(_message,e._message,size);
+      _message[size] = 0;
     }
     ~CImgAbortException() throw() { delete[] _message; }
     CImgAbortException& operator=(const CImgAbortException& e) {
-      strncpy(_message,e._message,16383); _message[16383] = 0;
+      const size_t size = std::strlen(e._message);
+      _message = new char[size + 1];
+      std::strncpy(_message,e._message,size);
+      _message[size] = 0;
       return *this;
     }
     //! Return a C-string containing the error message associated to the thrown exception.
@@ -2397,7 +2465,7 @@ namespace cimg_library_suffixed {
       static bool is_inf(const T) { return false; }
       static bool is_nan(const T) { return false; }
       static T min() { return ~max(); }
-      static T max() { return (T)(1UL<<(8*sizeof(T) - 1)); }
+      static T max() { return (T)1<<(8*sizeof(T) - 1); }
       static T inf() { return max(); }
       static T cut(const double val) { return val<(double)min()?min():val>(double)max()?max():(T)val; }
       static const char* format() { return "%s"; }
@@ -2529,31 +2597,31 @@ namespace cimg_library_suffixed {
       static int format(const int val) { return val; }
     };
 
-    template<> struct type<unsigned long> {
-      static const char* string() { static const char *const s = "unsigned long"; return s; }
+    template<> struct type<cimg_uint64> {
+      static const char* string() { static const char *const s = "unsigned int64"; return s; }
       static bool is_float() { return false; }
-      static bool is_inf(const unsigned long) { return false; }
-      static bool is_nan(const unsigned long) { return false; }
-      static unsigned long min() { return 0; }
-      static unsigned long max() { return (unsigned long)-1; }
-      static unsigned long inf() { return max(); }
-      static unsigned long cut(const double val) {
-        return val<(double)min()?min():val>(double)max()?max():(unsigned long)val; }
+      static bool is_inf(const cimg_uint64) { return false; }
+      static bool is_nan(const cimg_uint64) { return false; }
+      static cimg_uint64 min() { return 0; }
+      static cimg_uint64 max() { return (cimg_uint64)-1; }
+      static cimg_uint64 inf() { return max(); }
+      static cimg_uint64 cut(const double val) {
+        return val<(double)min()?min():val>(double)max()?max():(cimg_uint64)val; }
       static const char* format() { return "%lu"; }
-      static unsigned long format(const unsigned long val) { return val; }
+      static unsigned long format(const cimg_uint64 val) { return (unsigned long)val; }
     };
 
-    template<> struct type<long> {
-      static const char* string() { static const char *const s = "long"; return s; }
+    template<> struct type<cimg_int64> {
+      static const char* string() { static const char *const s = "int64"; return s; }
       static bool is_float() { return false; }
-      static bool is_inf(const long) { return false; }
-      static bool is_nan(const long) { return false; }
-      static long min() { return ~max(); }
-      static long max() { return (long)((unsigned long)-1>>1); }
-      static long inf() { return max(); }
-      static long cut(const double val) { return val<(double)min()?min():val>(double)max()?max():(long)val; }
+      static bool is_inf(const cimg_int64) { return false; }
+      static bool is_nan(const cimg_int64) { return false; }
+      static cimg_int64 min() { return ~max(); }
+      static cimg_int64 max() { return (cimg_int64)((cimg_uint64)-1>>1); }
+      static cimg_int64 inf() { return max(); }
+      static cimg_int64 cut(const double val) { return val<(double)min()?min():val>(double)max()?max():(cimg_int64)val; }
       static const char* format() { return "%ld"; }
-      static long format(const long val) { return val; }
+      static long format(const long val) { return (long)val; }
     };
 
     template<> struct type<double> {
@@ -2573,10 +2641,22 @@ namespace cimg_library_suffixed {
         return !(val==val);
 #endif
       }
-      static double min() { return -1.7E308; }
-      static double max() { return  1.7E308; }
-      static double inf() { return max()*max(); }
-      static double nan() { const double val_nan = -std::sqrt(-1.0); return val_nan; }
+      static double min() { return -DBL_MAX; }
+      static double max() { return DBL_MAX; }
+      static double inf() {
+#ifdef INFINITY
+        return (double)INFINITY;
+#else
+        return max()*max();
+#endif
+      }
+      static double nan() {
+#ifdef NAN
+        return (double)NAN;
+#else
+        const double val_nan = -std::sqrt(-1.0); return val_nan;
+#endif
+      }
       static double cut(const double val) { return val<min()?min():val>max()?max():val; }
       static const char* format() { return "%.16g"; }
       static double format(const double val) { return val; }
@@ -2599,8 +2679,8 @@ namespace cimg_library_suffixed {
         return !(val==val);
 #endif
       }
-      static float min() { return -3.4E38f; }
-      static float max() { return  3.4E38f; }
+      static float min() { return -FLT_MAX; }
+      static float max() { return FLT_MAX; }
       static float inf() { return (float)cimg::type<double>::inf(); }
       static float nan() { return (float)cimg::type<double>::nan(); }
       static float cut(const double val) { return val<(double)min()?min():val>(double)max()?max():(float)val; }
@@ -2608,6 +2688,32 @@ namespace cimg_library_suffixed {
       static double format(const float val) { return (double)val; }
     };
 
+    template<> struct type<long double> {
+      static const char* string() { static const char *const s = "long double"; return s; }
+      static bool is_float() { return true; }
+      static bool is_inf(const long double val) {
+#ifdef isinf
+        return (bool)isinf(val);
+#else
+        return !is_nan(val) && (val<cimg::type<long double>::min() || val>cimg::type<long double>::max());
+#endif
+      }
+      static bool is_nan(const long double val) {
+#ifdef isnan
+        return (bool)isnan(val);
+#else
+        return !(val==val);
+#endif
+      }
+      static long double min() { return -LDBL_MAX; }
+      static long double max() { return LDBL_MAX; }
+      static long double inf() { return max()*max(); }
+      static long double nan() { const long double val_nan = -std::sqrt(-1.0L); return val_nan; }
+      static long double cut(const long double val) { return val<min()?min():val>max()?max():val; }
+      static const char* format() { return "%.16g"; }
+      static double format(const long double val) { return (double)val; }
+    };
+
     template<typename T, typename t> struct superset { typedef T type; };
     template<> struct superset<bool,unsigned char> { typedef unsigned char type; };
     template<> struct superset<bool,char> { typedef char type; };
@@ -2616,8 +2722,8 @@ namespace cimg_library_suffixed {
     template<> struct superset<bool,short> { typedef short type; };
     template<> struct superset<bool,unsigned int> { typedef unsigned int type; };
     template<> struct superset<bool,int> { typedef int type; };
-    template<> struct superset<bool,unsigned long> { typedef unsigned long type; };
-    template<> struct superset<bool,long> { typedef long type; };
+    template<> struct superset<bool,cimg_uint64> { typedef cimg_uint64 type; };
+    template<> struct superset<bool,cimg_int64> { typedef cimg_int64 type; };
     template<> struct superset<bool,float> { typedef float type; };
     template<> struct superset<bool,double> { typedef double type; };
     template<> struct superset<unsigned char,char> { typedef short type; };
@@ -2626,28 +2732,28 @@ namespace cimg_library_suffixed {
     template<> struct superset<unsigned char,short> { typedef short type; };
     template<> struct superset<unsigned char,unsigned int> { typedef unsigned int type; };
     template<> struct superset<unsigned char,int> { typedef int type; };
-    template<> struct superset<unsigned char,unsigned long> { typedef unsigned long type; };
-    template<> struct superset<unsigned char,long> { typedef long type; };
+    template<> struct superset<unsigned char,cimg_uint64> { typedef cimg_uint64 type; };
+    template<> struct superset<unsigned char,cimg_int64> { typedef cimg_int64 type; };
     template<> struct superset<unsigned char,float> { typedef float type; };
     template<> struct superset<unsigned char,double> { typedef double type; };
     template<> struct superset<signed char,unsigned char> { typedef short type; };
     template<> struct superset<signed char,char> { typedef short type; };
     template<> struct superset<signed char,unsigned short> { typedef int type; };
     template<> struct superset<signed char,short> { typedef short type; };
-    template<> struct superset<signed char,unsigned int> { typedef long type; };
+    template<> struct superset<signed char,unsigned int> { typedef cimg_int64 type; };
     template<> struct superset<signed char,int> { typedef int type; };
-    template<> struct superset<signed char,unsigned long> { typedef long type; };
-    template<> struct superset<signed char,long> { typedef long type; };
+    template<> struct superset<signed char,cimg_uint64> { typedef cimg_int64 type; };
+    template<> struct superset<signed char,cimg_int64> { typedef cimg_int64 type; };
     template<> struct superset<signed char,float> { typedef float type; };
     template<> struct superset<signed char,double> { typedef double type; };
     template<> struct superset<char,unsigned char> { typedef short type; };
     template<> struct superset<char,signed char> { typedef short type; };
     template<> struct superset<char,unsigned short> { typedef int type; };
     template<> struct superset<char,short> { typedef short type; };
-    template<> struct superset<char,unsigned int> { typedef long type; };
+    template<> struct superset<char,unsigned int> { typedef cimg_int64 type; };
     template<> struct superset<char,int> { typedef int type; };
-    template<> struct superset<char,unsigned long> { typedef long type; };
-    template<> struct superset<char,long> { typedef long type; };
+    template<> struct superset<char,cimg_uint64> { typedef cimg_int64 type; };
+    template<> struct superset<char,cimg_int64> { typedef cimg_int64 type; };
     template<> struct superset<char,float> { typedef float type; };
     template<> struct superset<char,double> { typedef double type; };
     template<> struct superset<unsigned short,char> { typedef int type; };
@@ -2655,39 +2761,39 @@ namespace cimg_library_suffixed {
     template<> struct superset<unsigned short,short> { typedef int type; };
     template<> struct superset<unsigned short,unsigned int> { typedef unsigned int type; };
     template<> struct superset<unsigned short,int> { typedef int type; };
-    template<> struct superset<unsigned short,unsigned long> { typedef unsigned long type; };
-    template<> struct superset<unsigned short,long> { typedef long type; };
+    template<> struct superset<unsigned short,cimg_uint64> { typedef cimg_uint64 type; };
+    template<> struct superset<unsigned short,cimg_int64> { typedef cimg_int64 type; };
     template<> struct superset<unsigned short,float> { typedef float type; };
     template<> struct superset<unsigned short,double> { typedef double type; };
     template<> struct superset<short,unsigned short> { typedef int type; };
-    template<> struct superset<short,unsigned int> { typedef long type; };
+    template<> struct superset<short,unsigned int> { typedef cimg_int64 type; };
     template<> struct superset<short,int> { typedef int type; };
-    template<> struct superset<short,unsigned long> { typedef long type; };
-    template<> struct superset<short,long> { typedef long type; };
+    template<> struct superset<short,cimg_uint64> { typedef cimg_int64 type; };
+    template<> struct superset<short,cimg_int64> { typedef cimg_int64 type; };
     template<> struct superset<short,float> { typedef float type; };
     template<> struct superset<short,double> { typedef double type; };
-    template<> struct superset<unsigned int,char> { typedef long type; };
-    template<> struct superset<unsigned int,signed char> { typedef long type; };
-    template<> struct superset<unsigned int,short> { typedef long type; };
-    template<> struct superset<unsigned int,int> { typedef long type; };
-    template<> struct superset<unsigned int,unsigned long> { typedef unsigned long type; };
-    template<> struct superset<unsigned int,long> { typedef long type; };
+    template<> struct superset<unsigned int,char> { typedef cimg_int64 type; };
+    template<> struct superset<unsigned int,signed char> { typedef cimg_int64 type; };
+    template<> struct superset<unsigned int,short> { typedef cimg_int64 type; };
+    template<> struct superset<unsigned int,int> { typedef cimg_int64 type; };
+    template<> struct superset<unsigned int,cimg_uint64> { typedef cimg_uint64 type; };
+    template<> struct superset<unsigned int,cimg_int64> { typedef cimg_int64 type; };
     template<> struct superset<unsigned int,float> { typedef float type; };
     template<> struct superset<unsigned int,double> { typedef double type; };
-    template<> struct superset<int,unsigned int> { typedef long type; };
-    template<> struct superset<int,unsigned long> { typedef long type; };
-    template<> struct superset<int,long> { typedef long type; };
+    template<> struct superset<int,unsigned int> { typedef cimg_int64 type; };
+    template<> struct superset<int,cimg_uint64> { typedef cimg_int64 type; };
+    template<> struct superset<int,cimg_int64> { typedef cimg_int64 type; };
     template<> struct superset<int,float> { typedef float type; };
     template<> struct superset<int,double> { typedef double type; };
-    template<> struct superset<unsigned long,char> { typedef long type; };
-    template<> struct superset<unsigned long,signed char> { typedef long type; };
-    template<> struct superset<unsigned long,short> { typedef long type; };
-    template<> struct superset<unsigned long,int> { typedef long type; };
-    template<> struct superset<unsigned long,long> { typedef long type; };
-    template<> struct superset<unsigned long,float> { typedef double type; };
-    template<> struct superset<unsigned long,double> { typedef double type; };
-    template<> struct superset<long,float> { typedef double type; };
-    template<> struct superset<long,double> { typedef double type; };
+    template<> struct superset<cimg_uint64,char> { typedef cimg_int64 type; };
+    template<> struct superset<cimg_uint64,signed char> { typedef cimg_int64 type; };
+    template<> struct superset<cimg_uint64,short> { typedef cimg_int64 type; };
+    template<> struct superset<cimg_uint64,int> { typedef cimg_int64 type; };
+    template<> struct superset<cimg_uint64,cimg_int64> { typedef cimg_int64 type; };
+    template<> struct superset<cimg_uint64,float> { typedef double type; };
+    template<> struct superset<cimg_uint64,double> { typedef double type; };
+    template<> struct superset<cimg_int64,float> { typedef double type; };
+    template<> struct superset<cimg_int64,double> { typedef double type; };
     template<> struct superset<float,double> { typedef double type; };
 
     template<typename t1, typename t2, typename t3> struct superset2 {
@@ -2700,9 +2806,9 @@ namespace cimg_library_suffixed {
 
     template<typename t1, typename t2> struct last { typedef t2 type; };
 
-#define _cimg_Tt       typename cimg::superset<T,t>::type
-#define _cimg_Tfloat   typename cimg::superset<T,float>::type
-#define _cimg_Ttfloat  typename cimg::superset2<T,t,float>::type
+#define _cimg_Tt typename cimg::superset<T,t>::type
+#define _cimg_Tfloat typename cimg::superset<T,float>::type
+#define _cimg_Ttfloat typename cimg::superset2<T,t,float>::type
 #define _cimg_Ttdouble typename cimg::superset2<T,t,double>::type
 
     // Define variables used internally by CImg.
@@ -3091,7 +3197,7 @@ namespace cimg_library_suffixed {
     const double PI = 3.14159265358979323846;   //!< Value of the mathematical constant PI
 
     // Define a 12x13 font (small size).
-    const char *const data_font12x13 =
+    static const char *const data_font12x13 =
 "                          .wjwlwmyuw>wjwkwbwjwkwRxuwmwjwkwmyuwJwjwlx`w      Fw                         mwlwlwuwnwuynwuwmyTwlwkwuwmwuwnwlwkwuwmwuw_wuxl"
 "wlwkwuwnwuynwuwTwlwlwtwnwtwnw my     Qw   +wlw   b{ \\w  Wx`xTw_w[wbxawSwkw  nynwky<x1w `y    ,w  Xwuw   CxlwiwlwmyuwbwuwUwiwlwbwiwrwqw^wuwmxuwnwiwlwmy"
 "uwJwiwlw^wnwEymymymymy1w^wkxnxtxnw<| gybwkwuwjwtwowmxswnxnwkxlxkw:wlymxlymykwn{myo{nymy2ykwqwqwm{myozn{o{mzpwrwpwkwkwswowkwqwqxswnyozlyozmzp}pwrwqwqwq"
@@ -3131,7 +3237,7 @@ namespace cimg_library_suffixed {
 "wlxm";
 
     // Define a 20x23 font (normal size).
-    const char *const data_font20x23 =
+    static const char *const data_font20x23 =
 "                                                9q\\q^r_rnp`qnq`plp7q\\q^q_qmqbq\\q^q_qmqHqmp_q\\q^r_rnp`qnq7q\\q^q_qmq_q \"r                               "
 "                        Mq^q^qnq`pnr`qnq`plp6q^q^pmp`qmqaq^q^pmp`qmqIpmq]q^q^qnq`pnr`qnq6q^q^pmp`qmq`q \"plp         'q     5qmq               Vq      "
 "               Xq    [plp      3qYq_p^rnpLplp8qYq_qNqYq_q4rmpaqYq_q_rmp%qYq^pGq  Irc|!pKp]raqjq`p   HtNq_qmq\\plqbp_shpdscq[q^q[p [q]s_r`uau]rbv`tcxbua"
@@ -3199,7 +3305,7 @@ namespace cimg_library_suffixed {
 "r^q                               *q                                                                                   kr               i";
 
     // Define a 47x53 font (extra-large size).
-    const char *const data_font47x53 =
+    static const char *const data_font47x53 =
 "                                                                                                                                                      "
 "        9])]2_2]T\\8^U^3]  E])]2`4^U^>])]2_4^U^ 6^T\\5])]1_2]T\\8^U^  K])]2`4^V^3]                                                                       "
 "                                                                                                                    U]*\\2a4`V\\8^U^5a  F]*\\1\\X\\4^U^=]*\\"
@@ -3392,7 +3498,7 @@ namespace cimg_library_suffixed {
 "                                                F]']2]    +]']2^ D]']3_   E]']1]   \"]']2^ 8]                             H";
 
     // Define a 90x103 font (huge size).
-    const char *const _data_font90x103[] = {  // Defined as an array to avoid MS compiler limit about constant string (65Kb).
+    static const char *const _data_font90x103[] = {  // Defined as an array to avoid MS compiler limit about constant string (65Kb).
       // Start of first string.
 "                                                                                                                                                      "
 "                                                                                                                                                      "
@@ -3932,7 +4038,7 @@ namespace cimg_library_suffixed {
 "                                                                                                                              D" };
 
     // Define a 40x38 'danger' color logo (used by cimg::dialog()).
-    const unsigned char logo40x38[4576] = {
+    static const unsigned char logo40x38[4576] = {
       177,200,200,200,3,123,123,0,36,200,200,200,1,123,123,0,2,255,255,0,1,189,189,189,1,0,0,0,34,200,200,200,
       1,123,123,0,4,255,255,0,1,189,189,189,1,0,0,0,1,123,123,123,32,200,200,200,1,123,123,0,5,255,255,0,1,0,0,
       0,2,123,123,123,30,200,200,200,1,123,123,0,6,255,255,0,1,189,189,189,1,0,0,0,2,123,123,123,29,200,200,200,
@@ -4018,7 +4124,7 @@ namespace cimg_library_suffixed {
 #ifdef cimg_strict_warnings
         throw CImgWarningException(message);
 #else
-        std::fprintf(cimg::output(),"\n%s[CImg] *** Warning ***%s%s",cimg::t_red,cimg::t_normal,message);
+        std::fprintf(cimg::output(),"\n%s[CImg] *** Warning ***%s%s\n",cimg::t_red,cimg::t_normal,message);
 #endif
         delete[] message;
       }
@@ -4039,7 +4145,7 @@ namespace cimg_library_suffixed {
       return -1;
 #else
 #if cimg_OS==1
-      const unsigned int l = std::strlen(command);
+      const unsigned int l = (unsigned int)std::strlen(command);
       if (l) {
         char *const ncommand = new char[l + 16];
         std::strncpy(ncommand,command,l);
@@ -4059,7 +4165,7 @@ namespace cimg_library_suffixed {
       si.dwFlags |= SW_HIDE | STARTF_USESHOWWINDOW;
       const BOOL res = CreateProcess((LPCTSTR)module_name,(LPTSTR)command,0,0,FALSE,0,0,0,&si,&pi);
       if (res) {
-        WaitForSingleObject(pi.hProcess, INFINITE);
+        WaitForSingleObject(pi.hProcess,INFINITE);
         CloseHandle(pi.hThread);
         CloseHandle(pi.hProcess);
         return 0;
@@ -4138,25 +4244,25 @@ namespace cimg_library_suffixed {
        \param size Number of buffer elements to reverse.
     **/
     template<typename T>
-    inline void invert_endianness(T* const buffer, const unsigned long size) {
+    inline void invert_endianness(T* const buffer, const cimg_ulong size) {
       if (size) switch (sizeof(T)) {
-      case 1 : break;
-      case 2 : { for (unsigned short *ptr = (unsigned short*)buffer + size; ptr>(unsigned short*)buffer; ) {
-        const unsigned short val = *(--ptr);
-        *ptr = (unsigned short)((val>>8)|((val<<8)));
-      }
-      } break;
-      case 4 : { for (unsigned int *ptr = (unsigned int*)buffer + size; ptr>(unsigned int*)buffer; ) {
-        const unsigned int val = *(--ptr);
-        *ptr = (val>>24)|((val>>8)&0xff00)|((val<<8)&0xff0000)|(val<<24);
-      }
-      } break;
-      default : { for (T* ptr = buffer + size; ptr>buffer; ) {
-        unsigned char *pb = (unsigned char*)(--ptr), *pe = pb + sizeof(T);
-        for (int i = 0; i<(int)sizeof(T)/2; ++i) swap(*(pb++),*(--pe));
-      }
-      }
-      }
+        case 1 : break;
+        case 2 : { for (unsigned short *ptr = (unsigned short*)buffer + size; ptr>(unsigned short*)buffer; ) {
+              const unsigned short val = *(--ptr);
+              *ptr = (unsigned short)((val>>8)|((val<<8)));
+            }
+        } break;
+        case 4 : { for (unsigned int *ptr = (unsigned int*)buffer + size; ptr>(unsigned int*)buffer; ) {
+              const unsigned int val = *(--ptr);
+              *ptr = (val>>24)|((val>>8)&0xff00)|((val<<8)&0xff0000)|(val<<24);
+            }
+        } break;
+        default : { for (T* ptr = buffer + size; ptr>buffer; ) {
+              unsigned char *pb = (unsigned char*)(--ptr), *pe = pb + sizeof(T);
+              for (int i = 0; i<(int)sizeof(T)/2; ++i) swap(*(pb++),*(--pe));
+            }
+        }
+        }
     }
 
     //! Reverse endianness of a single variable.
@@ -4194,28 +4300,28 @@ namespace cimg_library_suffixed {
     /**
        \note The timer does not necessarily starts from \c 0.
     **/
-    inline unsigned long time() {
+    inline cimg_ulong time() {
 #if cimg_OS==1
       struct timeval st_time;
       gettimeofday(&st_time,0);
-      return (unsigned long)(st_time.tv_usec/1000 + st_time.tv_sec*1000);
+      return (cimg_ulong)(st_time.tv_usec/1000 + st_time.tv_sec*1000);
 #elif cimg_OS==2
       SYSTEMTIME st_time;
       GetLocalTime(&st_time);
-      return (unsigned long)(st_time.wMilliseconds + 1000*(st_time.wSecond + 60*(st_time.wMinute + 60*st_time.wHour)));
+      return (cimg_ulong)(st_time.wMilliseconds + 1000*(st_time.wSecond + 60*(st_time.wMinute + 60*st_time.wHour)));
 #else
       return 0;
 #endif
     }
 
     // Implement a tic/toc mechanism to display elapsed time of algorithms.
-    inline unsigned long tictoc(const bool is_tic);
+    inline cimg_ulong tictoc(const bool is_tic);
 
     //! Start tic/toc timer for time measurement between code instructions.
     /**
        \return Current value of the timer (same value as time()).
     **/
-    inline unsigned long tic() {
+    inline cimg_ulong tic() {
       return cimg::tictoc(true);
     }
 
@@ -4223,7 +4329,7 @@ namespace cimg_library_suffixed {
     /**
        \return Time elapsed (in ms) since last call to tic().
     **/
-    inline unsigned long toc() {
+    inline cimg_ulong toc() {
       return cimg::tictoc(false);
     }
 
@@ -4244,14 +4350,14 @@ namespace cimg_library_suffixed {
 #endif
     }
 
-    inline unsigned int _wait(const unsigned int milliseconds, unsigned long& timer) {
+    inline unsigned int _wait(const unsigned int milliseconds, cimg_ulong& timer) {
       if (!timer) timer = cimg::time();
-      const unsigned long current_time = cimg::time();
+      const cimg_ulong current_time = cimg::time();
       if (current_time>=timer + milliseconds) { timer = current_time; return 0; }
-      const unsigned long time_diff = timer + milliseconds - current_time;
+      const unsigned int time_diff = (unsigned int)(timer + milliseconds - current_time);
       timer = current_time + time_diff;
       cimg::sleep(time_diff);
-      return (unsigned int)time_diff;
+      return time_diff;
     }
 
     //! Wait for a given number of milliseconds since the last call to wait().
@@ -4261,9 +4367,9 @@ namespace cimg_library_suffixed {
        \note Same as sleep() with a waiting time computed with regard to the last call
        of wait(). It may be used to temporize your program properly, without wasting CPU time.
     **/
-    inline unsigned int wait(const unsigned int milliseconds) {
+    inline cimg_long wait(const unsigned int milliseconds) {
       cimg::mutex(3);
-      static unsigned long timer = 0;
+      static cimg_ulong timer = 0;
       if (!timer) timer = cimg::time();
       cimg::mutex(3,0);
       return _wait(milliseconds,timer);
@@ -4279,9 +4385,9 @@ namespace cimg_library_suffixed {
 
     // Use a custom RNG.
     inline unsigned int _rand(const unsigned int seed=0, const bool set_seed=false) {
-      static unsigned long next = 0xB16B00B5;
+      static cimg_ulong next = 0xB16B00B5;
       cimg::mutex(4);
-      if (set_seed) next = (unsigned long)seed;
+      if (set_seed) next = (cimg_ulong)seed;
       next = next*1103515245 + 12345U;
       cimg::mutex(4,0);
       return (unsigned int)(next&0xFFFFFFU);
@@ -4302,8 +4408,9 @@ namespace cimg_library_suffixed {
       _rand(seed,true);
     }
 
-    inline double rand() {
-      return cimg::_rand()/16777215.;
+    inline double rand(const double val_min, const double val_max) {
+      const double val = cimg::_rand()/16777215.;
+      return val_min + (val_max - val_min)*val;
     }
 
 #else
@@ -4324,19 +4431,20 @@ namespace cimg_library_suffixed {
       std::srand(seed);
     }
 
-    //! Return a random variable between [0,1] with respect to an uniform distribution.
+    //! Return a random variable uniformely distributed between [val_min,val_max].
     /**
     **/
-    inline double rand() {
-      return (double)std::rand()/RAND_MAX;
+    inline double rand(const double val_min, const double val_max) {
+      const double val = (double)std::rand()/RAND_MAX;
+      return val_min + (val_max - val_min)*val;
     }
 #endif
 
-    //! Return a random variable between [-1,1] with respect to an uniform distribution.
+    //! Return a random variable uniformely distributed between [0,val_max].
     /**
-    **/
-    inline double crand() {
-      return 1 - 2*cimg::rand();
+     **/
+    inline double rand(const double val_max=1) {
+      return cimg::rand(0,val_max);
     }
 
     //! Return a random variable following a gaussian distribution and a standard deviation of 1.
@@ -4345,8 +4453,8 @@ namespace cimg_library_suffixed {
     inline double grand() {
       double x1, w;
       do {
-        const double x2 = 2*cimg::rand() - 1.0;
-        x1 = 2*cimg::rand() - 1.0;
+        const double x2 = cimg::rand(-1,1);
+        x1 = cimg::rand(-1,1);
         w = x1*x1 + x2*x2;
       } while (w<=0 || w>=1.0);
       return x1*std::sqrt((-2*std::log(w))/w);
@@ -4375,7 +4483,11 @@ namespace cimg_library_suffixed {
     }
 
     inline double rol(const double a, const unsigned int n=1) {
-      return (double)rol((long)a,n);
+      return (double)rol((cimg_long)a,n);
+    }
+
+    inline double rol(const long double a, const unsigned int n=1) {
+      return (double)rol((cimg_long)a,n);
     }
 
     //! Bitwise-rotate value on the right.
@@ -4389,7 +4501,11 @@ namespace cimg_library_suffixed {
     }
 
     inline double ror(const double a, const unsigned int n=1) {
-      return (double)ror((long)a,n);
+      return (double)ror((cimg_long)a,n);
+    }
+
+    inline double ror(const long double a, const unsigned int n=1) {
+      return (double)ror((cimg_long)a,n);
     }
 
     //! Return absolute value of a value.
@@ -4400,17 +4516,20 @@ namespace cimg_library_suffixed {
     inline bool abs(const bool a) {
       return a;
     }
-    inline unsigned char abs(const unsigned char a) {
-      return a;
+    inline int abs(const unsigned char a) {
+      return (int)a;
     }
-    inline unsigned short abs(const unsigned short a) {
-      return a;
+    inline int abs(const unsigned short a) {
+      return (int)a;
     }
-    inline unsigned int abs(const unsigned int a) {
-      return a;
+    inline int abs(const unsigned int a) {
+      return (int)a;
     }
-    inline unsigned long abs(const unsigned long a) {
-      return a;
+    inline int abs(const int a) {
+      return std::abs(a);
+    }
+    inline cimg_int64 abs(const cimg_uint64 a) {
+      return (cimg_int64)a;
     }
     inline double abs(const double a) {
       return std::fabs(a);
@@ -4418,9 +4537,6 @@ namespace cimg_library_suffixed {
     inline float abs(const float a) {
       return (float)std::fabs((double)a);
     }
-    inline int abs(const int a) {
-      return std::abs(a);
-    }
 
     //! Return square of a value.
     template<typename T>
@@ -4483,8 +4599,8 @@ namespace cimg_library_suffixed {
 
     //! Return the nearest power of 2 higher than given value.
     template<typename T>
-    inline unsigned long nearest_pow2(const T& x) {
-      unsigned long i = 1;
+    inline cimg_ulong nearest_pow2(const T& x) {
+      cimg_ulong i = 1;
       while (x>i) i<<=1;
       return i;
     }
@@ -4508,6 +4624,9 @@ namespace cimg_library_suffixed {
     inline int mod(const bool x, const bool m) {
       return m?(x?1:0):0;
     }
+    inline int mod(const unsigned char x, const unsigned char m) {
+      return x%m;
+    }
     inline int mod(const char x, const char m) {
 #if defined(CHAR_MAX) && CHAR_MAX==255
       return x%m;
@@ -4515,26 +4634,23 @@ namespace cimg_library_suffixed {
       return x>=0?x%m:(x%m?m + x%m:0);
 #endif
     }
+    inline int mod(const unsigned short x, const unsigned short m) {
+      return x%m;
+    }
     inline int mod(const short x, const short m) {
       return x>=0?x%m:(x%m?m + x%m:0);
     }
-    inline int mod(const int x, const int m) {
-      return x>=0?x%m:(x%m?m + x%m:0);
+    inline int mod(const unsigned int x, const unsigned int m) {
+      return (int)(x%m);
     }
-    inline int mod(const long x, const long m) {
+    inline int mod(const int x, const int m) {
       return x>=0?x%m:(x%m?m + x%m:0);
     }
-    inline int mod(const unsigned char x, const unsigned char m) {
+    inline cimg_int64 mod(const cimg_uint64 x, const cimg_uint64 m) {
       return x%m;
     }
-    inline int mod(const unsigned short x, const unsigned short m) {
-      return x%m;
-    }
-    inline int mod(const unsigned int x, const unsigned int m) {
-      return (int)(x%m);
-    }
-    inline int mod(const unsigned long x, const unsigned long m) {
-      return (long)(x%m);
+    inline cimg_int64 mod(const cimg_int64 x, const cimg_int64 m) {
+      return x>=0?x%m:(x%m?m + x%m:0);
     }
 
     //! Return the min-mod of two values.
@@ -4574,20 +4690,12 @@ namespace cimg_library_suffixed {
       else { const double tmp = absa/absb; return absb==0?0:absb*std::sqrt(1.0 + tmp*tmp); }
     }
 
-    inline bool _is_self_expr(const char *expression) {
-      if (!expression || *expression=='>' || *expression=='<') return false;
-      for (const char *s = expression; *s; ++s)
-        if ((*s=='i' || *s=='j') && (s[1]=='(' || s[1]=='[')) {
-          const char opening = s[1], ending = opening=='('?')':']';
-          const char *ns;
-          int level = 0;
-          for (ns = s + 2; *ns; ++ns) { // Find ending ')' or ']'.
-            if (*ns==ending && !level) break;
-            if (*ns==opening) ++level; else if (*ns==ending) --level;
-          }
-          if (*ns && (ns[1]!='=' || ns[2]=='=')) return true;
-        }
-      return false;
+    //! Return sqrt(x^2 + y^2).
+    inline double hypot(const double x, const double y) {
+      double nx = cimg::abs(x), ny = cimg::abs(y), t;
+      if (nx<ny) { t = nx; nx = ny; } else t = ny;
+      if (nx>0) { t/=nx; return nx*std::sqrt(1+t*t); }
+      return 0;
     }
 
     //! Convert ascii character to lower case.
@@ -4643,6 +4751,51 @@ namespace cimg_library_suffixed {
       return cimg::strncasecmp(str1,str2,1 + (l1<l2?l1:l2));
     }
 
+    //! Ellipsize a string.
+    /**
+       \param str C-string.
+       \param l Max number of characters.
+       \param is_ending Tell if the dots are placed at the end or at the center of the ellipsized string.
+    **/
+    inline char *strellipsize(char *const str, const unsigned int l=64,
+                              const bool is_ending=true) {
+      if (!str) return str;
+      const unsigned int nl = l<5?5:l, ls = (unsigned int)std::strlen(str);
+      if (ls<=nl) return str;
+      if (is_ending) std::strcpy(str + nl - 5,"(...)");
+      else {
+        const unsigned int ll = (nl - 5)/2 + 1 - (nl%2), lr = nl - ll - 5;
+        std::strcpy(str + ll,"(...)");
+        std::memmove(str + ll + 5,str + ls - lr,lr);
+      }
+      str[nl] = 0;
+      return str;
+    }
+
+    //! Ellipsize a string.
+    /**
+       \param str C-string.
+       \param res output C-string.
+       \param l Max number of characters.
+       \param is_ending Tell if the dots are placed at the end or at the center of the ellipsized string.
+    **/
+    inline char *strellipsize(const char *const str, char *const res, const unsigned int l=64,
+                              const bool is_ending=true) {
+      const unsigned int nl = l<5?5:l, ls = (unsigned int)std::strlen(str);
+      if (ls<=nl) { std::strcpy(res,str); return res; }
+      if (is_ending) {
+        std::strncpy(res,str,nl - 5);
+        std::strcpy(res + nl -5,"(...)");
+      } else {
+        const unsigned int ll = (nl - 5)/2 + 1 - (nl%2), lr = nl - ll - 5;
+        std::strncpy(res,str,ll);
+        std::strcpy(res + ll,"(...)");
+        std::strncpy(res + ll + 5,str + ls - lr,lr);
+      }
+      res[nl] = 0;
+      return res;
+    }
+
     //! Remove delimiters on the start and/or end of a C-string.
     /**
        \param[in,out] str C-string to work with (modified at output).
@@ -4706,32 +4859,32 @@ namespace cimg_library_suffixed {
             *nd = (char)val; break;
           case 'x' :
             cimg_sscanf(++ns,"%x",&val);
-            while ((*ns>='0' && *ns<='7') || (*ns>='a' && *ns<='f') || (*ns>='A' && *ns<='F')) ++ns;
+            while ((*ns>='0' && *ns<='9') || (*ns>='a' && *ns<='f') || (*ns>='A' && *ns<='F')) ++ns;
             *nd = (char)val; break;
           default : *nd = *(ns++);
           } else *nd = *(ns++);
     }
 
     // Return a temporary string describing the size of a memory buffer.
-    inline const char *strbuffersize(const unsigned long size);
+    inline const char *strbuffersize(const cimg_ulong size);
 
     // Return string that identifies the running OS.
     inline const char *stros() {
 #if defined(linux) || defined(__linux) || defined(__linux__)
-      const char *const str = "Linux";
+      static const char *const str = "Linux";
 #elif defined(sun) || defined(__sun)
-      const char *const str = "Sun OS";
+      static const char *const str = "Sun OS";
 #elif defined(BSD) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined (__DragonFly__)
-      const char *const str = "BSD";
+      static const char *const str = "BSD";
 #elif defined(sgi) || defined(__sgi)
-      const char *const str = "Irix";
+      static const char *const str = "Irix";
 #elif defined(__MACOSX__) || defined(__APPLE__)
-      const char *const str = "Mac OS";
+      static const char *const str = "Mac OS";
 #elif defined(unix) || defined(__unix) || defined(__unix__)
-      const char *const str = "Generic Unix";
+      static const char *const str = "Generic Unix";
 #elif defined(_MSC_VER) || defined(WIN32)  || defined(_WIN32) || defined(__WIN32__) || \
   defined(WIN64) || defined(_WIN64) || defined(__WIN64__)
-      const char *const str = "Windows";
+      static const char *const str = "Windows";
 #else
       const char
         *const _str1 = std::getenv("OSTYPE"),
@@ -4751,11 +4904,12 @@ namespace cimg_library_suffixed {
     // Return a random filename.
     inline const char* filenamerand() {
       cimg::mutex(6);
-      static char randomid[9] = { 0 };
+      static char randomid[9];
       cimg::srand();
       for (unsigned int k = 0; k<8; ++k) {
-        const int v = (int)std::rand()%3;
-        randomid[k] = (char)(v==0?('0' + (std::rand()%10)):(v==1?('a' + (std::rand()%26)):('A' + (std::rand()%26))));
+        const int v = (int)cimg::rand(65535)%3;
+        randomid[k] = (char)(v==0?('0' + ((int)cimg::rand(65535)%10)):
+                             (v==1?('a' + ((int)cimg::rand(65535)%26)):('A' + ((int)cimg::rand(65535)%26))));
       }
       cimg::mutex(6,0);
       return randomid;
@@ -4816,6 +4970,24 @@ namespace cimg_library_suffixed {
       return errn;
     }
 
+    //! Version of 'fseek()' that supports >=64bits offsets everywhere (for Windows).
+    inline int fseek(FILE *stream, cimg_long offset, int origin) {
+#if cimg_OS==2
+      return _fseeki64(stream,(__int64)offset,origin);
+#else
+      return std::fseek(stream,offset,origin);
+#endif
+    }
+
+    //! Version of 'ftell()' that supports >=64bits offsets everywhere (for Windows).
+    inline cimg_long ftell(FILE *stream) {
+#if cimg_OS==2
+      return (cimg_long)_ftelli64(stream);
+#else
+      return (cimg_long)std::ftell(stream);
+#endif
+    }
+
     //! Check if a path is a directory.
     /**
        \param path Specified path to test.
@@ -4883,7 +5055,7 @@ namespace cimg_library_suffixed {
                    Can be { 0=year | 1=month | 2=day | 3=day of week | 4=hour | 5=minute | 6=second }
     **/
     inline int date(const unsigned int attr) {
-      int res = -1;
+      int res;
       cimg::mutex(6);
 #if cimg_OS==2
       SYSTEMTIME st;
@@ -4974,23 +5146,23 @@ namespace cimg_library_suffixed {
        \note Same as <tt>std::fread()</tt> but may display warning message if all elements could not be read.
     **/
     template<typename T>
-    inline int fread(T *const ptr, const unsigned long nmemb, std::FILE *stream) {
+    inline size_t fread(T *const ptr, const size_t nmemb, std::FILE *stream) {
       if (!ptr || !stream)
         throw CImgArgumentException("cimg::fread(): Invalid reading request of %u %s%s from file %p to buffer %p.",
                                     nmemb,cimg::type<T>::string(),nmemb>1?"s":"",stream,ptr);
       if (!nmemb) return 0;
-      const unsigned long wlimitT = 63*1024*1024, wlimit = wlimitT/sizeof(T);
-      unsigned long to_read = nmemb, al_read = 0, l_to_read = 0, l_al_read = 0;
+      const size_t wlimitT = 63*1024*1024, wlimit = wlimitT/sizeof(T);
+      size_t to_read = nmemb, al_read = 0, l_to_read = 0, l_al_read = 0;
       do {
         l_to_read = (to_read*sizeof(T))<wlimitT?to_read:wlimit;
-        l_al_read = (unsigned long)std::fread((void*)(ptr + al_read),sizeof(T),l_to_read,stream);
+        l_al_read = std::fread((void*)(ptr + al_read),sizeof(T),l_to_read,stream);
         al_read+=l_al_read;
         to_read-=l_al_read;
       } while (l_to_read==l_al_read && to_read>0);
       if (to_read>0)
-        warn("cimg::fread(): Only %u/%u elements could be read from file.",
-             al_read,nmemb);
-      return (int)al_read;
+        warn("cimg::fread(): Only %lu/%lu elements could be read from file.",
+             (unsigned long)al_read,(unsigned long)nmemb);
+      return al_read;
     }
 
     //! Write data to file.
@@ -5002,23 +5174,23 @@ namespace cimg_library_suffixed {
        \note Similar to <tt>std::fwrite</tt> but may display warning messages if all elements could not be written.
     **/
     template<typename T>
-    inline int fwrite(const T *ptr, const unsigned long nmemb, std::FILE *stream) {
+    inline size_t fwrite(const T *ptr, const size_t nmemb, std::FILE *stream) {
       if (!ptr || !stream)
         throw CImgArgumentException("cimg::fwrite(): Invalid writing request of %u %s%s from buffer %p to file %p.",
                                     nmemb,cimg::type<T>::string(),nmemb>1?"s":"",ptr,stream);
       if (!nmemb) return 0;
-      const unsigned long wlimitT = 63*1024*1024, wlimit = wlimitT/sizeof(T);
-      unsigned long to_write = nmemb, al_write = 0, l_to_write = 0, l_al_write = 0;
+      const size_t wlimitT = 63*1024*1024, wlimit = wlimitT/sizeof(T);
+      size_t to_write = nmemb, al_write = 0, l_to_write = 0, l_al_write = 0;
       do {
         l_to_write = (to_write*sizeof(T))<wlimitT?to_write:wlimit;
-        l_al_write = (unsigned long)std::fwrite((void*)(ptr + al_write),sizeof(T),l_to_write,stream);
+        l_al_write = std::fwrite((void*)(ptr + al_write),sizeof(T),l_to_write,stream);
         al_write+=l_al_write;
         to_write-=l_al_write;
       } while (l_to_write==l_al_write && to_write>0);
       if (to_write>0)
-        warn("cimg::fwrite(): Only %u/%u elements could be written in file.",
-             al_write,nmemb);
-      return (int)al_write;
+        warn("cimg::fwrite(): Only %lu/%lu elements could be written in file.",
+             (unsigned long)al_write,(unsigned long)nmemb);
+      return al_write;
     }
 
     //! Create an empty file.
@@ -5038,7 +5210,8 @@ namespace cimg_library_suffixed {
 
     // Load file from network as a local temporary file.
     inline char *load_network(const char *const url, char *const filename_local,
-                              const unsigned int timeout=0, const bool try_fallback=false);
+                              const unsigned int timeout=0, const bool try_fallback=false,
+                              const char *const referer=0);
 
     //! Return options specified on the command line.
     inline const char* option(const char *const name, const int argc, const char *const *const argv,
@@ -5101,8 +5274,8 @@ namespace cimg_library_suffixed {
                        const char defaut, const char *const usage=0) {
       const char *const s = cimg::option(name,argc,argv,(char*)0);
       const char res = s?*s:defaut;
-      char tmp[8] = { 0 };
-      *tmp = res;
+      char tmp[8];
+      *tmp = res; tmp[1] = 0;
       cimg::option(name,0,0,tmp,usage);
       return res;
     }
@@ -5417,10 +5590,11 @@ namespace cimg_library_suffixed {
   _cimg_create_ext_operators(short)
   _cimg_create_ext_operators(unsigned int)
   _cimg_create_ext_operators(int)
-  _cimg_create_ext_operators(unsigned long)
-  _cimg_create_ext_operators(long)
+  _cimg_create_ext_operators(cimg_uint64)
+  _cimg_create_ext_operators(cimg_int64)
   _cimg_create_ext_operators(float)
   _cimg_create_ext_operators(double)
+  _cimg_create_ext_operators(long double)
 
   template<typename T>
   inline CImg<_cimg_Tfloat> operator+(const char *const expression, const CImg<T>& img) {
@@ -5429,7 +5603,7 @@ namespace cimg_library_suffixed {
 
   template<typename T>
   inline CImg<_cimg_Tfloat> operator-(const char *const expression, const CImg<T>& img) {
-    return CImg<_cimg_Tfloat>(img._width,img._height,img._depth,img._spectrum,expression,true)-=img;
+    return CImg<_cimg_Tfloat>(img,false).fill(expression,true)-=img;
   }
 
   template<typename T>
@@ -5459,12 +5633,12 @@ namespace cimg_library_suffixed {
 
   template<typename T>
   inline bool operator==(const char *const expression, const CImg<T>& img) {
-    return img == expression;
+    return img==expression;
   }
 
   template<typename T>
   inline bool operator!=(const char *const expression, const CImg<T>& img) {
-    return img != expression;
+    return img!=expression;
   }
 
   template<typename T>
@@ -5577,7 +5751,7 @@ namespace cimg_library_suffixed {
    # Define the CImgDisplay structure
    #
    ----------------------------------*/
-  //! Allow to create windows, display images on them and manage user events (keyboard, mouse and windows events).
+  //! Allow the creation of windows, display images on them and manage user events (keyboard, mouse and windows events).
   /**
      CImgDisplay methods rely on a low-level graphic library to perform: it can be either \b X-Window
      (X11, for Unix-based systems) or \b GDI32 (for Windows-based systems).
@@ -5595,7 +5769,7 @@ namespace cimg_library_suffixed {
      Remember to link your program against \b X11 or \b GDI32 libraries if you use CImgDisplay.
   **/
   struct CImgDisplay {
-    unsigned long _timer, _fps_frames, _fps_timer;
+    cimg_ulong _timer, _fps_frames, _fps_timer;
     unsigned int _width, _height, _normalization;
     float _fps_fps, _min, _max;
     bool _is_fullscreen;
@@ -5851,6 +6025,12 @@ namespace cimg_library_suffixed {
       return _empty.assign();
     }
 
+    //! Return a reference to an empty display \const.
+    static const CImgDisplay& const_empty() {
+      static const CImgDisplay _empty;
+      return _empty;
+    }
+
 #define cimg_fitscreen(dx,dy,dz) CImgDisplay::_fitscreen(dx,dy,dz,128,-85,false), \
                                  CImgDisplay::_fitscreen(dx,dy,dz,128,-85,true)
     static unsigned int _fitscreen(const unsigned int dx, const unsigned int dy, const unsigned int dz,
@@ -6482,11 +6662,14 @@ namespace cimg_library_suffixed {
         if (img._depth==1 && (img._spectrum==1 || img._spectrum>=3) && _normalization!=1) return display(img);
       }
       CImgList<typename CImg<T>::ucharT> visu(list._width);
+      unsigned int dims = 0;
       cimglist_for(list,l) {
         const CImg<T>& img = list._data[l];
         img.__get_select(*this,_normalization,(img._width - 1)/2,(img._height - 1)/2,
                          (img._depth - 1)/2).move_to(visu[l]);
+        dims = cimg::max(dims,visu[l]._spectrum);
       }
+      cimglist_for(list,l) if (visu[l]._spectrum<dims) visu[l].resize(-100,-100,-100,dims,1);
       visu.get_append(axis,align).display(*this);
       return *this;
     }
@@ -7391,8 +7574,8 @@ namespace cimg_library_suffixed {
       winattr.override_redirect = 1;
       _background_window = XCreateWindow(dpy,DefaultRootWindow(dpy),0,0,sx,sy,0,0,
                                          InputOutput,CopyFromParent,CWOverrideRedirect,&winattr);
-      const unsigned long buf_size = (unsigned long)sx*sy*(cimg::X11_attr().nb_bits==8?1:
-                                                           (cimg::X11_attr().nb_bits==16?2:4));
+      const cimg_ulong buf_size = (cimg_ulong)sx*sy*(cimg::X11_attr().nb_bits==8?1:
+                                                     (cimg::X11_attr().nb_bits==16?2:4));
       void *background_data = std::malloc(buf_size);
       std::memset(background_data,0,buf_size);
       XImage *background_image = XCreateImage(dpy,DefaultVisual(dpy,DefaultScreen(dpy)),cimg::X11_attr().nb_bits,
@@ -7446,7 +7629,7 @@ namespace cimg_library_suffixed {
 
       // Allocate space for window title
       const char *const nptitle = ptitle?ptitle:"";
-      const unsigned int s = std::strlen(nptitle) + 1;
+      const unsigned int s = (unsigned int)std::strlen(nptitle) + 1;
       char *const tmp_title = s?new char[s]:0;
       if (s) std::memcpy(tmp_title,nptitle,s*sizeof(char));
 
@@ -7558,8 +7741,8 @@ namespace cimg_library_suffixed {
       if (!_shminfo)
 #endif
         {
-          const unsigned long buf_size = (unsigned long)_width*_height*(cimg::X11_attr().nb_bits==8?1:
-                                                                        (cimg::X11_attr().nb_bits==16?2:4));
+          const cimg_ulong buf_size = (cimg_ulong)_width*_height*(cimg::X11_attr().nb_bits==8?1:
+                                                                  (cimg::X11_attr().nb_bits==16?2:4));
           _data = std::malloc(buf_size);
           _image = XCreateImage(dpy,DefaultVisual(dpy,DefaultScreen(dpy)),cimg::X11_attr().nb_bits,
                                 ZPixmap,0,(char*)_data,_width,_height,8,0);
@@ -7629,7 +7812,7 @@ namespace cimg_library_suffixed {
       _min = _max = 0;
       std::memset(_data,0,(cimg::X11_attr().nb_bits==8?sizeof(unsigned char):
                            (cimg::X11_attr().nb_bits==16?sizeof(unsigned short):sizeof(unsigned int)))*
-                  (unsigned long)_width*_height);
+                  (size_t)_width*_height);
       return paint();
     }
 
@@ -7666,7 +7849,7 @@ namespace cimg_library_suffixed {
       _assign(disp._width,disp._height,disp._title,disp._normalization,disp._is_fullscreen,disp._is_closed);
       std::memcpy(_data,disp._data,(cimg::X11_attr().nb_bits==8?sizeof(unsigned char):
                                     cimg::X11_attr().nb_bits==16?sizeof(unsigned short):
-                                    sizeof(unsigned int))*(unsigned long)_width*_height);
+                                    sizeof(unsigned int))*(size_t)_width*_height);
       return paint();
     }
 
@@ -7708,7 +7891,7 @@ namespace cimg_library_suffixed {
     CImgDisplay& toggle_fullscreen(const bool force_redraw=true) {
       if (is_empty()) return *this;
       if (force_redraw) {
-        const unsigned long buf_size = (unsigned long)_width*_height*
+        const cimg_ulong buf_size = (cimg_ulong)_width*_height*
           (cimg::X11_attr().nb_bits==8?1:(cimg::X11_attr().nb_bits==16?2:4));
         void *image_data = std::malloc(buf_size);
         std::memcpy(image_data,_data,buf_size);
@@ -7769,7 +7952,7 @@ namespace cimg_library_suffixed {
       if (is_empty()) return *this;
       Display *const dpy = cimg::X11_attr().display;
       cimg_lock_display();
-      const char pix_data[8] = { 0 };
+      static const char pix_data[8] = { 0 };
       XColor col;
       col.red = col.green = col.blue = 0;
       Pixmap pix = XCreateBitmapFromData(dpy,_window,pix_data,8,8);
@@ -7801,7 +7984,7 @@ namespace cimg_library_suffixed {
       va_end(ap);
       if (!std::strcmp(_title,tmp)) { delete[] tmp; return *this; }
       delete[] _title;
-      const unsigned int s = std::strlen(tmp) + 1;
+      const unsigned int s = (unsigned int)std::strlen(tmp) + 1;
       _title = new char[s];
       std::memcpy(_title,tmp,s*sizeof(char));
       Display *const dpy = cimg::X11_attr().display;
@@ -7861,18 +8044,18 @@ namespace cimg_library_suffixed {
           _set_colormap(_colormap,img._spectrum);
           unsigned char
             *const ndata = (img._width==_width && img._height==_height)?(unsigned char*)_data:
-            new unsigned char[(unsigned long)img._width*img._height],
+            new unsigned char[(size_t)img._width*img._height],
             *ptrd = (unsigned char*)ndata;
           switch (img._spectrum) {
           case 1 :
-            for (unsigned long xy = (unsigned long)img._width*img._height; xy>0; --xy)
+            for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy)
               (*ptrd++) = (unsigned char)*(data1++);
             break;
-          case 2 : for (unsigned long xy = (unsigned long)img._width*img._height; xy>0; --xy) {
+          case 2 : for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) {
 	      const unsigned char R = (unsigned char)*(data1++), G = (unsigned char)*(data2++);
 	      (*ptrd++) = (R&0xf0) | (G>>4);
 	    } break;
-          default : for (unsigned long xy = (unsigned long)img._width*img._height; xy>0; --xy) {
+          default : for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) {
 	      const unsigned char
                 R = (unsigned char)*(data1++),
                 G = (unsigned char)*(data2++),
@@ -7887,17 +8070,17 @@ namespace cimg_library_suffixed {
         } break;
         case 16 : { // 16 bits colors, no normalization
           unsigned short *const ndata = (img._width==_width && img._height==_height)?(unsigned short*)_data:
-            new unsigned short[(unsigned long)img._width*img._height];
+            new unsigned short[(size_t)img._width*img._height];
           unsigned char *ptrd = (unsigned char*)ndata;
           const unsigned int M = 248;
           switch (img._spectrum) {
           case 1 :
             if (cimg::X11_attr().byte_order)
-              for (unsigned long xy = (unsigned long)img._width*img._height; xy>0; --xy) {
+              for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) {
                 const unsigned char val = (unsigned char)*(data1++), G = val>>2;
                 *(ptrd++) = (val&M) | (G>>3);
                 *(ptrd++) = (G<<5) | (G>>1);
-              } else for (unsigned long xy = (unsigned long)img._width*img._height; xy>0; --xy) {
+              } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) {
                 const unsigned char val = (unsigned char)*(data1++), G = val>>2;
                 *(ptrd++) = (G<<5) | (G>>1);
                 *(ptrd++) = (val&M) | (G>>3);
@@ -7905,11 +8088,11 @@ namespace cimg_library_suffixed {
             break;
           case 2 :
             if (cimg::X11_attr().byte_order)
-              for (unsigned long xy = (unsigned long)img._width*img._height; xy>0; --xy) {
+              for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) {
                 const unsigned char G = (unsigned char)*(data2++)>>2;
                 *(ptrd++) = ((unsigned char)*(data1++)&M) | (G>>3);
                 *(ptrd++) = (G<<5);
-              } else for (unsigned long xy = (unsigned long)img._width*img._height; xy>0; --xy) {
+              } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) {
                 const unsigned char G = (unsigned char)*(data2++)>>2;
                 *(ptrd++) = (G<<5);
                 *(ptrd++) = ((unsigned char)*(data1++)&M) | (G>>3);
@@ -7917,11 +8100,11 @@ namespace cimg_library_suffixed {
             break;
           default :
             if (cimg::X11_attr().byte_order)
-              for (unsigned long xy = (unsigned long)img._width*img._height; xy>0; --xy) {
+              for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) {
                 const unsigned char G = (unsigned char)*(data2++)>>2;
                 *(ptrd++) = ((unsigned char)*(data1++)&M) | (G>>3);
                 *(ptrd++) = (G<<5) | ((unsigned char)*(data3++)>>3);
-              } else for (unsigned long xy = (unsigned long)img._width*img._height; xy>0; --xy) {
+              } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) {
                 const unsigned char G = (unsigned char)*(data2++)>>2;
                 *(ptrd++) = (G<<5) | ((unsigned char)*(data3++)>>3);
                 *(ptrd++) = ((unsigned char)*(data1++)&M) | (G>>3);
@@ -7934,37 +8117,37 @@ namespace cimg_library_suffixed {
         } break;
         default : { // 24 bits colors, no normalization
           unsigned int *const ndata = (img._width==_width && img._height==_height)?(unsigned int*)_data:
-            new unsigned int[(unsigned long)img._width*img._height];
+            new unsigned int[(size_t)img._width*img._height];
           if (sizeof(int)==4) { // 32 bits int uses optimized version
             unsigned int *ptrd = ndata;
             switch (img._spectrum) {
             case 1 :
               if (cimg::X11_attr().byte_order==cimg::endianness())
-                for (unsigned long xy = (unsigned long)img._width*img._height; xy>0; --xy) {
+                for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) {
                   const unsigned char val = (unsigned char)*(data1++);
                   *(ptrd++) = (val<<16) | (val<<8) | val;
                 }
               else
-                for (unsigned long xy = (unsigned long)img._width*img._height; xy>0; --xy) {
+                for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) {
                  const unsigned char val = (unsigned char)*(data1++);
                   *(ptrd++) = (val<<16) | (val<<8) | val;
                 }
               break;
             case 2 :
               if (cimg::X11_attr().byte_order==cimg::endianness())
-                for (unsigned long xy = (unsigned long)img._width*img._height; xy>0; --xy)
+                for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy)
                   *(ptrd++) = ((unsigned char)*(data1++)<<16) | ((unsigned char)*(data2++)<<8);
               else
-                for (unsigned long xy = (unsigned long)img._width*img._height; xy>0; --xy)
+                for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy)
                   *(ptrd++) = ((unsigned char)*(data2++)<<16) | ((unsigned char)*(data1++)<<8);
               break;
             default :
               if (cimg::X11_attr().byte_order==cimg::endianness())
-                for (unsigned long xy = (unsigned long)img._width*img._height; xy>0; --xy)
+                for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy)
                   *(ptrd++) = ((unsigned char)*(data1++)<<16) | ((unsigned char)*(data2++)<<8) |
                     (unsigned char)*(data3++);
               else
-                for (unsigned long xy = (unsigned long)img._width*img._height; xy>0; --xy)
+                for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy)
                   *(ptrd++) = ((unsigned char)*(data3++)<<24) | ((unsigned char)*(data2++)<<16) |
                     ((unsigned char)*(data1++)<<8);
             }
@@ -7973,12 +8156,12 @@ namespace cimg_library_suffixed {
             switch (img._spectrum) {
             case 1 :
               if (cimg::X11_attr().byte_order)
-                for (unsigned long xy = (unsigned long)img._width*img._height; xy>0; --xy) {
+                for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) {
                   *(ptrd++) = 0;
                   *(ptrd++) = (unsigned char)*(data1++);
                   *(ptrd++) = 0;
                   *(ptrd++) = 0;
-                } else for (unsigned long xy = (unsigned long)img._width*img._height; xy>0; --xy) {
+                } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) {
                   *(ptrd++) = 0;
                   *(ptrd++) = 0;
                   *(ptrd++) = (unsigned char)*(data1++);
@@ -7987,7 +8170,7 @@ namespace cimg_library_suffixed {
               break;
             case 2 :
               if (cimg::X11_attr().byte_order) cimg::swap(data1,data2);
-              for (unsigned long xy = (unsigned long)img._width*img._height; xy>0; --xy) {
+              for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) {
                 *(ptrd++) = 0;
                 *(ptrd++) = (unsigned char)*(data2++);
                 *(ptrd++) = (unsigned char)*(data1++);
@@ -7996,12 +8179,12 @@ namespace cimg_library_suffixed {
               break;
             default :
               if (cimg::X11_attr().byte_order)
-                for (unsigned long xy = (unsigned long)img._width*img._height; xy>0; --xy) {
+                for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) {
                   *(ptrd++) = 0;
                   *(ptrd++) = (unsigned char)*(data1++);
                   *(ptrd++) = (unsigned char)*(data2++);
                   *(ptrd++) = (unsigned char)*(data3++);
-                } else for (unsigned long xy = (unsigned long)img._width*img._height; xy>0; --xy) {
+                } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) {
                   *(ptrd++) = (unsigned char)*(data3++);
                   *(ptrd++) = (unsigned char)*(data2++);
                   *(ptrd++) = (unsigned char)*(data1++);
@@ -8025,21 +8208,21 @@ namespace cimg_library_suffixed {
         case 8 : { // 256 colormap, with normalization
           _set_colormap(_colormap,img._spectrum);
           unsigned char *const ndata = (img._width==_width && img._height==_height)?(unsigned char*)_data:
-            new unsigned char[(unsigned long)img._width*img._height];
+            new unsigned char[(size_t)img._width*img._height];
           unsigned char *ptrd = (unsigned char*)ndata;
           switch (img._spectrum) {
-          case 1 : for (unsigned long xy = (unsigned long)img._width*img._height; xy>0; --xy) {
+          case 1 : for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) {
               const unsigned char R = (unsigned char)((*(data1++) - _min)*mm);
               *(ptrd++) = R;
             } break;
-          case 2 : for (unsigned long xy = (unsigned long)img._width*img._height; xy>0; --xy) {
+          case 2 : for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) {
               const unsigned char
                 R = (unsigned char)((*(data1++) - _min)*mm),
                 G = (unsigned char)((*(data2++) - _min)*mm);
             (*ptrd++) = (R&0xf0) | (G>>4);
           } break;
           default :
-            for (unsigned long xy = (unsigned long)img._width*img._height; xy>0; --xy) {
+            for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) {
               const unsigned char
                 R = (unsigned char)((*(data1++) - _min)*mm),
                 G = (unsigned char)((*(data2++) - _min)*mm),
@@ -8054,17 +8237,17 @@ namespace cimg_library_suffixed {
         } break;
         case 16 : { // 16 bits colors, with normalization
           unsigned short *const ndata = (img._width==_width && img._height==_height)?(unsigned short*)_data:
-            new unsigned short[(unsigned long)img._width*img._height];
+            new unsigned short[(size_t)img._width*img._height];
           unsigned char *ptrd = (unsigned char*)ndata;
           const unsigned int M = 248;
           switch (img._spectrum) {
           case 1 :
             if (cimg::X11_attr().byte_order)
-              for (unsigned long xy = (unsigned long)img._width*img._height; xy>0; --xy) {
+              for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) {
                 const unsigned char val = (unsigned char)((*(data1++) - _min)*mm), G = val>>2;
                 *(ptrd++) = (val&M) | (G>>3);
                 *(ptrd++) = (G<<5) | (val>>3);
-              } else for (unsigned long xy = (unsigned long)img._width*img._height; xy>0; --xy) {
+              } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) {
                 const unsigned char val = (unsigned char)((*(data1++) - _min)*mm), G = val>>2;
                 *(ptrd++) = (G<<5) | (val>>3);
                 *(ptrd++) = (val&M) | (G>>3);
@@ -8072,11 +8255,11 @@ namespace cimg_library_suffixed {
             break;
           case 2 :
             if (cimg::X11_attr().byte_order)
-              for (unsigned long xy = (unsigned long)img._width*img._height; xy>0; --xy) {
+              for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) {
                 const unsigned char G = (unsigned char)((*(data2++) - _min)*mm)>>2;
                 *(ptrd++) = ((unsigned char)((*(data1++) - _min)*mm)&M) | (G>>3);
                 *(ptrd++) = (G<<5);
-              } else for (unsigned long xy = (unsigned long)img._width*img._height; xy>0; --xy) {
+              } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) {
                 const unsigned char G = (unsigned char)((*(data2++) - _min)*mm)>>2;
                 *(ptrd++) = (G<<5);
                 *(ptrd++) = ((unsigned char)((*(data1++) - _min)*mm)&M) | (G>>3);
@@ -8084,11 +8267,11 @@ namespace cimg_library_suffixed {
             break;
           default :
             if (cimg::X11_attr().byte_order)
-              for (unsigned long xy = (unsigned long)img._width*img._height; xy>0; --xy) {
+              for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) {
                 const unsigned char G = (unsigned char)((*(data2++) - _min)*mm)>>2;
                 *(ptrd++) = ((unsigned char)((*(data1++) - _min)*mm)&M) | (G>>3);
                 *(ptrd++) = (G<<5) | ((unsigned char)((*(data3++) - _min)*mm)>>3);
-              } else for (unsigned long xy = (unsigned long)img._width*img._height; xy>0; --xy) {
+              } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) {
                 const unsigned char G = (unsigned char)((*(data2++) - _min)*mm)>>2;
                 *(ptrd++) = (G<<5) | ((unsigned char)((*(data3++) - _min)*mm)>>3);
                 *(ptrd++) = ((unsigned char)((*(data1++) - _min)*mm)&M) | (G>>3);
@@ -8101,43 +8284,43 @@ namespace cimg_library_suffixed {
         } break;
         default : { // 24 bits colors, with normalization
           unsigned int *const ndata = (img._width==_width && img._height==_height)?(unsigned int*)_data:
-            new unsigned int[(unsigned long)img._width*img._height];
+            new unsigned int[(size_t)img._width*img._height];
           if (sizeof(int)==4) { // 32 bits int uses optimized version
             unsigned int *ptrd = ndata;
             switch (img._spectrum) {
             case 1 :
               if (cimg::X11_attr().byte_order==cimg::endianness())
-                for (unsigned long xy = (unsigned long)img._width*img._height; xy>0; --xy) {
+                for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) {
                   const unsigned char val = (unsigned char)((*(data1++) - _min)*mm);
                   *(ptrd++) = (val<<16) | (val<<8) | val;
                 }
               else
-                for (unsigned long xy = (unsigned long)img._width*img._height; xy>0; --xy) {
+                for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) {
                   const unsigned char val = (unsigned char)((*(data1++) - _min)*mm);
                   *(ptrd++) = (val<<24) | (val<<16) | (val<<8);
                 }
               break;
             case 2 :
               if (cimg::X11_attr().byte_order==cimg::endianness())
-                for (unsigned long xy = (unsigned long)img._width*img._height; xy>0; --xy)
+                for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy)
                   *(ptrd++) =
                     ((unsigned char)((*(data1++) - _min)*mm)<<16) |
                     ((unsigned char)((*(data2++) - _min)*mm)<<8);
               else
-                for (unsigned long xy = (unsigned long)img._width*img._height; xy>0; --xy)
+                for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy)
                   *(ptrd++) =
                     ((unsigned char)((*(data2++) - _min)*mm)<<16) |
                     ((unsigned char)((*(data1++) - _min)*mm)<<8);
               break;
             default :
               if (cimg::X11_attr().byte_order==cimg::endianness())
-                for (unsigned long xy = (unsigned long)img._width*img._height; xy>0; --xy)
+                for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy)
                   *(ptrd++) =
                     ((unsigned char)((*(data1++) - _min)*mm)<<16) |
                     ((unsigned char)((*(data2++) - _min)*mm)<<8) |
                     (unsigned char)((*(data3++) - _min)*mm);
               else
-                for (unsigned long xy = (unsigned long)img._width*img._height; xy>0; --xy)
+                for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy)
                   *(ptrd++) =
                     ((unsigned char)((*(data3++) - _min)*mm)<<24) |
                     ((unsigned char)((*(data2++) - _min)*mm)<<16) |
@@ -8148,13 +8331,13 @@ namespace cimg_library_suffixed {
             switch (img._spectrum) {
             case 1 :
               if (cimg::X11_attr().byte_order)
-                for (unsigned long xy = (unsigned long)img._width*img._height; xy>0; --xy) {
+                for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) {
                   const unsigned char val = (unsigned char)((*(data1++) - _min)*mm);
                   (*ptrd++) = 0;
                   (*ptrd++) = val;
                   (*ptrd++) = val;
                   (*ptrd++) = val;
-                } else for (unsigned long xy = (unsigned long)img._width*img._height; xy>0; --xy) {
+                } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) {
                   const unsigned char val = (unsigned char)((*(data1++) - _min)*mm);
                   (*ptrd++) = val;
                   (*ptrd++) = val;
@@ -8164,7 +8347,7 @@ namespace cimg_library_suffixed {
               break;
             case 2 :
               if (cimg::X11_attr().byte_order) cimg::swap(data1,data2);
-              for (unsigned long xy = (unsigned long)img._width*img._height; xy>0; --xy) {
+              for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) {
                 (*ptrd++) = 0;
                 (*ptrd++) = (unsigned char)((*(data2++) - _min)*mm);
                 (*ptrd++) = (unsigned char)((*(data1++) - _min)*mm);
@@ -8173,12 +8356,12 @@ namespace cimg_library_suffixed {
               break;
             default :
               if (cimg::X11_attr().byte_order)
-                for (unsigned long xy = (unsigned long)img._width*img._height; xy>0; --xy) {
+                for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) {
                   (*ptrd++) = 0;
                   (*ptrd++) = (unsigned char)((*(data1++) - _min)*mm);
                   (*ptrd++) = (unsigned char)((*(data2++) - _min)*mm);
                   (*ptrd++) = (unsigned char)((*(data3++) - _min)*mm);
-                } else for (unsigned long xy = (unsigned long)img._width*img._height; xy>0; --xy) {
+                } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) {
                   (*ptrd++) = (unsigned char)((*(data3++) - _min)*mm);
                   (*ptrd++) = (unsigned char)((*(data2++) - _min)*mm);
                   (*ptrd++) = (unsigned char)((*(data1++) - _min)*mm);
@@ -8209,7 +8392,7 @@ namespace cimg_library_suffixed {
       if (cimg::X11_attr().is_blue_first) cimg::swap(data1,data3);
       switch (cimg::X11_attr().nb_bits) {
       case 8 : {
-        for (unsigned long xy = (unsigned long)img._width*img._height; xy>0; --xy) {
+        for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) {
           const unsigned char val = *(ptrs++);
           *(data1++) = (T)(val&0xe0);
           *(data2++) = (T)((val&0x1c)<<3);
@@ -8217,12 +8400,12 @@ namespace cimg_library_suffixed {
         }
       } break;
       case 16 : {
-        if (cimg::X11_attr().byte_order) for (unsigned long xy = (unsigned long)img._width*img._height; xy>0; --xy) {
+        if (cimg::X11_attr().byte_order) for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) {
           const unsigned char val0 = *(ptrs++), val1 = *(ptrs++);
           *(data1++) = (T)(val0&0xf8);
           *(data2++) = (T)((val0<<5) | ((val1&0xe0)>>5));
           *(data3++) = (T)(val1<<3);
-          } else for (unsigned long xy = (unsigned long)img._width*img._height; xy>0; --xy) {
+          } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) {
           const unsigned short val0 = *(ptrs++), val1 = *(ptrs++);
           *(data1++) = (T)(val1&0xf8);
           *(data2++) = (T)((val1<<5) | ((val0&0xe0)>>5));
@@ -8230,12 +8413,12 @@ namespace cimg_library_suffixed {
         }
       } break;
       default : {
-        if (cimg::X11_attr().byte_order) for (unsigned long xy = (unsigned long)img._width*img._height; xy>0; --xy) {
+        if (cimg::X11_attr().byte_order) for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) {
           ++ptrs;
           *(data1++) = (T)*(ptrs++);
           *(data2++) = (T)*(ptrs++);
           *(data3++) = (T)*(ptrs++);
-          } else for (unsigned long xy = (unsigned long)img._width*img._height; xy>0; --xy) {
+          } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) {
             *(data3++) = (T)*(ptrs++);
             *(data2++) = (T)*(ptrs++);
             *(data1++) = (T)*(ptrs++);
@@ -8413,7 +8596,7 @@ namespace cimg_library_suffixed {
       disp->_bmi.bmiHeader.biYPelsPerMeter = 1;
       disp->_bmi.bmiHeader.biClrUsed = 0;
       disp->_bmi.bmiHeader.biClrImportant = 0;
-      disp->_data = new unsigned int[(unsigned long)disp->_width*disp->_height];
+      disp->_data = new unsigned int[(size_t)disp->_width*disp->_height];
       if (!disp->_is_fullscreen) { // Normal window
         RECT rect;
         rect.left = rect.top = 0; rect.right = (LONG)disp->_width - 1; rect.bottom = (LONG)disp->_height - 1;
@@ -8653,7 +8836,7 @@ namespace cimg_library_suffixed {
     CImgDisplay& toggle_fullscreen(const bool force_redraw=true) {
       if (is_empty()) return *this;
       if (force_redraw) {
-        const unsigned long buf_size = _width*_height*4UL;
+        const cimg_ulong buf_size = (cimg_ulong)_width*_height*4;
         void *odata = std::malloc(buf_size);
         if (odata) {
           std::memcpy(odata,_data,buf_size);
@@ -8717,7 +8900,7 @@ namespace cimg_library_suffixed {
     }
 
     CImgDisplay& set_mouse(const int posx, const int posy) {
-      if (_is_closed || posx<0 || posy<0) return *this;
+      if (is_empty() || _is_closed || posx<0 || posy<0) return *this;
       _update_window_pos();
       const int res = (int)SetCursorPos(_window_x + posx,_window_y + posy);
       if (res) { _mouse_x = posx; _mouse_y = posy; }
@@ -8778,20 +8961,20 @@ namespace cimg_library_suffixed {
       WaitForSingleObject(_mutex,INFINITE);
       unsigned int
         *const ndata = (img._width==_width && img._height==_height)?_data:
-        new unsigned int[(unsigned long)img._width*img._height],
+        new unsigned int[(size_t)img._width*img._height],
         *ptrd = ndata;
 
       if (!_normalization || (_normalization==3 && cimg::type<T>::string()==cimg::type<unsigned char>::string())) {
         _min = _max = 0;
         switch (img._spectrum) {
         case 1 : {
-          for (unsigned long xy = (unsigned long)img._width*img._height; xy>0; --xy) {
+          for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) {
             const unsigned char val = (unsigned char)*(data1++);
             *(ptrd++) = (unsigned int)((val<<16) | (val<<8) | val);
           }
         } break;
         case 2 : {
-          for (unsigned long xy = (unsigned long)img._width*img._height; xy>0; --xy) {
+          for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) {
             const unsigned char
               R = (unsigned char)*(data1++),
               G = (unsigned char)*(data2++);
@@ -8799,7 +8982,7 @@ namespace cimg_library_suffixed {
           }
         } break;
         default : {
-          for (unsigned long xy = (unsigned long)img._width*img._height; xy>0; --xy) {
+          for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) {
             const unsigned char
               R = (unsigned char)*(data1++),
               G = (unsigned char)*(data2++),
@@ -8816,13 +8999,13 @@ namespace cimg_library_suffixed {
         const float delta = _max - _min, mm = 255/(delta?delta:1.0f);
         switch (img._spectrum) {
         case 1 : {
-          for (unsigned long xy = (unsigned long)img._width*img._height; xy>0; --xy) {
+          for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) {
             const unsigned char val = (unsigned char)((*(data1++) - _min)*mm);
             *(ptrd++) = (unsigned int)((val<<16) | (val<<8) | val);
           }
         } break;
         case 2 : {
-          for (unsigned long xy = (unsigned long)img._width*img._height; xy>0; --xy) {
+          for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) {
             const unsigned char
               R = (unsigned char)((*(data1++) - _min)*mm),
               G = (unsigned char)((*(data2++) - _min)*mm);
@@ -8830,7 +9013,7 @@ namespace cimg_library_suffixed {
           }
         } break;
         default : {
-          for (unsigned long xy = (unsigned long)img._width*img._height; xy>0; --xy) {
+          for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) {
             const unsigned char
               R = (unsigned char)((*(data1++) - _min)*mm),
               G = (unsigned char)((*(data2++) - _min)*mm),
@@ -8854,7 +9037,7 @@ namespace cimg_library_suffixed {
         *data1 = img.data(0,0,0,0),
         *data2 = img.data(0,0,0,1),
         *data3 = img.data(0,0,0,2);
-      for (unsigned long xy = (unsigned long)img._width*img._height; xy>0; --xy) {
+      for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) {
         const unsigned int val = *(ptrs++);
         *(data1++) = (T)(unsigned char)(val>>16);
         *(data2++) = (T)(unsigned char)((val>>8)&0xFF);
@@ -8957,10 +9140,8 @@ namespace cimg_library_suffixed {
      - Construct images from C-style arrays:
          - <tt>CImg<int> img(data_buffer,256,256);</tt> constructs a 256x256 greyscale image from a \c int* buffer
          \c data_buffer (of size 256x256=65536).
-         - <tt>CImg<unsigned char> img(data_buffer,256,256,1,3,false);</tt> constructs a 256x256 color image
+         - <tt>CImg<unsigned char> img(data_buffer,256,256,1,3);</tt> constructs a 256x256 color image
          from a \c unsigned \c char* buffer \c data_buffer (where R,G,B channels follow each others).
-         - <tt>CImg<unsigned char> img(data_buffer,256,256,1,3,true);</tt> constructs a 256x256 color image
-         from a \c unsigned \c char* buffer \c data_buffer (where R,G,B channels are multiplexed).
 
          The complete list of constructors can be found <a href="#constructors">here</a>.
 
@@ -8969,7 +9150,7 @@ namespace cimg_library_suffixed {
      The \c CImg<T> class contains a lot of functions that operates on images.
      Some of the most useful are:
 
-     - operator()(): allows to access or write pixel values.
+     - operator()(): Read or write pixel values.
      - display(): displays the image in a new window.
   **/
   template<typename T>
@@ -9028,8 +9209,8 @@ namespace cimg_library_suffixed {
     typedef typename cimg::superset<T,short>::type Tshort;
     typedef typename cimg::superset<T,unsigned int>::type Tuint;
     typedef typename cimg::superset<T,int>::type Tint;
-    typedef typename cimg::superset<T,unsigned long>::type Tulong;
-    typedef typename cimg::superset<T,long>::type Tlong;
+    typedef typename cimg::superset<T,cimg_ulong>::type Tulong;
+    typedef typename cimg::superset<T,cimg_long>::type Tlong;
     typedef typename cimg::superset<T,float>::type Tfloat;
     typedef typename cimg::superset<T,double>::type Tdouble;
     typedef typename cimg::last<T,bool>::type boolT;
@@ -9039,8 +9220,10 @@ namespace cimg_library_suffixed {
     typedef typename cimg::last<T,short>::type shortT;
     typedef typename cimg::last<T,unsigned int>::type uintT;
     typedef typename cimg::last<T,int>::type intT;
-    typedef typename cimg::last<T,unsigned long>::type ulongT;
-    typedef typename cimg::last<T,long>::type longT;
+    typedef typename cimg::last<T,cimg_ulong>::type ulongT;
+    typedef typename cimg::last<T,cimg_long>::type longT;
+    typedef typename cimg::last<T,cimg_uint64>::type uint64T;
+    typedef typename cimg::last<T,cimg_int64>::type int64T;
     typedef typename cimg::last<T,float>::type floatT;
     typedef typename cimg::last<T,double>::type doubleT;
 
@@ -9144,7 +9327,7 @@ namespace cimg_library_suffixed {
     explicit CImg(const unsigned int size_x, const unsigned int size_y=1,
                   const unsigned int size_z=1, const unsigned int size_c=1):
       _is_shared(false) {
-      const unsigned long siz = (unsigned long)size_x*size_y*size_z*size_c;
+      size_t siz = (size_t)size_x*size_y*size_z*size_c;
       if (siz) {
         _width = size_x; _height = size_y; _depth = size_z; _spectrum = size_c;
         try { _data = new T[siz]; } catch (...) {
@@ -9176,7 +9359,7 @@ namespace cimg_library_suffixed {
     CImg(const unsigned int size_x, const unsigned int size_y,
          const unsigned int size_z, const unsigned int size_c, const T& value):
       _is_shared(false) {
-      const unsigned long siz = (unsigned long)size_x*size_y*size_z*size_c;
+      const size_t siz = (size_t)size_x*size_y*size_z*size_c;
       if (siz) {
         _width = size_x; _height = size_y; _depth = size_z; _spectrum = size_c;
         try { _data = new T[siz]; } catch (...) {
@@ -9223,7 +9406,7 @@ namespace cimg_library_suffixed {
          const int value0, const int value1, ...):
       _width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) {
 #define _CImg_stdarg(img,a0,a1,N,t) { \
-	unsigned long _siz = (unsigned long)N; \
+	size_t _siz = (size_t)N; \
 	if (_siz--) { \
 	  va_list ap; \
 	  va_start(ap,a1); \
@@ -9237,10 +9420,10 @@ namespace cimg_library_suffixed {
 	} \
       }
       assign(size_x,size_y,size_z,size_c);
-      _CImg_stdarg(*this,value0,value1,(unsigned long)size_x*size_y*size_z*size_c,int);
+      _CImg_stdarg(*this,value0,value1,(size_t)size_x*size_y*size_z*size_c,int);
     }
 
-#ifdef cimg_use_cpp11
+#if defined(cimg_use_cpp11) && cimg_use_cpp11!=0
     //! Construct image with specified size and initialize pixel values from an initializer list of integers.
     /**
        Construct a new image instance of size \c size_x x \c size_y x \c size_z x \c size_c,
@@ -9273,7 +9456,7 @@ namespace cimg_library_suffixed {
       _width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) {
 #define _cimg_constructor_cpp11(repeat_values) \
   auto it = values.begin(); \
-  unsigned long siz = size(); \
+  size_t siz = size(); \
   if (repeat_values) for (T *ptrd = _data; siz--; ) { \
     *(ptrd++) = (T)(*(it++)); if (it==values.end()) it = values.begin(); } \
   else { siz = cimg::min(siz,values.size()); for (T *ptrd = _data; siz--; ) *(ptrd++) = (T)(*(it++)); }
@@ -9329,7 +9512,7 @@ namespace cimg_library_suffixed {
       _width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) {
       assign(values.size(),1,1,1);
       auto it = values.begin();
-      unsigned long siz = _width;
+      unsigned int siz = _width;
       for (T *ptrd = _data; siz--; ) *(ptrd++) = (T)(*(it++));
     }
 
@@ -9366,7 +9549,7 @@ namespace cimg_library_suffixed {
          const double value0, const double value1, ...):
       _width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) {
       assign(size_x,size_y,size_z,size_c);
-      _CImg_stdarg(*this,value0,value1,(unsigned long)size_x*size_y*size_z*size_c,double);
+      _CImg_stdarg(*this,value0,value1,(size_t)size_x*size_y*size_z*size_c,double);
     }
 
     //! Construct image with specified size and initialize pixel values from a value string.
@@ -9401,7 +9584,7 @@ namespace cimg_library_suffixed {
      **/
     CImg(const unsigned int size_x, const unsigned int size_y, const unsigned int size_z, const unsigned int size_c,
 	 const char *const values, const bool repeat_values):_is_shared(false) {
-      const unsigned long siz = (unsigned long)size_x*size_y*size_z*size_c;
+      const size_t siz = (size_t)size_x*size_y*size_z*size_c;
       if (siz) {
         _width = size_x; _height = size_y; _depth = size_z; _spectrum = size_c;
         try { _data = new T[siz]; } catch (...) {
@@ -9457,7 +9640,7 @@ namespace cimg_library_suffixed {
                                     cimg_instance,
                                     size_x,size_y,size_z,size_c,CImg<t>::pixel_type());
       }
-      const unsigned long siz = (unsigned long)size_x*size_y*size_z*size_c;
+      const size_t siz = (size_t)size_x*size_y*size_z*size_c;
       if (values && siz) {
         _width = size_x; _height = size_y; _depth = size_z; _spectrum = size_c;
         try { _data = new T[siz]; } catch (...) {
@@ -9476,7 +9659,7 @@ namespace cimg_library_suffixed {
     //! Construct image with specified size and initialize pixel values from a memory buffer \specialization.
     CImg(const T *const values, const unsigned int size_x, const unsigned int size_y=1,
          const unsigned int size_z=1, const unsigned int size_c=1, const bool is_shared=false) {
-      const unsigned long siz = (unsigned long)size_x*size_y*size_z*size_c;
+      const size_t siz = (size_t)size_x*size_y*size_z*size_c;
       if (values && siz) {
         _width = size_x; _height = size_y; _depth = size_z; _spectrum = size_c; _is_shared = is_shared;
         if (_is_shared) _data = const_cast<T*>(values);
@@ -9540,7 +9723,7 @@ namespace cimg_library_suffixed {
     **/
     template<typename t>
     CImg(const CImg<t>& img):_is_shared(false) {
-      const unsigned long siz = img.size();
+      const size_t siz = (size_t)img.size();
       if (img._data && siz) {
         _width = img._width; _height = img._height; _depth = img._depth; _spectrum = img._spectrum;
         try { _data = new T[siz]; } catch (...) {
@@ -9557,7 +9740,7 @@ namespace cimg_library_suffixed {
 
     //! Construct image copy \specialization.
     CImg(const CImg<T>& img) {
-      const unsigned long siz = img.size();
+      const size_t siz = (size_t)img.size();
       if (img._data && siz) {
         _width = img._width; _height = img._height; _depth = img._depth; _spectrum = img._spectrum;
         _is_shared = img._is_shared;
@@ -9602,7 +9785,7 @@ namespace cimg_library_suffixed {
                                     cimg_instance,
                                     CImg<t>::pixel_type(),img._width,img._height,img._depth,img._spectrum,img._data);
       }
-      const unsigned long siz = img.size();
+      const size_t siz = (size_t)img.size();
       if (img._data && siz) {
         _width = img._width; _height = img._height; _depth = img._depth; _spectrum = img._spectrum;
         try { _data = new T[siz]; } catch (...) {
@@ -9619,7 +9802,7 @@ namespace cimg_library_suffixed {
 
     //! Advanced copy constructor \specialization.
     CImg(const CImg<T>& img, const bool is_shared) {
-      const unsigned long siz = img.size();
+      const size_t siz = (size_t)img.size();
       if (img._data && siz) {
         _width = img._width; _height = img._height; _depth = img._depth; _spectrum = img._spectrum;
         _is_shared = is_shared;
@@ -9696,7 +9879,7 @@ namespace cimg_library_suffixed {
 
     // Constructor and assignment operator for rvalue references (c++11).
     // This avoids an additional image copy for methods returning new images. Can save RAM for big images !
-#ifdef cimg_use_cpp11
+#if defined(cimg_use_cpp11) && cimg_use_cpp11!=0
     CImg(CImg<T>&& img):_width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) {
       swap(img);
     }
@@ -9722,9 +9905,9 @@ namespace cimg_library_suffixed {
     **/
     CImg<T>& assign(const unsigned int size_x, const unsigned int size_y=1,
                     const unsigned int size_z=1, const unsigned int size_c=1) {
-      const unsigned long siz = (unsigned long)size_x*size_y*size_z*size_c;
+      const size_t siz = (size_t)size_x*size_y*size_z*size_c;
       if (!siz) return assign();
-      const unsigned long curr_siz = size();
+      const size_t curr_siz = (size_t)size();
       if (siz!=curr_siz) {
 	if (_is_shared)
           throw CImgArgumentException(_cimg_instance
@@ -9765,7 +9948,7 @@ namespace cimg_library_suffixed {
                     const unsigned int size_z, const unsigned int size_c,
                     const int value0, const int value1, ...) {
       assign(size_x,size_y,size_z,size_c);
-      _CImg_stdarg(*this,value0,value1,(unsigned long)size_x*size_y*size_z*size_c,int);
+      _CImg_stdarg(*this,value0,value1,(size_t)size_x*size_y*size_z*size_c,int);
       return *this;
     }
 
@@ -9777,7 +9960,7 @@ namespace cimg_library_suffixed {
                     const unsigned int size_z, const unsigned int size_c,
                     const double value0, const double value1, ...) {
       assign(size_x,size_y,size_z,size_c);
-      _CImg_stdarg(*this,value0,value1,(unsigned long)size_x*size_y*size_z*size_c,double);
+      _CImg_stdarg(*this,value0,value1,(size_t)size_x*size_y*size_z*size_c,double);
       return *this;
     }
 
@@ -9798,7 +9981,7 @@ namespace cimg_library_suffixed {
     template<typename t>
     CImg<T>& assign(const t *const values, const unsigned int size_x, const unsigned int size_y=1,
                     const unsigned int size_z=1, const unsigned int size_c=1) {
-      const unsigned long siz = (unsigned long)size_x*size_y*size_z*size_c;
+      const size_t siz = (size_t)size_x*size_y*size_z*size_c;
       if (!values || !siz) return assign();
       assign(size_x,size_y,size_z,size_c);
       const t *ptrs = values; cimg_for(*this,ptrd,T) *ptrd = (T)*(ptrs++);
@@ -9808,9 +9991,9 @@ namespace cimg_library_suffixed {
     //! Construct image with specified size and initialize pixel values from a memory buffer \specialization.
     CImg<T>& assign(const T *const values, const unsigned int size_x, const unsigned int size_y=1,
                     const unsigned int size_z=1, const unsigned int size_c=1) {
-      const unsigned long siz = (unsigned long)size_x*size_y*size_z*size_c;
+      const size_t siz = (size_t)size_x*size_y*size_z*size_c;
       if (!values || !siz) return assign();
-      const unsigned long curr_siz = size();
+      const size_t curr_siz = (size_t)size();
       if (values==_data && siz==curr_siz) return assign(size_x,size_y,size_z,size_c);
       if (_is_shared || values + siz<_data || values>=_data + size()) {
         assign(size_x,size_y,size_z,size_c);
@@ -9848,7 +10031,7 @@ namespace cimg_library_suffixed {
     //! Construct image with specified size and initialize pixel values from a memory buffer \overloading.
     CImg<T>& assign(const T *const values, const unsigned int size_x, const unsigned int size_y,
                     const unsigned int size_z, const unsigned int size_c, const bool is_shared) {
-      const unsigned long siz = (unsigned long)size_x*size_y*size_z*size_c;
+      const size_t siz = (size_t)size_x*size_y*size_z*size_c;
       if (!values || !siz) return assign();
       if (!is_shared) { if (_is_shared) assign(); assign(values,size_x,size_y,size_z,size_c); }
       else {
@@ -10021,10 +10204,7 @@ namespace cimg_library_suffixed {
       \endcode
     **/
     CImg<T>& swap(CImg<T>& img) {
-      cimg::swap(_width,img._width);
-      cimg::swap(_height,img._height);
-      cimg::swap(_depth,img._depth);
-      cimg::swap(_spectrum,img._spectrum);
+      cimg::swap(_width,img._width,_height,img._height,_depth,img._depth,_spectrum,img._spectrum);
       cimg::swap(_data,img._data);
       cimg::swap(_is_shared,img._is_shared);
       return img;
@@ -10044,6 +10224,12 @@ namespace cimg_library_suffixed {
       return _empty.assign();
     }
 
+    //! Return a reference to an empty image \const.
+    static const CImg<T>& const_empty() {
+      static const CImg<T> _empty;
+      return _empty;
+    }
+
     //@}
     //------------------------------------------
     //
@@ -10087,12 +10273,12 @@ namespace cimg_library_suffixed {
 #if cimg_verbosity>=3
     T& operator()(const unsigned int x, const unsigned int y=0,
                   const unsigned int z=0, const unsigned int c=0) {
-      const unsigned long off = (unsigned long)offset(x,y,z,c);
+      const ulongT off = (ulongT)offset(x,y,z,c);
       if (!_data || off>=size()) {
         cimg::warn(_cimg_instance
-                   "operator(): Invalid pixel request, at coordinates (%u,%u,%u,%u) [offset=%u].",
+                   "operator(): Invalid pixel request, at coordinates (%d,%d,%d,%d) [offset=%u].",
                    cimg_instance,
-                   x,y,z,c,off);
+                   (int)x,(int)y,(int)z,(int)c,off);
         return *_data;
       }
       else return _data[off];
@@ -10118,14 +10304,14 @@ namespace cimg_library_suffixed {
          the reading/writing of several pixel values in the same image (e.g. in a loop).
      **/
     T& operator()(const unsigned int x, const unsigned int y, const unsigned int z, const unsigned int c,
-                  const unsigned long wh, const unsigned long whd=0) {
+                  const ulongT wh, const ulongT whd=0) {
       cimg::unused(wh,whd);
       return (*this)(x,y,z,c);
     }
 
     //! Access to a pixel value \const.
     const T& operator()(const unsigned int x, const unsigned int y, const unsigned int z, const unsigned int c,
-                        const unsigned long wh, const unsigned long whd=0) const {
+                        const ulongT wh, const ulongT whd=0) const {
       cimg::unused(wh,whd);
       return (*this)(x,y,z,c);
     }
@@ -10147,40 +10333,38 @@ namespace cimg_library_suffixed {
     }
 
     T& operator()(const unsigned int x, const unsigned int y, const unsigned int z) {
-      return _data[x + y*(unsigned long)_width + z*(unsigned long)_width*_height];
+      return _data[x + y*(ulongT)_width + z*(ulongT)_width*_height];
    }
 
     const T& operator()(const unsigned int x, const unsigned int y, const unsigned int z) const {
-      return _data[x + y*(unsigned long)_width + z*(unsigned long)_width*_height];
+      return _data[x + y*(ulongT)_width + z*(ulongT)_width*_height];
     }
 
     T& operator()(const unsigned int x, const unsigned int y, const unsigned int z, const unsigned int c) {
-      return _data[x + y*(unsigned long)_width + z*(unsigned long)_width*_height +
-                   c*(unsigned long)_width*_height*_depth];
+      return _data[x + y*(ulongT)_width + z*(ulongT)_width*_height + c*(ulongT)_width*_height*_depth];
     }
 
     const T& operator()(const unsigned int x, const unsigned int y, const unsigned int z, const unsigned int c) const {
-      return _data[x + y*(unsigned long)_width + z*(unsigned long)_width*_height +
-                   c*(unsigned long)_width*_height*_depth];
+      return _data[x + y*(ulongT)_width + z*(ulongT)_width*_height + c*(ulongT)_width*_height*_depth];
     }
 
     T& operator()(const unsigned int x, const unsigned int y, const unsigned int z, const unsigned int,
-                  const unsigned long wh) {
+                  const ulongT wh) {
       return _data[x + y*_width + z*wh];
     }
 
     const T& operator()(const unsigned int x, const unsigned int y, const unsigned int z, const unsigned int,
-                        const unsigned long wh) const {
+                        const ulongT wh) const {
       return _data[x + y*_width + z*wh];
     }
 
     T& operator()(const unsigned int x, const unsigned int y, const unsigned int z, const unsigned int c,
-                  const unsigned long wh, const unsigned long whd) {
+                  const ulongT wh, const ulongT whd) {
       return _data[x + y*_width + z*wh + c*whd];
     }
 
     const T& operator()(const unsigned int x, const unsigned int y, const unsigned int z, const unsigned int c,
-                        const unsigned long wh, const unsigned long whd) const {
+                        const ulongT wh, const ulongT whd) const {
       return _data[x + y*_width + z*wh + c*whd];
     }
 #endif
@@ -10258,7 +10442,7 @@ namespace cimg_library_suffixed {
       const unsigned int omode = cimg::exception_mode();
       cimg::exception_mode(0);
       try {
-        fill(expression,true);
+        _fill(expression,true,true,0,0,"operator=",0);
       } catch (CImgException&) {
         cimg::exception_mode(omode);
         load(expression);
@@ -10321,7 +10505,7 @@ namespace cimg_library_suffixed {
     CImg<T>& operator+=(const t value) {
       if (is_empty()) return *this;
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (size()>=524288)
+#pragma omp parallel for cimg_openmp_if(size()>=524288)
 #endif
       cimg_rof(*this,ptrd,T) *ptrd = (T)(*ptrd + value);
       return *this;
@@ -10336,37 +10520,7 @@ namespace cimg_library_suffixed {
          instead of assigning them.
     **/
     CImg<T>& operator+=(const char *const expression) {
-      if (is_empty()) return *this;
-      const unsigned int omode = cimg::exception_mode();
-      cimg::exception_mode(0);
-      try {
-        const CImg<T> _base = cimg::_is_self_expr(expression)?+*this:CImg<T>(), &base = _base?_base:*this;
-        _cimg_math_parser mp(base,this,expression + (*expression=='>' || *expression=='<'?1:0),"operator+=");
-        T *ptrd = *expression=='<'?end() - 1:_data;
-        if (*expression=='<') cimg_rofXYZC(*this,x,y,z,c) { *ptrd = (T)(*ptrd + mp(x,y,z,c)); --ptrd; }
-        else if (*expression=='>') cimg_forXYZC(*this,x,y,z,c) { *ptrd = (T)(*ptrd + mp(x,y,z,c)); ++ptrd; }
-        else {
-#ifdef cimg_use_openmp
-          if (_width>=512 && _height*_depth*_spectrum>=2 && std::strlen(expression)>=6)
-#pragma omp parallel
-            {
-              _cimg_math_parser _mp = omp_get_thread_num()?mp:_cimg_math_parser(), &lmp = omp_get_thread_num()?_mp:mp;
-#pragma omp for collapse(3)
-              cimg_forYZC(*this,y,z,c) {
-                T *ptrd = data(0,y,z,c);
-                cimg_forX(*this,x) { *ptrd = (T)(*ptrd + lmp(x,y,z,c)); ++ptrd; }
-              }
-            }
-          else
-#endif
-            cimg_forXYZC(*this,x,y,z,c) { *ptrd = (T)(*ptrd + mp(x,y,z,c)); ++ptrd; }
-        }
-      } catch (CImgException&) {
-        cimg::exception_mode(omode);
-        *this+=CImg<T>(_width,_height,_depth,_spectrum,expression,true);
-      }
-      cimg::exception_mode(omode);
-      return *this;
+      return *this+=(+*this)._fill(expression,true,true,0,0,"operator+=",this);
     }
 
     //! In-place addition operator.
@@ -10391,11 +10545,11 @@ namespace cimg_library_suffixed {
     **/
     template<typename t>
     CImg<T>& operator+=(const CImg<t>& img) {
-      const unsigned long siz = size(), isiz = img.size();
+      const ulongT siz = size(), isiz = img.size();
       if (siz && isiz) {
         if (is_overlapped(img)) return *this+=+img;
         T *ptrd = _data, *const ptre = _data + siz;
-        if (siz>isiz) for (unsigned long n = siz/isiz; n; --n)
+        if (siz>isiz) for (ulongT n = siz/isiz; n; --n)
           for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs<ptrs_end; ++ptrd)
             *ptrd = (T)(*ptrd + *(ptrs++));
         for (const t *ptrs = img._data; ptrd<ptre; ++ptrd) *ptrd = (T)(*ptrd + *(ptrs++));
@@ -10412,7 +10566,7 @@ namespace cimg_library_suffixed {
     CImg<T>& operator++() {
       if (is_empty()) return *this;
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (size()>=524288)
+#pragma omp parallel for cimg_openmp_if(size()>=524288)
 #endif
       cimg_rof(*this,ptrd,T) ++*ptrd;
       return *this;
@@ -10481,7 +10635,7 @@ namespace cimg_library_suffixed {
     CImg<T>& operator-=(const t value) {
       if (is_empty()) return *this;
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (size()>=524288)
+#pragma omp parallel for cimg_openmp_if(size()>=524288)
 #endif
       cimg_rof(*this,ptrd,T) *ptrd = (T)(*ptrd - value);
       return *this;
@@ -10492,37 +10646,7 @@ namespace cimg_library_suffixed {
        Similar to operator+=(const char*), except that it performs a substraction instead of an addition.
      **/
     CImg<T>& operator-=(const char *const expression) {
-      if (is_empty()) return *this;
-      const unsigned int omode = cimg::exception_mode();
-      cimg::exception_mode(0);
-      try {
-        const CImg<T> _base = cimg::_is_self_expr(expression)?+*this:CImg<T>(), &base = _base?_base:*this;
-        _cimg_math_parser mp(base,this,expression + (*expression=='>' || *expression=='<'?1:0),"operator-=");
-        T *ptrd = *expression=='<'?end() - 1:_data;
-        if (*expression=='<') cimg_rofXYZC(*this,x,y,z,c) { *ptrd = (T)(*ptrd - mp(x,y,z,c)); --ptrd; }
-        else if (*expression=='>') cimg_forXYZC(*this,x,y,z,c) { *ptrd = (T)(*ptrd - mp(x,y,z,c)); ++ptrd; }
-        else {
-#ifdef cimg_use_openmp
-          if (_width>=512 && _height*_depth*_spectrum>=2 && std::strlen(expression)>=6)
-#pragma omp parallel
-          {
-            _cimg_math_parser _mp = omp_get_thread_num()?mp:_cimg_math_parser(), &lmp = omp_get_thread_num()?_mp:mp;
-#pragma omp for collapse(3)
-            cimg_forYZC(*this,y,z,c) {
-              T *ptrd = data(0,y,z,c);
-              cimg_forX(*this,x) { *ptrd = (T)(*ptrd - lmp(x,y,z,c)); ++ptrd; }
-            }
-          }
-          else
-#endif
-            cimg_forXYZC(*this,x,y,z,c) { *ptrd = (T)(*ptrd - mp(x,y,z,c)); ++ptrd; }
-        }
-      } catch (CImgException&) {
-        cimg::exception_mode(omode);
-        *this-=CImg<T>(_width,_height,_depth,_spectrum,expression,true);
-      }
-      cimg::exception_mode(omode);
-      return *this;
+      return *this-=(+*this)._fill(expression,true,true,0,0,"operator-=",this);
     }
 
     //! In-place substraction operator.
@@ -10531,11 +10655,11 @@ namespace cimg_library_suffixed {
      **/
     template<typename t>
     CImg<T>& operator-=(const CImg<t>& img) {
-      const unsigned long siz = size(), isiz = img.size();
+      const ulongT siz = size(), isiz = img.size();
       if (siz && isiz) {
         if (is_overlapped(img)) return *this-=+img;
         T *ptrd = _data, *const ptre = _data + siz;
-        if (siz>isiz) for (unsigned long n = siz/isiz; n; --n)
+        if (siz>isiz) for (ulongT n = siz/isiz; n; --n)
           for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs<ptrs_end; ++ptrd)
             *ptrd = (T)(*ptrd - *(ptrs++));
         for (const t *ptrs = img._data; ptrd<ptre; ++ptrd) *ptrd = (T)(*ptrd - *(ptrs++));
@@ -10550,7 +10674,7 @@ namespace cimg_library_suffixed {
     CImg<T>& operator--() {
       if (is_empty()) return *this;
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (size()>=524288)
+#pragma omp parallel for cimg_openmp_if(size()>=524288)
 #endif
       cimg_rof(*this,ptrd,T) *ptrd = *ptrd - (T)1;
       return *this;
@@ -10621,7 +10745,7 @@ namespace cimg_library_suffixed {
     CImg<T>& operator*=(const t value) {
       if (is_empty()) return *this;
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (size()>=262144)
+#pragma omp parallel for cimg_openmp_if(size()>=262144)
 #endif
       cimg_rof(*this,ptrd,T) *ptrd = (T)(*ptrd * value);
       return *this;
@@ -10632,37 +10756,7 @@ namespace cimg_library_suffixed {
        Similar to operator+=(const char*), except that it performs a multiplication instead of an addition.
      **/
     CImg<T>& operator*=(const char *const expression) {
-      if (is_empty()) return *this;
-      const unsigned int omode = cimg::exception_mode();
-      cimg::exception_mode(0);
-      try {
-        const CImg<T> _base = cimg::_is_self_expr(expression)?+*this:CImg<T>(), &base = _base?_base:*this;
-        _cimg_math_parser mp(base,this,expression + (*expression=='>' || *expression=='<'?1:0),"operator*=");
-        T *ptrd = *expression=='<'?end() - 1:_data;
-        if (*expression=='<') cimg_rofXYZC(*this,x,y,z,c) { *ptrd = (T)(*ptrd * mp(x,y,z,c)); --ptrd; }
-        else if (*expression=='>') cimg_forXYZC(*this,x,y,z,c) { *ptrd = (T)(*ptrd * mp(x,y,z,c)); ++ptrd; }
-        else {
-#ifdef cimg_use_openmp
-          if (_width>=512 && _height*_depth*_spectrum>=2 && std::strlen(expression)>=6)
-#pragma omp parallel
-          {
-            _cimg_math_parser _mp = omp_get_thread_num()?mp:_cimg_math_parser(), &lmp = omp_get_thread_num()?_mp:mp;
-#pragma omp for collapse(3)
-            cimg_forYZC(*this,y,z,c) {
-              T *ptrd = data(0,y,z,c);
-              cimg_forX(*this,x) { *ptrd = (T)(*ptrd * lmp(x,y,z,c)); ++ptrd; }
-            }
-          }
-          else
-#endif
-            cimg_forXYZC(*this,x,y,z,c) { *ptrd = (T)(*ptrd * mp(x,y,z,c)); ++ptrd; }
-        }
-      } catch (CImgException&) {
-        cimg::exception_mode(omode);
-        mul(CImg<T>(_width,_height,_depth,_spectrum,expression,true));
-      }
-      cimg::exception_mode(omode);
-      return *this;
+      return mul((+*this)._fill(expression,true,true,0,0,"operator*=",this));
     }
 
     //! In-place multiplication operator.
@@ -10721,7 +10815,7 @@ namespace cimg_library_suffixed {
                                     img._width,img._height,img._depth,img._spectrum,img._data);
       CImg<_cimg_Tt> res(img._width,_height);
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (size()>1024 && img.size()>1024) collapse(2)
+#pragma omp parallel for collapse(2) cimg_openmp_if(size()>1024 && img.size()>1024)
       cimg_forXY(res,i,j) {
         _cimg_Ttdouble value = 0; cimg_forX(*this,k) value+=(*this)(k,j)*img(i,k); res(i,j) = (_cimg_Tt)value;
       }
@@ -10742,7 +10836,7 @@ namespace cimg_library_suffixed {
     CImg<T>& operator/=(const t value) {
       if (is_empty()) return *this;
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (size()>=32768)
+#pragma omp parallel for cimg_openmp_if(size()>=32768)
 #endif
       cimg_rof(*this,ptrd,T) *ptrd = (T)(*ptrd / value);
       return *this;
@@ -10753,37 +10847,7 @@ namespace cimg_library_suffixed {
        Similar to operator+=(const char*), except that it performs a division instead of an addition.
      **/
     CImg<T>& operator/=(const char *const expression) {
-      if (is_empty()) return *this;
-      const unsigned int omode = cimg::exception_mode();
-      cimg::exception_mode(0);
-      try {
-        const CImg<T> _base = cimg::_is_self_expr(expression)?+*this:CImg<T>(), &base = _base?_base:*this;
-        _cimg_math_parser mp(base,this,expression + (*expression=='>' || *expression=='<'?1:0),"operator/=");
-        T *ptrd = *expression=='<'?end() - 1:_data;
-        if (*expression=='<') cimg_rofXYZC(*this,x,y,z,c) { *ptrd = (T)(*ptrd / mp(x,y,z,c)); --ptrd; }
-        else if (*expression=='>') cimg_forXYZC(*this,x,y,z,c) { *ptrd = (T)(*ptrd / mp(x,y,z,c)); ++ptrd; }
-        else {
-#ifdef cimg_use_openmp
-          if (_width>=512 && _height*_depth*_spectrum>=2 && std::strlen(expression)>=6)
-#pragma omp parallel
-          {
-            _cimg_math_parser _mp = omp_get_thread_num()?mp:_cimg_math_parser(), &lmp = omp_get_thread_num()?_mp:mp;
-#pragma omp for collapse(3)
-            cimg_forYZC(*this,y,z,c) {
-              T *ptrd = data(0,y,z,c);
-              cimg_forX(*this,x) { *ptrd = (T)(*ptrd / lmp(x,y,z,c)); ++ptrd; }
-            }
-          }
-          else
-#endif
-            cimg_forXYZC(*this,x,y,z,c) { *ptrd = (T)(*ptrd / mp(x,y,z,c)); ++ptrd; }
-        }
-      } catch (CImgException&) {
-        cimg::exception_mode(omode);
-        div(CImg<T>(_width,_height,_depth,_spectrum,expression,true));
-      }
-      cimg::exception_mode(omode);
-      return *this;
+      return div((+*this)._fill(expression,true,true,0,0,"operator/=",this));
     }
 
     //! In-place division operator.
@@ -10839,7 +10903,7 @@ namespace cimg_library_suffixed {
     CImg<T>& operator%=(const t value) {
       if (is_empty()) return *this;
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (size()>=16384)
+#pragma omp parallel for cimg_openmp_if(size()>=16384)
 #endif
       cimg_rof(*this,ptrd,T) *ptrd = (T)cimg::mod(*ptrd,(T)value);
       return *this;
@@ -10850,37 +10914,7 @@ namespace cimg_library_suffixed {
        Similar to operator+=(const char*), except that it performs a modulo operation instead of an addition.
     **/
     CImg<T>& operator%=(const char *const expression) {
-      if (is_empty()) return *this;
-      const unsigned int omode = cimg::exception_mode();
-      cimg::exception_mode(0);
-      try {
-        const CImg<T> _base = cimg::_is_self_expr(expression)?+*this:CImg<T>(), &base = _base?_base:*this;
-        _cimg_math_parser mp(base,this,expression + (*expression=='>' || *expression=='<'?1:0),"operator%=");
-        T *ptrd = *expression=='<'?end() - 1:_data;
-        if (*expression=='<') cimg_rofXYZC(*this,x,y,z,c) { *ptrd = (T)cimg::mod(*ptrd,(T)mp(x,y,z,c)); --ptrd; }
-        else if (*expression=='>') cimg_forXYZC(*this,x,y,z,c) { *ptrd = (T)cimg::mod(*ptrd,(T)mp(x,y,z,c)); ++ptrd; }
-        else {
-#ifdef cimg_use_openmp
-          if (_width>=512 && _height*_depth*_spectrum>=2 && std::strlen(expression)>=6)
-#pragma omp parallel
-          {
-            _cimg_math_parser _mp = omp_get_thread_num()?mp:_cimg_math_parser(), &lmp = omp_get_thread_num()?_mp:mp;
-#pragma omp for collapse(3)
-            cimg_forYZC(*this,y,z,c) {
-              T *ptrd = data(0,y,z,c);
-              cimg_forX(*this,x) { *ptrd = (T)cimg::mod(*ptrd,(T)lmp(x,y,z,c)); ++ptrd; }
-            }
-          }
-          else
-#endif
-            cimg_forXYZC(*this,x,y,z,c) { *ptrd = (T)cimg::mod(*ptrd,(T)mp(x,y,z,c)); ++ptrd; }
-        }
-      } catch (CImgException&) {
-        cimg::exception_mode(omode);
-        *this%=CImg<T>(_width,_height,_depth,_spectrum,expression,true);
-      }
-      cimg::exception_mode(omode);
-      return *this;
+      return *this%=(+*this)._fill(expression,true,true,0,0,"operator%=",this);
     }
 
     //! In-place modulo operator.
@@ -10889,11 +10923,11 @@ namespace cimg_library_suffixed {
     **/
     template<typename t>
     CImg<T>& operator%=(const CImg<t>& img) {
-      const unsigned long siz = size(), isiz = img.size();
+      const ulongT siz = size(), isiz = img.size();
       if (siz && isiz) {
         if (is_overlapped(img)) return *this%=+img;
         T *ptrd = _data, *const ptre = _data + siz;
-        if (siz>isiz) for (unsigned long n = siz/isiz; n; --n)
+        if (siz>isiz) for (ulongT n = siz/isiz; n; --n)
           for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs<ptrs_end; ++ptrd)
             *ptrd = cimg::mod(*ptrd,(T)*(ptrs++));
         for (const t *ptrs = img._data; ptrd<ptre; ++ptrd) *ptrd = cimg::mod(*ptrd,(T)*(ptrs++));
@@ -10938,9 +10972,9 @@ namespace cimg_library_suffixed {
     CImg<T>& operator&=(const t value) {
       if (is_empty()) return *this;
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (size()>=32768)
+#pragma omp parallel for cimg_openmp_if(size()>=32768)
 #endif
-      cimg_rof(*this,ptrd,T) *ptrd = (T)((unsigned long)*ptrd & (unsigned long)value);
+      cimg_rof(*this,ptrd,T) *ptrd = (T)((ulongT)*ptrd & (ulongT)value);
       return *this;
     }
 
@@ -10949,39 +10983,7 @@ namespace cimg_library_suffixed {
        Similar to operator+=(const char*), except that it performs a bitwise AND operation instead of an addition.
     **/
     CImg<T>& operator&=(const char *const expression) {
-      if (is_empty()) return *this;
-      const unsigned int omode = cimg::exception_mode();
-      cimg::exception_mode(0);
-      try {
-        const CImg<T> _base = cimg::_is_self_expr(expression)?+*this:CImg<T>(), &base = _base?_base:*this;
-        _cimg_math_parser mp(base,this,expression + (*expression=='>' || *expression=='<'?1:0),"operator&=");
-        T *ptrd = *expression=='<'?end() - 1:_data;
-        if (*expression=='<')
-          cimg_rofXYZC(*this,x,y,z,c) { *ptrd = (T)((unsigned long)*ptrd & (unsigned long)mp(x,y,z,c)); --ptrd; }
-        else if (*expression=='>')
-          cimg_forXYZC(*this,x,y,z,c) { *ptrd = (T)((unsigned long)*ptrd & (unsigned long)mp(x,y,z,c)); ++ptrd; }
-        else {
-#ifdef cimg_use_openmp
-          if (_width>=512 && _height*_depth*_spectrum>=2 && std::strlen(expression)>=6)
-#pragma omp parallel
-          {
-            _cimg_math_parser _mp = omp_get_thread_num()?mp:_cimg_math_parser(), &lmp = omp_get_thread_num()?_mp:mp;
-#pragma omp for collapse(3)
-            cimg_forYZC(*this,y,z,c) {
-              T *ptrd = data(0,y,z,c);
-              cimg_forX(*this,x) { *ptrd = (T)((unsigned long)*ptrd & (unsigned long)lmp(x,y,z,c)); ++ptrd; }
-            }
-          }
-          else
-#endif
-            cimg_forXYZC(*this,x,y,z,c) { *ptrd = (T)((unsigned long)*ptrd & (unsigned long)mp(x,y,z,c)); ++ptrd; }
-        }
-      } catch (CImgException&) {
-        cimg::exception_mode(omode);
-        *this&=CImg<T>(_width,_height,_depth,_spectrum,expression,true);
-      }
-      cimg::exception_mode(omode);
-      return *this;
+      return *this&=(+*this)._fill(expression,true,true,0,0,"operator&=",this);
     }
 
     //! In-place bitwise AND operator.
@@ -10990,14 +10992,14 @@ namespace cimg_library_suffixed {
     **/
     template<typename t>
     CImg<T>& operator&=(const CImg<t>& img) {
-      const unsigned long siz = size(), isiz = img.size();
+      const ulongT siz = size(), isiz = img.size();
       if (siz && isiz) {
         if (is_overlapped(img)) return *this&=+img;
         T *ptrd = _data, *const ptre = _data + siz;
-        if (siz>isiz) for (unsigned long n = siz/isiz; n; --n)
+        if (siz>isiz) for (ulongT n = siz/isiz; n; --n)
           for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs<ptrs_end; ++ptrd)
-            *ptrd = (T)((unsigned long)*ptrd & (unsigned long)*(ptrs++));
-        for (const t *ptrs = img._data; ptrd<ptre; ++ptrd) *ptrd = (T)((unsigned long)*ptrd & (unsigned long)*(ptrs++));
+            *ptrd = (T)((ulongT)*ptrd & (ulongT)*(ptrs++));
+        for (const t *ptrs = img._data; ptrd<ptre; ++ptrd) *ptrd = (T)((ulongT)*ptrd & (ulongT)*(ptrs++));
       }
       return *this;
     }
@@ -11039,9 +11041,9 @@ namespace cimg_library_suffixed {
     CImg<T>& operator|=(const t value) {
       if (is_empty()) return *this;
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (size()>=32768)
+#pragma omp parallel for cimg_openmp_if(size()>=32768)
 #endif
-      cimg_rof(*this,ptrd,T) *ptrd = (T)((unsigned long)*ptrd | (unsigned long)value);
+      cimg_rof(*this,ptrd,T) *ptrd = (T)((ulongT)*ptrd | (ulongT)value);
       return *this;
     }
 
@@ -11050,39 +11052,7 @@ namespace cimg_library_suffixed {
        Similar to operator+=(const char*), except that it performs a bitwise OR operation instead of an addition.
     **/
     CImg<T>& operator|=(const char *const expression) {
-      if (is_empty()) return *this;
-      const unsigned int omode = cimg::exception_mode();
-      cimg::exception_mode(0);
-      try {
-        const CImg<T> _base = cimg::_is_self_expr(expression)?+*this:CImg<T>(), &base = _base?_base:*this;
-        _cimg_math_parser mp(base,this,expression + (*expression=='>' || *expression=='<'?1:0),"operator|=");
-        T *ptrd = *expression=='<'?end() - 1:_data;
-        if (*expression=='<')
-          cimg_rofXYZC(*this,x,y,z,c) { *ptrd = (T)((unsigned long)*ptrd | (unsigned long)mp(x,y,z,c)); --ptrd; }
-        else if (*expression=='>')
-          cimg_forXYZC(*this,x,y,z,c) { *ptrd = (T)((unsigned long)*ptrd | (unsigned long)mp(x,y,z,c)); ++ptrd; }
-        else {
-#ifdef cimg_use_openmp
-          if (_width>=512 && _height*_depth*_spectrum>=2 && std::strlen(expression)>=6)
-#pragma omp parallel
-          {
-            _cimg_math_parser _mp = omp_get_thread_num()?mp:_cimg_math_parser(), &lmp = omp_get_thread_num()?_mp:mp;
-#pragma omp for collapse(3)
-            cimg_forYZC(*this,y,z,c) {
-              T *ptrd = data(0,y,z,c);
-              cimg_forX(*this,x) { *ptrd = (T)((unsigned long)*ptrd | (unsigned long)lmp(x,y,z,c)); ++ptrd; }
-            }
-          }
-          else
-#endif
-            cimg_forXYZC(*this,x,y,z,c) { *ptrd = (T)((unsigned long)*ptrd | (unsigned long)mp(x,y,z,c)); ++ptrd; }
-        }
-      } catch (CImgException&) {
-        cimg::exception_mode(omode);
-        *this|=CImg<T>(_width,_height,_depth,_spectrum,expression,true);
-      }
-      cimg::exception_mode(omode);
-      return *this;
+      return *this|=(+*this)._fill(expression,true,true,0,0,"operator|=",this);
     }
 
     //! In-place bitwise OR operator.
@@ -11091,14 +11061,14 @@ namespace cimg_library_suffixed {
     **/
     template<typename t>
     CImg<T>& operator|=(const CImg<t>& img) {
-      const unsigned long siz = size(), isiz = img.size();
+      const ulongT siz = size(), isiz = img.size();
       if (siz && isiz) {
         if (is_overlapped(img)) return *this|=+img;
         T *ptrd = _data, *const ptre = _data + siz;
-        if (siz>isiz) for (unsigned long n = siz/isiz; n; --n)
+        if (siz>isiz) for (ulongT n = siz/isiz; n; --n)
           for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs<ptrs_end; ++ptrd)
-            *ptrd = (T)((unsigned long)*ptrd | (unsigned long)*(ptrs++));
-        for (const t *ptrs = img._data; ptrd<ptre; ++ptrd) *ptrd = (T)((unsigned long)*ptrd | (unsigned long)*(ptrs++));
+            *ptrd = (T)((ulongT)*ptrd | (ulongT)*(ptrs++));
+        for (const t *ptrs = img._data; ptrd<ptre; ++ptrd) *ptrd = (T)((ulongT)*ptrd | (ulongT)*(ptrs++));
       }
       return *this;
     }
@@ -11142,9 +11112,9 @@ namespace cimg_library_suffixed {
     CImg<T>& operator^=(const t value) {
       if (is_empty()) return *this;
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (size()>=32768)
+#pragma omp parallel for cimg_openmp_if(size()>=32768)
 #endif
-      cimg_rof(*this,ptrd,T) *ptrd = (T)((unsigned long)*ptrd ^ (unsigned long)value);
+      cimg_rof(*this,ptrd,T) *ptrd = (T)((ulongT)*ptrd ^ (ulongT)value);
       return *this;
     }
 
@@ -11155,39 +11125,7 @@ namespace cimg_library_suffixed {
        - It does \e not compute the \e power of pixel values. For this purpose, use pow(const char*) instead.
     **/
     CImg<T>& operator^=(const char *const expression) {
-      if (is_empty()) return *this;
-      const unsigned int omode = cimg::exception_mode();
-      cimg::exception_mode(0);
-      try {
-        const CImg<T> _base = cimg::_is_self_expr(expression)?+*this:CImg<T>(), &base = _base?_base:*this;
-        _cimg_math_parser mp(base,this,expression + (*expression=='>' || *expression=='<'?1:0),"operator^=");
-        T *ptrd = *expression=='<'?end() - 1:_data;
-        if (*expression=='<')
-          cimg_rofXYZC(*this,x,y,z,c) { *ptrd = (T)((unsigned long)*ptrd ^ (unsigned long)mp(x,y,z,c)); --ptrd; }
-        else if (*expression=='>')
-          cimg_forXYZC(*this,x,y,z,c) { *ptrd = (T)((unsigned long)*ptrd ^ (unsigned long)mp(x,y,z,c)); ++ptrd; }
-        else {
-#ifdef cimg_use_openmp
-          if (_width>=512 && _height*_depth*_spectrum>=2 && std::strlen(expression)>=6)
-#pragma omp parallel
-            {
-              _cimg_math_parser _mp = omp_get_thread_num()?mp:_cimg_math_parser(), &lmp = omp_get_thread_num()?_mp:mp;
-#pragma omp for collapse(3)
-              cimg_forYZC(*this,y,z,c) {
-                T *ptrd = data(0,y,z,c);
-                cimg_forX(*this,x) { *ptrd = (T)((unsigned long)*ptrd ^ (unsigned long)lmp(x,y,z,c)); ++ptrd; }
-              }
-            }
-          else
-#endif
-            cimg_forXYZC(*this,x,y,z,c) { *ptrd = (T)((unsigned long)*ptrd ^ (unsigned long)mp(x,y,z,c)); ++ptrd; }
-        }
-      } catch (CImgException&) {
-        cimg::exception_mode(omode);
-        *this^=CImg<T>(_width,_height,_depth,_spectrum,expression,true);
-      }
-      cimg::exception_mode(omode);
-      return *this;
+      return *this^=(+*this)._fill(expression,true,true,0,0,"operator^=",this);
     }
 
     //! In-place bitwise XOR operator.
@@ -11198,14 +11136,14 @@ namespace cimg_library_suffixed {
     **/
     template<typename t>
     CImg<T>& operator^=(const CImg<t>& img) {
-      const unsigned long siz = size(), isiz = img.size();
+      const ulongT siz = size(), isiz = img.size();
       if (siz && isiz) {
         if (is_overlapped(img)) return *this^=+img;
         T *ptrd = _data, *const ptre = _data + siz;
-        if (siz>isiz) for (unsigned long n = siz/isiz; n; --n)
+        if (siz>isiz) for (ulongT n = siz/isiz; n; --n)
           for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs<ptrs_end; ++ptrd)
-            *ptrd = (T)((unsigned long)*ptrd ^ (unsigned long)*(ptrs++));
-        for (const t *ptrs = img._data; ptrd<ptre; ++ptrd) *ptrd = (T)((unsigned long)*ptrd ^ (unsigned long)*(ptrs++));
+            *ptrd = (T)((ulongT)*ptrd ^ (ulongT)*(ptrs++));
+        for (const t *ptrs = img._data; ptrd<ptre; ++ptrd) *ptrd = (T)((ulongT)*ptrd ^ (ulongT)*(ptrs++));
       }
       return *this;
     }
@@ -11247,9 +11185,9 @@ namespace cimg_library_suffixed {
     CImg<T>& operator<<=(const t value) {
       if (is_empty()) return *this;
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (size()>=65536)
+#pragma omp parallel for cimg_openmp_if(size()>=65536)
 #endif
-      cimg_rof(*this,ptrd,T) *ptrd = (T)(((long)*ptrd) << (int)value);
+      cimg_rof(*this,ptrd,T) *ptrd = (T)(((longT)*ptrd) << (int)value);
       return *this;
     }
 
@@ -11258,37 +11196,7 @@ namespace cimg_library_suffixed {
        Similar to operator+=(const char*), except that it performs a bitwise left shift instead of an addition.
     **/
     CImg<T>& operator<<=(const char *const expression) {
-      if (is_empty()) return *this;
-      const unsigned int omode = cimg::exception_mode();
-      cimg::exception_mode(0);
-      try {
-        const CImg<T> _base = cimg::_is_self_expr(expression)?+*this:CImg<T>(), &base = _base?_base:*this;
-        _cimg_math_parser mp(base,this,expression + (*expression=='>' || *expression=='<'?1:0),"operator<<=");
-        T *ptrd = *expression=='<'?end() - 1:_data;
-        if (*expression=='<') cimg_rofXYZC(*this,x,y,z,c) { *ptrd = (T)((long)*ptrd << (int)mp(x,y,z,c)); --ptrd; }
-        else if (*expression=='>') cimg_forXYZC(*this,x,y,z,c) { *ptrd = (T)((long)*ptrd << (int)mp(x,y,z,c)); ++ptrd; }
-        else {
-#ifdef cimg_use_openmp
-          if (_width>=512 && _height*_depth*_spectrum>=2 && std::strlen(expression)>=6)
-#pragma omp parallel
-          {
-            _cimg_math_parser _mp = omp_get_thread_num()?mp:_cimg_math_parser(), &lmp = omp_get_thread_num()?_mp:mp;
-#pragma omp for collapse(3)
-            cimg_forYZC(*this,y,z,c) {
-              T *ptrd = data(0,y,z,c);
-              cimg_forX(*this,x) { *ptrd = (T)((long)*ptrd << (int)lmp(x,y,z,c)); ++ptrd; }
-            }
-          }
-          else
-#endif
-            cimg_forXYZC(*this,x,y,z,c) { *ptrd = (T)((long)*ptrd << (int)mp(x,y,z,c)); ++ptrd; }
-        }
-      } catch (CImgException&) {
-        cimg::exception_mode(omode);
-        *this<<=CImg<T>(_width,_height,_depth,_spectrum,expression,true);
-      }
-      cimg::exception_mode(omode);
-      return *this;
+      return *this<<=(+*this)._fill(expression,true,true,0,0,"operator<<=",this);
     }
 
     //! In-place bitwise left shift operator.
@@ -11297,14 +11205,14 @@ namespace cimg_library_suffixed {
     **/
     template<typename t>
     CImg<T>& operator<<=(const CImg<t>& img) {
-      const unsigned long siz = size(), isiz = img.size();
+      const ulongT siz = size(), isiz = img.size();
       if (siz && isiz) {
         if (is_overlapped(img)) return *this^=+img;
         T *ptrd = _data, *const ptre = _data + siz;
-        if (siz>isiz) for (unsigned long n = siz/isiz; n; --n)
+        if (siz>isiz) for (ulongT n = siz/isiz; n; --n)
           for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs<ptrs_end; ++ptrd)
-            *ptrd = (T)((long)*ptrd << (int)*(ptrs++));
-        for (const t *ptrs = img._data; ptrd<ptre; ++ptrd) *ptrd = (T)((long)*ptrd << (int)*(ptrs++));
+            *ptrd = (T)((longT)*ptrd << (int)*(ptrs++));
+        for (const t *ptrs = img._data; ptrd<ptre; ++ptrd) *ptrd = (T)((longT)*ptrd << (int)*(ptrs++));
       }
       return *this;
     }
@@ -11347,9 +11255,9 @@ namespace cimg_library_suffixed {
     CImg<T>& operator>>=(const t value) {
       if (is_empty()) return *this;
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (size()>=65536)
+#pragma omp parallel for cimg_openmp_if(size()>=65536)
 #endif
-      cimg_rof(*this,ptrd,T) *ptrd = (T)(((long)*ptrd) >> (int)value);
+      cimg_rof(*this,ptrd,T) *ptrd = (T)(((longT)*ptrd) >> (int)value);
       return *this;
     }
 
@@ -11358,37 +11266,7 @@ namespace cimg_library_suffixed {
        Similar to operator+=(const char*), except that it performs a bitwise right shift instead of an addition.
     **/
     CImg<T>& operator>>=(const char *const expression) {
-      if (is_empty()) return *this;
-      const unsigned int omode = cimg::exception_mode();
-      cimg::exception_mode(0);
-      try {
-        const CImg<T> _base = cimg::_is_self_expr(expression)?+*this:CImg<T>(), &base = _base?_base:*this;
-        _cimg_math_parser mp(base,this,expression + (*expression=='>' || *expression=='<'?1:0),"operator<<=");
-        T *ptrd = *expression=='<'?end() - 1:_data;
-        if (*expression=='<') cimg_rofXYZC(*this,x,y,z,c) { *ptrd = (T)((long)*ptrd >> (int)mp(x,y,z,c)); --ptrd; }
-        else if (*expression=='>') cimg_forXYZC(*this,x,y,z,c) { *ptrd = (T)((long)*ptrd >> (int)mp(x,y,z,c)); ++ptrd; }
-        else {
-#ifdef cimg_use_openmp
-          if (_width>=512 && _height*_depth*_spectrum>=2 && std::strlen(expression)>=6)
-#pragma omp parallel
-          {
-            _cimg_math_parser _mp = omp_get_thread_num()?mp:_cimg_math_parser(), &lmp = omp_get_thread_num()?_mp:mp;
-#pragma omp for collapse(3)
-            cimg_forYZC(*this,y,z,c) {
-              T *ptrd = data(0,y,z,c);
-              cimg_forX(*this,x) { *ptrd = (T)((long)*ptrd >> (int)lmp(x,y,z,c)); ++ptrd; }
-            }
-          }
-          else
-#endif
-            cimg_forXYZC(*this,x,y,z,c) { *ptrd = (T)((long)*ptrd >> (int)mp(x,y,z,c)); ++ptrd; }
-        }
-      } catch (CImgException&) {
-        cimg::exception_mode(omode);
-        *this>>=CImg<T>(_width,_height,_depth,_spectrum,expression,true);
-      }
-      cimg::exception_mode(omode);
-      return *this;
+      return *this>>=(+*this)._fill(expression,true,true,0,0,"operator>>=",this);
     }
 
     //! In-place bitwise right shift operator.
@@ -11397,14 +11275,14 @@ namespace cimg_library_suffixed {
     **/
     template<typename t>
     CImg<T>& operator>>=(const CImg<t>& img) {
-      const unsigned long siz = size(), isiz = img.size();
+      const ulongT siz = size(), isiz = img.size();
       if (siz && isiz) {
         if (is_overlapped(img)) return *this^=+img;
         T *ptrd = _data, *const ptre = _data + siz;
-        if (siz>isiz) for (unsigned long n = siz/isiz; n; --n)
+        if (siz>isiz) for (ulongT n = siz/isiz; n; --n)
           for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs<ptrs_end; ++ptrd)
-            *ptrd = (T)((long)*ptrd >> (int)*(ptrs++));
-        for (const t *ptrs = img._data; ptrd<ptre; ++ptrd) *ptrd = (T)((long)*ptrd >> (int)*(ptrs++));
+            *ptrd = (T)((longT)*ptrd >> (int)*(ptrs++));
+        for (const t *ptrs = img._data; ptrd<ptre; ++ptrd) *ptrd = (T)((longT)*ptrd >> (int)*(ptrs++));
       }
       return *this;
     }
@@ -11446,7 +11324,7 @@ namespace cimg_library_suffixed {
     CImg<T> operator~() const {
       CImg<T> res(_width,_height,_depth,_spectrum);
       const T *ptrs = _data;
-      cimg_for(res,ptrd,T) { const unsigned long value = (unsigned long)*(ptrs++); *ptrd = (T)~value; }
+      cimg_for(res,ptrd,T) { const ulongT value = (ulongT)*(ptrs++); *ptrd = (T)~value; }
       return res;
     }
 
@@ -11470,25 +11348,7 @@ namespace cimg_library_suffixed {
        \param expression Value string describing the way pixel values are compared.
     **/
     bool operator==(const char *const expression) const {
-      if (is_empty()) return !*expression;
-      const unsigned int omode = cimg::exception_mode();
-      cimg::exception_mode(0);
-      bool is_equal = true;
-      try {
-        const CImg<T> _base = cimg::_is_self_expr(expression)?+*this:CImg<T>(), &base = _base?_base:*this;
-        _cimg_math_parser mp(base,0,expression + (*expression=='>' || *expression=='<'?1:0),"operator<<=");
-        const T *ptrs = *expression=='<'?end() - 1:_data;
-        if (*expression=='<')
-          cimg_rofXYZC(*this,x,y,z,c) { if (!is_equal) break; is_equal = ((double)*(ptrs--)==mp(x,y,z,c)); }
-        else if (*expression=='>')
-          cimg_forXYZC(*this,x,y,z,c) { if (!is_equal) break; is_equal = ((double)*(ptrs++)==mp(x,y,z,c)); }
-        else cimg_forXYZC(*this,x,y,z,c) { if (!is_equal) break; is_equal = ((double)*(ptrs++)==mp(x,y,z,c)); }
-      } catch (CImgException&) {
-        cimg::exception_mode(omode);
-        is_equal = (*this==CImg<T>(_width,_height,_depth,_spectrum,expression,true));
-      }
-      cimg::exception_mode(omode);
-      return is_equal;
+      return *this==(+*this)._fill(expression,true,true,0,0,"operator==",this);
     }
 
     //! Test if two images have the same size and values.
@@ -11513,7 +11373,7 @@ namespace cimg_library_suffixed {
     template<typename t>
     bool operator==(const CImg<t>& img) const {
       typedef _cimg_Tt Tt;
-      const unsigned long siz = size();
+      const ulongT siz = size();
       bool is_equal = true;
       if (siz!=img.size()) return false;
       t *ptrs = img._data + siz;
@@ -11724,8 +11584,8 @@ namespace cimg_library_suffixed {
                      img.size()*sizeof(float));
        \endcode
     **/
-    unsigned long size() const {
-      return (unsigned long)_width*_height*_depth*_spectrum;
+    ulongT size() const {
+      return (ulongT)_width*_height*_depth*_spectrum;
     }
 
     //! Return a pointer to the first pixel value.
@@ -11763,7 +11623,7 @@ namespace cimg_library_suffixed {
      **/
 #if cimg_verbosity>=3
     T *data(const unsigned int x, const unsigned int y=0, const unsigned int z=0, const unsigned int c=0) {
-      const unsigned long off = (unsigned long)offset(x,y,z,c);
+      const ulongT off = (ulongT)offset(x,y,z,c);
       if (off>=size())
         cimg::warn(_cimg_instance
                    "data(): Invalid pointer request, at coordinates (%u,%u,%u,%u) [offset=%u].",
@@ -11778,12 +11638,11 @@ namespace cimg_library_suffixed {
     }
 #else
     T* data(const unsigned int x, const unsigned int y=0, const unsigned int z=0, const unsigned int c=0) {
-      return _data + x + y*(unsigned long)_width + z*(unsigned long)_width*_height +
-        c*(unsigned long)_width*_height*_depth;
+      return _data + x + (ulongT)y*_width + (ulongT)z*_width*_height + (ulongT)c*_width*_height*_depth;
     }
 
     const T* data(const unsigned int x, const unsigned int y=0, const unsigned int z=0, const unsigned int c=0) const {
-      return _data + x + y*_width + z*(unsigned long)_width*_height + c*(unsigned long)_width*_height*_depth;
+      return _data + x + (ulongT)y*_width + (ulongT)z*_width*_height + (ulongT)c*_width*_height*_depth;
     }
 #endif
 
@@ -11803,8 +11662,8 @@ namespace cimg_library_suffixed {
        const float val = img[off];              // Get the blue value of this pixel.
        \endcode
     **/
-    long offset(const int x, const int y=0, const int z=0, const int c=0) const {
-      return x + y*(long)_width + z*(long)(_width*_height) + c*(long)(_width*_height*_depth);
+    longT offset(const int x, const int y=0, const int z=0, const int c=0) const {
+      return x + (longT)y*_width + (longT)z*_width*_height + (longT)c*_width*_height*_depth;
     }
 
     //! Return a CImg<T>::iterator pointing to the first pixel value.
@@ -13013,6 +12872,8 @@ namespace cimg_library_suffixed {
        of the image instance (written in base 10), separated by specified \c separator character.
        \param separator A \c char character which specifies the separator between values in the returned C-string.
        \param max_size Maximum size of the returned image.
+       \param format For float-values, tell the printf format used to generate the ascii representation of the numbers.
+         (or \c 0 for default representation).
        \note
        - The returned image is never empty.
        - For an empty image instance, the returned string is <tt>""</tt>.
@@ -13020,15 +12881,18 @@ namespace cimg_library_suffixed {
        - Otherwise, if the maximum number of string characters is exceeded, the value string is cut off
          and terminated by character \c '\0'. In that case, the returned image size is <tt>max_size + 1</tt>.
     **/
-    CImg<charT> value_string(const char separator=',', const unsigned int max_size=0) const {
+    CImg<charT> value_string(const char separator=',', const unsigned int max_size=0,
+                             const char *const format=0) const {
       if (is_empty()) return CImg<charT>::string("");
       CImgList<charT> items;
       CImg<charT> s_item(256); *s_item = 0;
       const T *ptrs = _data;
       unsigned int string_size = 0;
-      for (unsigned long off = 0, siz = (unsigned int)size(); off<siz && string_size<=max_size; ++off) {
-        const unsigned int printed_size = 1U + cimg_snprintf(s_item,s_item._width,
-                                                             cimg::type<T>::format(),cimg::type<T>::format(*(ptrs++)));
+      const char *const _format = format?format:cimg::type<T>::format();
+
+      for (ulongT off = 0, siz = size(); off<siz && string_size<=max_size; ++off) {
+        const unsigned int printed_size = 1U + cimg_snprintf(s_item,s_item._width,_format,
+                                                             cimg::type<T>::format(*(ptrs++)));
         CImg<charT> item(s_item._data,printed_size);
         item[printed_size - 1] = separator;
         item.move_to(items);
@@ -13078,9 +12942,9 @@ namespace cimg_library_suffixed {
       return false;
     }
 
-    //! Test if image instance contains a 'nan' value.
+    //! Test if image instance contains a NaN value.
     /**
-       Return \c true, if image instance contains a 'nan' value, and \c false otherwise.
+       Return \c true, if image instance contains a NaN value, and \c false otherwise.
     **/
     bool is_nan() const {
       if (cimg::type<T>::is_float()) cimg_for(*this,p,T) if (cimg::type<T>::is_nan((float)*p)) return true;
@@ -13381,15 +13245,15 @@ namespace cimg_library_suffixed {
     **/
     template<typename t>
     bool contains(const T& pixel, t& x, t& y, t& z, t& c) const {
-      const unsigned long wh = (unsigned long)_width*_height, whd = wh*_depth, siz = whd*_spectrum;
+      const ulongT wh = (ulongT)_width*_height, whd = wh*_depth, siz = whd*_spectrum;
       const T *const ppixel = &pixel;
       if (is_empty() || ppixel<_data || ppixel>=_data + siz) return false;
-      unsigned long off = (unsigned long)(ppixel - _data);
-      const unsigned long nc = off/whd;
+      ulongT off = (ulongT)(ppixel - _data);
+      const ulongT nc = off/whd;
       off%=whd;
-      const unsigned long nz = off/wh;
+      const ulongT nz = off/wh;
       off%=wh;
-      const unsigned long ny = off/_width, nx = off%_width;
+      const ulongT ny = off/_width, nx = off%_width;
       x = (t)nx; y = (t)ny; z = (t)nz; c = (t)nc;
       return true;
     }
@@ -13400,13 +13264,13 @@ namespace cimg_library_suffixed {
     **/
     template<typename t>
     bool contains(const T& pixel, t& x, t& y, t& z) const {
-      const unsigned long wh = (unsigned long)_width*_height, whd = wh*_depth, siz = whd*_spectrum;
+      const ulongT wh = (ulongT)_width*_height, whd = wh*_depth, siz = whd*_spectrum;
       const T *const ppixel = &pixel;
       if (is_empty() || ppixel<_data || ppixel>=_data + siz) return false;
-      unsigned long off = ((unsigned long)(ppixel - _data))%whd;
-      const unsigned long nz = off/wh;
+      ulongT off = ((ulongT)(ppixel - _data))%whd;
+      const ulongT nz = off/wh;
       off%=wh;
-      const unsigned long ny = off/_width, nx = off%_width;
+      const ulongT ny = off/_width, nx = off%_width;
       x = (t)nx; y = (t)ny; z = (t)nz;
       return true;
     }
@@ -13417,11 +13281,11 @@ namespace cimg_library_suffixed {
     **/
     template<typename t>
     bool contains(const T& pixel, t& x, t& y) const {
-      const unsigned long wh = (unsigned long)_width*_height, siz = wh*_depth*_spectrum;
+      const ulongT wh = (ulongT)_width*_height, siz = wh*_depth*_spectrum;
       const T *const ppixel = &pixel;
       if (is_empty() || ppixel<_data || ppixel>=_data + siz) return false;
-      unsigned long off = ((unsigned int)(ppixel - _data))%wh;
-      const unsigned long ny = off/_width, nx = off%_width;
+      ulongT off = ((unsigned int)(ppixel - _data))%wh;
+      const ulongT ny = off/_width, nx = off%_width;
       x = (t)nx; y = (t)ny;
       return true;
     }
@@ -13434,7 +13298,7 @@ namespace cimg_library_suffixed {
     bool contains(const T& pixel, t& x) const {
       const T *const ppixel = &pixel;
       if (is_empty() || ppixel<_data || ppixel>=_data + size()) return false;
-      x = (t)(((unsigned long)(ppixel - _data))%_width);
+      x = (t)(((ulongT)(ppixel - _data))%_width);
       return true;
     }
 
@@ -13468,7 +13332,7 @@ namespace cimg_library_suffixed {
     **/
     template<typename t>
     bool is_overlapped(const CImg<t>& img) const {
-      const unsigned long csiz = size(), isiz = img.size();
+      const ulongT csiz = size(), isiz = img.size();
       return !((void*)(_data + csiz)<=(void*)img._data || (void*)_data>=(void*)(img._data + isiz));
     }
 
@@ -13531,7 +13395,7 @@ namespace cimg_library_suffixed {
       // Check consistency of primitives.
       cimglist_for(primitives,l) {
         const CImg<tp>& primitive = primitives[l];
-        const unsigned long psiz = primitive.size();
+        const unsigned int psiz = primitive.size();
         switch (psiz) {
         case 1 : { // Point.
           const unsigned int i0 = (unsigned int)primitive(0);
@@ -13664,7 +13528,7 @@ namespace cimg_library_suffixed {
 
       // Check consistency of number of vertices / primitives.
       if (!full_check) {
-        const unsigned long minimal_size = 8UL + 3*nb_points + 6*nb_primitives;
+        const ulongT minimal_size = 8UL + 3*nb_points + 6*nb_primitives;
         if (_data + minimal_size>ptre) {
           if (error_message) cimg_sprintf(error_message,
                                           "CImg3d (%u,%u) has only %lu values, while at least %lu values were expected",
@@ -13875,1440 +13739,5937 @@ namespace cimg_library_suffixed {
     //@{
     //-------------------------------------
 
-    // Define the math formula parser/compiler and evaluator.
+    // Define the math formula parser/compiler and expression evaluator.
     struct _cimg_math_parser {
-      CImgList<longT> code;
-      CImg<longT> opcode;
-      const CImg<longT>* p_code;
-      CImgList<charT> labelM;
-      CImg<uintT> level, labelMpos, reserved_label;
       CImg<doubleT> mem;
-      CImg<charT> expr;
-      const CImg<T>& input;
-      CImg<T> &output;
-      CImg<Tdouble> input_stats;
-      double median_value;
-      bool is_median_value;
-      unsigned int mempos, result;
-      const char *const calling_function;
+      CImg<intT> memtype;
+      CImgList<ulongT> _code, &code;
+      CImg<ulongT> opcode;
+      const CImg<ulongT> *p_code_begin, *p_code_end, *p_code;
+
+      CImg<charT> expr, pexpr;
+      const CImg<T>& imgin;
+      const CImgList<T>& listin;
+      CImg<T> &imgout;
+      CImgList<T>& listout;
+
+      CImg<doubleT> _img_stats, &img_stats;
+      CImgList<doubleT> _list_stats, &list_stats, _list_median, &list_median;
+      CImg<uintT> mem_img_stats;
+
+      CImg<uintT> level, variable_pos, reserved_label;
+      CImgList<charT> variable_def, function_def, function_body;
+      char *user_function;
+
+      unsigned int mempos, mem_img_median, debug_indent, init_size, result_dim;
+      bool is_parallelizable, need_input_copy;
+      double *result;
+      const char *const calling_function, *s_op, *ss_op;
       typedef double (*mp_func)(_cimg_math_parser&);
 
-#define _cimg_mp_return(x) { *se = saved_char; return x; }
-#define _cimg_mp_opcode0(op) _cimg_mp_return(opcode0(op));
-#define _cimg_mp_opcode1(op,i1) _cimg_mp_return(opcode1(op,i1));
-#define _cimg_mp_opcode2(op,i1,i2) { const unsigned int _i1 = i1, _i2 = i2; _cimg_mp_return(opcode2(op,_i1,_i2)); }
-#define _cimg_mp_opcode3(op,i1,i2,i3) \
-  { const unsigned int _i1 = i1, _i2 = i2, _i3 = i3; _cimg_mp_return(opcode3(op,_i1,_i2,_i3)); }
-#define _cimg_mp_opcode5(op,i1,i2,i3,i4,i5) \
-  { const unsigned int _i1 = i1, _i2 = i2, _i3 = i3, _i4 = i4, _i5 = i5; \
-        _cimg_mp_return(opcode5(op,_i1,_i2,_i3,_i4,_i5)); }
-#define _cimg_mp_opcode6(op,i1,i2,i3,i4,i5,i6) \
-  { const unsigned int _i1 = i1, _i2 = i2, _i3 = i3, _i4 = i4, _i5 = i5, _i6 = i6; \
-        _cimg_mp_return(opcode6(op,_i1,_i2,_i3,_i4,_i5,_i6)); }
-
-#if defined(_WIN64)
-      // On Win64 and gcc 4.7, sizeof(long)!=sizeof(pointer), so a workaround is needed..
-#define _cimg_mp_enfunc(op) (long)((char*)(op) - (char*)mp_u)
-#define _cimg_mp_defunc(mp) (*(mp_func)((char*)mp_u + (mp).opcode[0]))(mp)
-#else
-#define _cimg_mp_enfunc(op) (long)(op)
-#define _cimg_mp_defunc(mp) (*(mp_func)((mp).opcode[0]))(mp)
-#endif
+#define _cimg_mp_is_constant(arg) (memtype[arg]==1) // Is constant?
+#define _cimg_mp_is_scalar(arg) (memtype[arg]<2) // Is scalar?
+#define _cimg_mp_is_temp(arg) (!memtype[arg]) // Is temporary scalar?
+#define _cimg_mp_is_variable(arg) (memtype[arg]==-1) // Is scalar variable?
+#define _cimg_mp_is_vector(arg) (memtype[arg]>1) // Is vector?
+#define _cimg_mp_vector_size(arg) (_cimg_mp_is_scalar(arg)?0U:(unsigned int)memtype[arg] - 1) // Vector size
+#define _cimg_mp_calling_function calling_function_s()._data
+#define _cimg_mp_op(s) s_op = s; ss_op = ss
+#define _cimg_mp_check_type(arg,n_arg,mode,N) check_type(arg,n_arg,mode,N,ss,se,saved_char)
+#define _cimg_mp_check_constant(arg,n_arg,is_strict) check_constant(arg,n_arg,is_strict,ss,se,saved_char)
+#define _cimg_mp_check_matrix_square(arg,n_arg) check_matrix_square(arg,n_arg,ss,se,saved_char)
+#define _cimg_mp_check_vector0(dim) check_vector0(dim,ss,se,saved_char)
+#define _cimg_mp_check_list(is_out) check_list(is_out,ss,se,saved_char)
+#define _cimg_mp_defunc(mp) (*(mp_func)(*(mp).opcode))(mp)
+#define _cimg_mp_return(x) { *se = saved_char; s_op = previous_s_op; ss_op = previous_ss_op; return x; }
+#define _cimg_mp_constant(val) _cimg_mp_return(constant((double)(val)))
+#define _cimg_mp_scalar0(op) _cimg_mp_return(scalar0(op))
+#define _cimg_mp_scalar1(op,i1) _cimg_mp_return(scalar1(op,i1))
+#define _cimg_mp_scalar2(op,i1,i2) _cimg_mp_return(scalar2(op,i1,i2))
+#define _cimg_mp_scalar3(op,i1,i2,i3) _cimg_mp_return(scalar3(op,i1,i2,i3))
+#define _cimg_mp_scalar6(op,i1,i2,i3,i4,i5,i6) _cimg_mp_return(scalar6(op,i1,i2,i3,i4,i5,i6))
+#define _cimg_mp_scalar7(op,i1,i2,i3,i4,i5,i6,i7) _cimg_mp_return(scalar7(op,i1,i2,i3,i4,i5,i6,i7))
+#define _cimg_mp_vector1_v(op,i1) _cimg_mp_return(vector1_v(op,i1))
+#define _cimg_mp_vector2_sv(op,i1,i2) _cimg_mp_return(vector2_sv(op,i1,i2))
+#define _cimg_mp_vector2_vs(op,i1,i2) _cimg_mp_return(vector2_vs(op,i1,i2))
+#define _cimg_mp_vector2_vv(op,i1,i2) _cimg_mp_return(vector2_vv(op,i1,i2))
+#define _cimg_mp_vector3_vss(op,i1,i2,i3) _cimg_mp_return(vector3_vss(op,i1,i2,i3))
 
       // Constructors.
-      _cimg_math_parser():input(CImg<T>::empty()),output(CImg<T>::empty()),
-                          median_value(0),is_median_value(false),calling_function(0) {}
-
-      _cimg_math_parser(const CImg<T>& img_input, CImg<T> *const img_output,
-                        const char *const expression, const char *const funcname=0):
-        input(img_input),output(img_output?*img_output:CImg<T>::empty()),
-        median_value(0),is_median_value(false),calling_function(funcname?funcname:"cimg_math_parser") {
+      _cimg_math_parser(const char *const expression, const char *const funcname=0,
+                        const CImg<T>& img_input=CImg<T>::const_empty(), CImg<T> *const img_output=0,
+                        const CImgList<T> *const list_input=0, CImgList<T> *const list_output=0):
+        code(_code),imgin(img_input),listin(list_input?*list_input:CImgList<T>::const_empty()),
+        imgout(img_output?*img_output:CImg<T>::empty()),listout(list_output?*list_output:CImgList<T>::empty()),
+        img_stats(_img_stats),list_stats(_list_stats),list_median(_list_median),user_function(0),
+        mem_img_median(~0U),debug_indent(0),init_size(0),result_dim(0),is_parallelizable(true),
+        need_input_copy(false),calling_function(funcname?funcname:"cimg_math_parser") {
         if (!expression || !*expression)
           throw CImgArgumentException("[_cimg_math_parser] "
-                                      "CImg<%s>::%s(): Empty specified expression.",
-                                      pixel_type(),calling_function);
-        CImg<charT>::string(expression).move_to(expr);
+                                      "CImg<%s>::%s: Empty expression.",
+                                      pixel_type(),_cimg_mp_calling_function);
+        const char *_expression = expression;
+        while (*_expression && (*_expression<=' ' || *_expression==';')) ++_expression;
+        CImg<charT>::string(_expression).move_to(expr);
+        char *ps = &expr.back() - 1;
+        while (ps>expr._data && (*ps==' ' || *ps==';')) --ps;
+        *(++ps) = 0; expr._width = (unsigned int)(ps - expr._data + 1);
+
+        // Ease the retrieval of previous non-space characters afterwards.
+        pexpr.assign(expr._width);
+
+        char c, *pe = pexpr._data;
+        for (ps = expr._data, c = ' '; *ps; ++ps) {
+          if (*ps!=' ') c = *ps;
+          *(pe++) = c;
+        }
+        *pe = 0;
+
+        // Count parentheses/brackets level of expression.
         level.assign(expr._width - 1);
-        int lv = 0; // Count parentheses/brackets level of expression.
+        int lv = 0;
         unsigned int *pd = level._data;
-        for (const char *ps = expr._data; *ps && lv>=0; ++ps)
+        for (ps = expr._data; *ps && lv>=0; ++ps)
           *(pd++) = (unsigned int)(*ps=='('||*ps=='['?lv++:*ps==')'||*ps==']'?--lv:lv);
         if (lv!=0) {
+          cimg::strellipsize(expr,64);
           throw CImgArgumentException("[_cimg_math_parser] "
-                                      "CImg<%s>::%s(): Unbalanced parentheses/brackets in expression '%s'.",
-                                      pixel_type(),calling_function,
+                                      "CImg<%s>::%s: Unbalanced parentheses/brackets, in expression '%s'.",
+                                      pixel_type(),_cimg_mp_calling_function,
                                       expr._data);
         }
 
         // Init constant values.
-        mem.assign(512);
-        mem[0] = 0.0;
-        mem[1] = 1.0;
-        mem[2] = 2.0;
-        mem[3] = 3.0;
-        mem[4] = 4.0;
-        mem[5] = 5.0;
-        mem[6] = (double)input._width;
-        mem[7] = (double)input._height;
-        mem[8] = (double)input._depth;
-        mem[9] = (double)input._spectrum;
-        mem[10] = (double)input._is_shared;
-        mem[11] = (double)input._width*input._height;
-        mem[12] = (double)input._width*input._height*input._depth;
-        mem[13] = (double)input._width*input._height*input._depth*input._spectrum;
-        mem[14] = cimg::PI;
-        mem[15] = std::exp(1.0); // Then [16] = x, [17] = y, [18] = z and [19] = c.
-        mempos = 20;
-        labelMpos.assign(8);
+        mem.assign(96);
+        memtype.assign(96);
+        double *p_mem = mem._data;
+        for (unsigned int i = 0; i<=10; ++i) *(p_mem++) = (double)i;  // mem[0-10]
+        for (unsigned int i = 1; i<=5; ++i) *(p_mem++) = -(double)i;  // mem[11-15]
+        *(p_mem++) = 0.5; // mem[16]
+        *(p_mem++) = 0; // mem[17] = thread_id
+        *(p_mem++) = (double)imgin._width; // mem[18]
+        *(p_mem++) = (double)imgin._height; // mem[19]
+        *(p_mem++) = (double)imgin._depth; // mem[20]
+        *(p_mem++) = (double)imgin._spectrum; // mem[21]
+        *(p_mem++) = (double)imgin._is_shared; // mem[22]
+        *(p_mem++) = (double)imgin._width*imgin._height; // mem[23]
+        *(p_mem++) = (double)imgin._width*imgin._height*imgin._depth; // mem[24]
+        *(p_mem++) = (double)imgin._width*imgin._height*imgin._depth*imgin._spectrum; // mem[25]
+        *(p_mem++) = cimg::PI; // mem[26]
+        *(p_mem++) = std::exp(1.0); // mem[27]
+        *(p_mem++) = cimg::type<double>::nan(); // mem[28]
+
+        // Then, [29] = x, [30] = y, [31] = z and [32] = c.
+#define _cimg_mp_x 29
+#define _cimg_mp_y 30
+#define _cimg_mp_z 31
+#define _cimg_mp_c 32
+
+        // Set value property :
+        // { -1 = variable | 0 = regular value | 1 = compile time constant | N>1 = constant ptr to vector[N-1] }.
+        std::memset(memtype._data,0,sizeof(int)*memtype._width);
+        int *p_memtype = memtype._data; for (unsigned int i = 0; i<_cimg_mp_x; ++i) *(p_memtype++) = 1;
+        memtype[17] = 0;
+
+        mempos = _cimg_mp_c + 1;
+        variable_pos.assign(8);
         reserved_label.assign(128,1,1,1,~0U);
-        reserved_label['w'] = 6;
-        reserved_label['h'] = 7;
-        reserved_label['d'] = 8;
-        reserved_label['s'] = 9;
-        reserved_label['r'] = 10;
-        reserved_label[0] = 11; // wh
-        reserved_label[1] = 12; // whd
-        reserved_label[2] = 13; // whds
-        reserved_label[3] = 14; // pi
-        reserved_label['e'] = 15;
-        reserved_label['x'] = 16;
-        reserved_label['y'] = 17;
-        reserved_label['z'] = 18;
-        reserved_label['c'] = 19;
-        result = compile(expr._data,expr._data + expr._width - 1); // Compile formula into a serie of opcodes.
-      }
-
-      // Insert code instructions.
-      unsigned int opcode0(const mp_func op) {
-        if (mempos>=mem._width) mem.resize(-200,1,1,1,0);
-        const unsigned int pos = mempos++;
-        CImg<longT>::vector(_cimg_mp_enfunc(op),pos).move_to(code);
-        return pos;
-      }
-
-      unsigned int opcode1(const mp_func op, const unsigned int arg1) {
-        if (mempos>=mem._width) mem.resize(-200,1,1,1,0);
-        const unsigned int pos = mempos++;
-        CImg<longT>::vector(_cimg_mp_enfunc(op),pos,arg1).move_to(code);
-        return pos;
-      }
-
-      unsigned int opcode2(const mp_func op, const unsigned int arg1, const unsigned int arg2) {
-        if (mempos>=mem._width) mem.resize(-200,1,1,1,0);
-        const unsigned int pos = mempos++;
-        CImg<longT>::vector(_cimg_mp_enfunc(op),pos,arg1,arg2).move_to(code);
-        return pos;
-      }
-
-      unsigned int opcode3(const mp_func op,
-                           const unsigned int arg1, const unsigned int arg2, const unsigned int arg3) {
-        if (mempos>=mem._width) mem.resize(-200,1,1,1,0);
-        const unsigned int pos = mempos++;
-        CImg<longT>::vector(_cimg_mp_enfunc(op),pos,arg1,arg2,arg3).move_to(code);
-        return pos;
+        reserved_label['t'] = 17;
+        reserved_label['w'] = 18;
+        reserved_label['h'] = 19;
+        reserved_label['d'] = 20;
+        reserved_label['s'] = 21;
+        reserved_label['r'] = 22;
+        reserved_label[0] = 23; // wh
+        reserved_label[1] = 24; // whd
+        reserved_label[2] = 25; // whds
+        reserved_label[3] = 26; // pi
+        reserved_label['e'] = 27;
+        reserved_label[29] = 0; // interpolation
+        reserved_label[30] = 0; // boundary
+        reserved_label['x'] = _cimg_mp_x;
+        reserved_label['y'] = _cimg_mp_y;
+        reserved_label['z'] = _cimg_mp_z;
+        reserved_label['c'] = _cimg_mp_c;
+        // reserved_label[4-28] store also two-char variables:
+        // [4] = im, [5] = iM, [6] = ia, [7] = iv, [8] = is, [9] = ip, [10] = ic,
+        // [11] = xm, [12] = ym, [13] = zm, [14] = cm, [15] = xM, [16] = yM, [17] = zM, [18]=cM, [19]=i0...[28]=i9,
+
+        // Compile expression into a serie of opcodes.
+        s_op = ""; ss_op = expr._data;
+        const unsigned int ind_result = compile(expr._data,expr._data + expr._width - 1,0,0);
+        p_code_end = code.end();
+
+        // Free resources used for parsing and prepare for evaluation.
+        if (_cimg_mp_is_vector(ind_result)) result_dim = _cimg_mp_vector_size(ind_result);
+        mem.resize(mempos,1,1,1,-1);
+        result = mem._data + ind_result;
+        memtype.assign();
+        level.assign();
+        variable_pos.assign();
+        reserved_label.assign();
+        expr.assign();
+        pexpr.assign();
+        opcode.assign();
+        opcode._width = opcode._depth = opcode._spectrum = 1;
+        opcode._is_shared = true;
+
+        // Execute init() function if any specified.
+        p_code_begin = code._data + init_size;
+        if (init_size) {
+          mem[_cimg_mp_x] = mem[_cimg_mp_y] = mem[_cimg_mp_z] = mem[_cimg_mp_c] = 0;
+          for (p_code = code._data; p_code<p_code_begin; ++p_code) {
+            const CImg<ulongT> &op = *p_code;
+            opcode._data = op._data; opcode._height = op._height;
+            const ulongT target = opcode[1];
+            mem[target] = _cimg_mp_defunc(*this);
+          }
+        }
+      }
+
+      _cimg_math_parser():
+        code(_code),p_code_begin(0),p_code_end(0),
+        imgin(CImg<T>::const_empty()),listin(CImgList<T>::const_empty()),
+        imgout(CImg<T>::empty()),listout(CImgList<T>::empty()),
+        img_stats(_img_stats),list_stats(_list_stats),list_median(_list_median),debug_indent(0),
+        result_dim(0),is_parallelizable(true),need_input_copy(false),calling_function(0) {
+        mem.assign(1 + _cimg_mp_c,1,1,1,0); // Allow to skip 'is_empty?' test in operator()()
+        result = mem._data;
+      }
+
+      _cimg_math_parser(const _cimg_math_parser& mp):
+        mem(mp.mem),code(mp.code),p_code_begin(mp.p_code_begin),p_code_end(mp.p_code_end),
+        imgin(mp.imgin),listin(mp.listin),imgout(mp.imgout),listout(mp.listout),img_stats(mp.img_stats),
+        list_stats(mp.list_stats),list_median(mp.list_median),debug_indent(0),result_dim(mp.result_dim),
+        is_parallelizable(mp.is_parallelizable), need_input_copy(mp.need_input_copy),
+        result(mem._data + (mp.result - mp.mem._data)),calling_function(0) {
+#ifdef cimg_use_openmp
+        mem[17] = omp_get_thread_num();
+#endif
+        opcode._width = opcode._depth = opcode._spectrum = 1;
+        opcode._is_shared = true;
       }
 
-      unsigned int opcode5(const mp_func op,
-                           const unsigned int arg1, const unsigned int arg2, const unsigned int arg3,
-                           const unsigned int arg4, const unsigned int arg5) {
-        if (mempos>=mem._width) mem.resize(-200,1,1,1,0);
-        const unsigned int pos = mempos++;
-        CImg<longT>::vector(_cimg_mp_enfunc(op),pos,arg1,arg2,arg3,arg4,arg5).move_to(code);
-        return pos;
-      }
+      // Compilation procedure.
+      unsigned int compile(char *ss, char *se, const unsigned int depth, unsigned int *const p_ref) {
+        if (depth>256) {
+          cimg::strellipsize(expr,64);
+          throw CImgArgumentException("[_cimg_math_parser] "
+                                      "CImg<%s>::%s: Call stack overflow (infinite recursion?), "
+                                      "in expression '%s%s%s'.",
+                                      pixel_type(),_cimg_mp_calling_function,
+                                      (ss - 4)>expr._data?"...":"",
+                                      (ss - 4)>expr._data?ss - 4:expr._data,
+                                      se<&expr.back()?"...":"");
+        }
 
-      unsigned int opcode6(const mp_func op,
-                           const unsigned int arg1, const unsigned int arg2, const unsigned int arg3,
-                           const unsigned int arg4, const unsigned int arg5, const unsigned int arg6) {
-        if (mempos>=mem._width) mem.resize(-200,1,1,1,0);
-        const unsigned int pos = mempos++;
-        CImg<longT>::vector(_cimg_mp_enfunc(op),pos,arg1,arg2,arg3,arg4,arg5,arg6).move_to(code);
-        return pos;
-      }
+        const char *const ss0 = ss;
+        char c1, c2, c3, c4;
 
-      // Compilation procedure.
-      unsigned int compile(char *ss, char *se) {
         if (ss<se) {
-          while (*ss==' ') ++ss;
-          while (se>ss && *(se-1)==' ') --se;
+          while (*ss && (*ss<=' ' || *ss==';')) ++ss;
+          while (se>ss && (c1=*(se - 1))>0 && (c1<=' ' || c1==';')) --se;
+        }
+        if (se>ss && *(se - 1)==';') --se;
+        while (*ss=='(' && *(se - 1)==')' && std::strchr(ss,')')==se - 1) { // Detect simple content around parentheses.
+          ++ss; --se;
         }
         if (se<=ss || !*ss) {
+          cimg::strellipsize(expr,64);
           throw CImgArgumentException("[_cimg_math_parser] "
-                                      "CImg<%s>::%s(): Missing item in expression '%s'.",
-                                      pixel_type(),calling_function,
-                                      expr._data);
+                                      "CImg<%s>::%s: %s%s Missing %s, in expression '%s%s%s'.",
+                                      pixel_type(),_cimg_mp_calling_function,s_op,*s_op?":":"",
+                                      *s_op=='F'?"argument":"item",
+                                      (ss_op - 4)>expr._data?"...":"",
+                                      (ss_op - 4)>expr._data?ss_op - 4:expr._data,
+                                      ss_op + std::strlen(ss_op)<&expr.back()?"...":"");
         }
+
+        const char *const previous_s_op = s_op, *const previous_ss_op = ss_op;
+        const unsigned int depth1 = depth + 1;
+        unsigned int pos, p1, p2, p3, arg1, arg2, arg3, arg4, arg5, arg6;
         char
           *const se1 = se - 1, *const se2 = se - 2, *const se3 = se - 3,
           *const ss1 = ss + 1, *const ss2 = ss + 2, *const ss3 = ss + 3, *const ss4 = ss + 4,
-          *const ss5 = ss + 5, *const ss6 = ss + 6, *const ss7 = ss + 7, *const ss8 = ss + 8;
+          *const ss5 = ss + 5, *const ss6 = ss + 6, *const ss7 = ss + 7, *const ss8 = ss + 8,
+          *s, *ps, *ns, *s0, *s1, *s2, *s3, sep = 0, end = 0;
+        double val, val1, val2;
+        mp_func op;
+
+        // 'p_ref' is a 'unsigned int[7]' used to return a reference to an image or vector value
+        // linked to the returned memory slot (reference that cannot be determined at compile time).
+        // p_ref[0] can be { 0 = scalar (unlinked) | 1 = vector value | 2 = image value (offset) |
+        //                   3 = image value (coordinates) | 4 = image value as a vector (offsets) |
+        //                   5 = image value as a vector (coordinates) }.
+        // Depending on p_ref[0], the remaining p_ref[k] have the following meaning:
+        // When p_ref[0]==0, p_ref is actually unlinked.
+        // When p_ref[0]==1, p_ref = [ 1, vector_ind, offset ].
+        // When p_ref[0]==2, p_ref = [ 2, image_ind (or ~0U), is_relative, offset ].
+        // When p_ref[0]==3, p_ref = [ 3, image_ind (or ~0U), is_relative, x, y, z, c ].
+        // When p_ref[0]==4, p_ref = [ 4, image_ind (or ~0U), is_relative, offset ].
+        // When p_ref[0]==5, p_ref = [ 5, image_ind (or ~0U), is_relative, x, y, z ].
+        if (p_ref) { *p_ref = 0; p_ref[1] = p_ref[2] = p_ref[3] = p_ref[4] = p_ref[5] = p_ref[6] = ~0U; }
+
         const char saved_char = *se; *se = 0;
         const unsigned int clevel = level[ss - expr._data], clevel1 = clevel + 1;
-        if (*se1==';') return compile(ss,se1);
+        bool is_sth, is_relative;
+        CImg<uintT> ref;
+        CImgList<ulongT> _opcode;
+        CImg<charT> variable_name;
 
-        // Look for a single value, variable or variable assignment.
-        char end = 0, sep = 0; double val = 0;
-        int nb = cimg_sscanf(ss,"%lf%c%c",&val,&sep,&end);
-        CImgList<longT> _opcode;
+        // Look for a single value or a pre-defined variable.
+        int nb = cimg_sscanf(ss,"%lf%c%c",&val,&(sep=0),&(end=0));
 
 #if cimg_OS==2
         // Check for +/-NaN and +/-inf as Microsoft's sscanf() version is not able
         // to read those particular values.
         if (!nb && (*ss=='+' || *ss=='-' || *ss=='i' || *ss=='I' || *ss=='n' || *ss=='N')) {
-          bool is_positive = true;
-          const char *_ss = ss;
-          if (*_ss=='+') ++_ss; else if (*_ss=='-') { ++_ss; is_positive = false; }
-          if (!cimg::strcasecmp(_ss,"inf")) { val = cimg::type<double>::inf(); nb = 1; }
-          else if (!cimg::strcasecmp(_ss,"nan")) { val = cimg::type<double>::nan(); nb = 1; }
-          if (nb==1 && !is_positive) val = -val;
-        }
-#endif
-
-        if (nb==1) {
-          if (val==0 || val==1 || val==2 || val==3 || val==4 || val==5)
-            _cimg_mp_return((unsigned int)val);
-          if (mempos>=mem._width) mem.resize(-200,1,1,1,0);
-          const unsigned int pos = mempos++;
-          mem[pos] = val;
-          _cimg_mp_return(pos);
-        }
-        if (nb==2 && sep=='%') {
-          if (val==0 || val==100 || val==200 || val==300 || val==400 || val==500)
-            _cimg_mp_return((unsigned int)val/100);
-          if (mempos>=mem._width) mem.resize(-200,1,1,1,0);
-          const unsigned int pos = mempos++;
-          mem[pos] = val/100;
-          _cimg_mp_return(pos);
-        }
-        if (ss1==se) switch (*ss) { // One-char variable.
-          case 'w' : case 'h' : case 'd' : case 's' : case 'r' :
-          case 'x' : case 'y' : case 'z' : case 'c' : case 'e' : _cimg_mp_return(reserved_label[*ss]);
-          case 'u' : if (reserved_label['u']!=~0U) _cimg_mp_return(reserved_label['u']); _cimg_mp_opcode2(mp_u,0,1);
-          case 'g' : if (reserved_label['g']!=~0U) _cimg_mp_return(reserved_label['g']); _cimg_mp_opcode0(mp_g);
-          case 'i' : if (reserved_label['i']!=~0U) _cimg_mp_return(reserved_label['i']); _cimg_mp_opcode0(mp_i);
-          case '?' : _cimg_mp_opcode2(mp_u,0,1);
-          }
-        else if (ss2==se) { // Two-chars variable.
+          is_sth = true;
+          s = ss;
+          if (*s=='+') ++s; else if (*s=='-') { ++s; is_sth = false; }
+          if (!cimg::strcasecmp(s,"inf")) { val = cimg::type<double>::inf(); nb = 1; }
+          else if (!cimg::strcasecmp(s,"nan")) { val = cimg::type<double>::nan(); nb = 1; }
+          if (nb==1 && !is_sth) val = -val;
+        }
+#endif
+        if (nb==1) _cimg_mp_constant(val);
+        if (nb==2 && sep=='%') _cimg_mp_constant(val/100);
+
+        if (ss1==se) switch (*ss) { // One-char variable
+          case 't' : case 'w' : case 'h' : case 'd' : case 's' : case 'r' :
+          case 'x' : case 'y' : case 'z' : case 'c' : case 'e' :
+            _cimg_mp_return(reserved_label[*ss]);
+          case 'u' :
+            if (reserved_label['u']!=~0U) _cimg_mp_return(reserved_label['u']);
+            _cimg_mp_scalar2(mp_u,0,1);
+          case 'g' :
+            if (reserved_label['g']!=~0U) _cimg_mp_return(reserved_label['g']);
+            _cimg_mp_scalar0(mp_g);
+          case 'i' :
+            if (reserved_label['i']!=~0U) _cimg_mp_return(reserved_label['i']);
+            _cimg_mp_scalar0(mp_i);
+          case 'I' :
+            _cimg_mp_op("Variable 'I'");
+            if (reserved_label['I']!=~0U) _cimg_mp_return(reserved_label['I']);
+            _cimg_mp_check_vector0(imgin._spectrum);
+            need_input_copy = true;
+            pos = vector(imgin._spectrum);
+            CImg<ulongT>::vector((ulongT)mp_Joff,pos,0,0).move_to(code);
+            _cimg_mp_return(pos);
+          case 'R' :
+            if (reserved_label['R']!=~0U) _cimg_mp_return(reserved_label['R']);
+            need_input_copy = true;
+            _cimg_mp_scalar6(mp_ixyzc,_cimg_mp_x,_cimg_mp_y,_cimg_mp_z,0,0,0);
+          case 'G' :
+            if (reserved_label['G']!=~0U) _cimg_mp_return(reserved_label['G']);
+            need_input_copy = true;
+            _cimg_mp_scalar6(mp_ixyzc,_cimg_mp_x,_cimg_mp_y,_cimg_mp_z,1,0,0);
+          case 'B' :
+            if (reserved_label['B']!=~0U) _cimg_mp_return(reserved_label['B']);
+            need_input_copy = true;
+            _cimg_mp_scalar6(mp_ixyzc,_cimg_mp_x,_cimg_mp_y,_cimg_mp_z,2,0,0);
+          case 'A' :
+            if (reserved_label['A']!=~0U) _cimg_mp_return(reserved_label['A']);
+            need_input_copy = true;
+            _cimg_mp_scalar6(mp_ixyzc,_cimg_mp_x,_cimg_mp_y,_cimg_mp_z,3,0,0);
+          }
+        else if (ss2==se) { // Two-chars variable
+          arg1 = arg2 = ~0U;
           if (*ss=='w' && *ss1=='h') _cimg_mp_return(reserved_label[0]); // wh
           if (*ss=='p' && *ss1=='i') _cimg_mp_return(reserved_label[3]); // pi
-          if (*ss=='i') { // im
-            if (*ss1=='m') {
-              if (!input_stats) input.get_stats().move_to(input_stats);
-              if (reserved_label[4]!=~0U) _cimg_mp_return(reserved_label[4]); _cimg_mp_opcode0(mp_im);
-            }
-            if (*ss1=='M') { // iM
-              if (!input_stats) input.get_stats().move_to(input_stats);
-              if (reserved_label[5]!=~0U) _cimg_mp_return(reserved_label[5]); _cimg_mp_opcode0(mp_iM);
-            }
-            if (*ss1=='a') { // ia
-              if (!input_stats) input.get_stats().move_to(input_stats);
-              if (reserved_label[6]!=~0U) _cimg_mp_return(reserved_label[6]); _cimg_mp_opcode0(mp_ia);
-            }
-            if (*ss1=='v') { // iv
-              if (!input_stats) input.get_stats().move_to(input_stats);
-              if (reserved_label[7]!=~0U) _cimg_mp_return(reserved_label[7]); _cimg_mp_opcode0(mp_iv);
-            }
-            if (*ss1=='s') { // is
-              if (!input_stats) input.get_stats().move_to(input_stats);
-              if (reserved_label[8]!=~0U) _cimg_mp_return(reserved_label[8]); _cimg_mp_opcode0(mp_is);
-            }
-            if (*ss1=='p') { // ip
-              if (!input_stats) input.get_stats().move_to(input_stats);
-              if (reserved_label[9]!=~0U) _cimg_mp_return(reserved_label[9]); _cimg_mp_opcode0(mp_ip);
-            }
-            if (*ss1=='c') { // ic
-              if (!is_median_value && input) { median_value = input.median(); is_median_value = true; }
-              if (reserved_label[10]!=~0U) _cimg_mp_return(reserved_label[10]); _cimg_mp_opcode0(mp_ic);
-            }
-          }
-          if (*ss1=='m') {
-            if (*ss=='x') { // xm
-              if (!input_stats) input.get_stats().move_to(input_stats);
-              if (reserved_label[11]!=~0U) _cimg_mp_return(reserved_label[11]); _cimg_mp_opcode0(mp_xm);
-            }
-            if (*ss=='y') { // ym
-              if (!input_stats) input.get_stats().move_to(input_stats);
-              if (reserved_label[12]!=~0U) _cimg_mp_return(reserved_label[12]); _cimg_mp_opcode0(mp_ym);
-            }
-            if (*ss=='z') { // zm
-              if (!input_stats) input.get_stats().move_to(input_stats);
-              if (reserved_label[13]!=~0U) _cimg_mp_return(reserved_label[13]); _cimg_mp_opcode0(mp_zm);
-            }
-            if (*ss=='c') { // cm
-              if (!input_stats) input.get_stats().move_to(input_stats);
-              if (reserved_label[14]!=~0U) _cimg_mp_return(reserved_label[14]); _cimg_mp_opcode0(mp_cm);
+          if (*ss=='i') {
+            if (*ss1>='0' && *ss1<='9') { // i0...i9
+              pos = 19 + *ss1 - '0';
+              if (reserved_label[pos]!=~0U) _cimg_mp_return(reserved_label[pos]);
+              need_input_copy = true;
+              _cimg_mp_scalar6(mp_ixyzc,_cimg_mp_x,_cimg_mp_y,_cimg_mp_z,pos - 19,0,0);
+            }
+            switch (*ss1) {
+            case 'm' : arg1 = 4; arg2 = 0; break; // im
+            case 'M' : arg1 = 5; arg2 = 1; break; // iM
+            case 'a' : arg1 = 6; arg2 = 2; break; // ia
+            case 'v' : arg1 = 7; arg2 = 3; break; // iv
+            case 's' : arg1 = 8; arg2 = 12; break; // is
+            case 'p' : arg1 = 9; arg2 = 13; break; // is
+            case 'c' : // ic
+              if (reserved_label[10]!=~0U) _cimg_mp_return(reserved_label[10]);
+              if (mem_img_median==~0U) mem_img_median = imgin?constant(imgin.median()):0;
+              _cimg_mp_return(mem_img_median);
+              break;
             }
           }
-          if (*ss1=='M') {
-            if (*ss=='x') { // xM
-              if (!input_stats) input.get_stats().move_to(input_stats);
-              if (reserved_label[15]!=~0U) _cimg_mp_return(reserved_label[15]); _cimg_mp_opcode0(mp_xM);
-            }
-            if (*ss=='y') { // yM
-              if (!input_stats) input.get_stats().move_to(input_stats);
-              if (reserved_label[16]!=~0U) _cimg_mp_return(reserved_label[16]); _cimg_mp_opcode0(mp_yM);
+          else if (*ss1=='m') switch (*ss) {
+            case 'x' : arg1 = 11; arg2 = 4; break; // xm
+            case 'y' : arg1 = 12; arg2 = 5; break; // ym
+            case 'z' : arg1 = 13; arg2 = 6; break; // zm
+            case 'c' : arg1 = 14; arg2 = 7; break; // cm
             }
-            if (*ss=='z') { // zM
-              if (!input_stats) input.get_stats().move_to(input_stats);
-              if (reserved_label[17]!=~0U) _cimg_mp_return(reserved_label[17]); _cimg_mp_opcode0(mp_zM);
+          else if (*ss1=='M') switch (*ss) {
+            case 'x' : arg1 = 15; arg2 = 8; break; // xM
+            case 'y' : arg1 = 16; arg2 = 9; break; // yM
+            case 'z' : arg1 = 17; arg2 = 10; break; // zM
+            case 'c' : arg1 = 18; arg2 = 11; break; // cM
             }
-            if (*ss=='c') { // cM
-              if (!input_stats) input.get_stats().move_to(input_stats);
-              if (reserved_label[18]!=~0U) _cimg_mp_return(reserved_label[18]); _cimg_mp_opcode0(mp_cM);
+          if (arg1!=~0U) {
+            if (reserved_label[arg1]!=~0U) _cimg_mp_return(reserved_label[arg1]);
+            if (!img_stats) {
+              img_stats.assign(1,14,1,1,0).fill(imgin.get_stats(),false);
+              mem_img_stats.assign(1,14,1,1,~0U);
             }
+            if (mem_img_stats[arg2]==~0U) mem_img_stats[arg2] = constant(img_stats[arg2]);
+            _cimg_mp_return(mem_img_stats[arg2]);
           }
-        } else if (ss3==se) { // Three-chars variable.
+        } else if (ss3==se) { // Three-chars variable
           if (*ss=='w' && *ss1=='h' && *ss2=='d') _cimg_mp_return(reserved_label[1]); // whd
-        } else if (ss4==se) { // Four-chars variable.
+        } else if (ss4==se) { // Four-chars variable
           if (*ss=='w' && *ss1=='h' && *ss2=='d' && *ss3=='s') _cimg_mp_return(reserved_label[2]); // whds
         }
 
-        // Look for variable declarations.
-        for (char *s = se2; s>ss; --s)
-          if (*s==';' && level[s - expr._data]==clevel) { compile(ss,s); _cimg_mp_return(compile(s + 1,se)); }
-        for (char *s = ss1, *ps = ss, *ns = ss2; s<se1; ++s, ++ps, ++ns)
-          if (*s=='=' && *ns!='=' && *ps!='=' && *ps!='>' && *ps!='<' && *ps!='!' && level[s - expr._data]==clevel) {
-            CImg<charT> variable_name(ss,(unsigned int)(s - ss + 1));
-            variable_name.back() = 0;
+        pos = ~0U;
+        for (s0 = ss, s = ss1; s<se1; ++s)
+          if (*s==';' && level[s - expr._data]==clevel) { // Separator ';'
+            pos = compile(s0,s,depth,0);
+            s0 = s + 1;
+          }
+        if (pos!=~0U) _cimg_mp_return(compile(s0,se,depth,p_ref));
+
+        // Declare / assign variable, vector value or image value.
+        for (s = ss1, ps = ss, ns = ss2; s<se1; ++s, ++ps, ++ns)
+          if (*s=='=' && *ns!='=' && *ps!='=' && *ps!='>' && *ps!='<' && *ps!='!' &&
+              *ps!='+' && *ps!='-' && *ps!='*' && *ps!='/' && *ps!='%' &&
+              *ps!='>' && *ps!='<' && *ps!='&' && *ps!='|' && *ps!='^' &&
+              level[s - expr._data]==clevel) {
+            variable_name.assign(ss,(unsigned int)(s + 1 - ss)).back() = 0;
             cimg::strpare(variable_name);
-            const unsigned int l_variable_name = std::strlen(variable_name);
+            const unsigned int l_variable_name = (unsigned int)std::strlen(variable_name);
             char *const ve1 = ss + l_variable_name - 1;
+            _cimg_mp_op("Operator '='");
+
+            // Assign image value (direct).
+            if (l_variable_name>2 && (*ss=='i' || *ss=='j' || *ss=='I' || *ss=='J') && (*ss1=='(' || *ss1=='[') &&
+                (reserved_label[*ss]==~0U || *ss1=='(' || !_cimg_mp_is_vector(reserved_label[*ss]))) {
+              is_relative = *ss=='j' || *ss=='J';
+
+              if (*ss1=='[' && *ve1==']') { // i/j/I/J[_#ind,offset] = value
+                is_parallelizable = false;
+                if (*ss2=='#') { // Index specified
+                  s0 = ss3; while (s0<ve1 && (*s0!=',' || level[s0 - expr._data]!=clevel1)) ++s0;
+                  p1 = compile(ss3,s0++,depth1,0);
+                  _cimg_mp_check_list(true);
+                } else { p1 = ~0U; s0 = ss2; }
+                arg1 = compile(s0,ve1,depth1,0); // Offset
+                arg2 = compile(s + 1,se,depth1,0); // Value to assign
+                if (_cimg_mp_is_vector(arg2)) {
+                  p2 = ~0U; // 'p2' must the dimension of the vector-valued operand if any
+                  if (p1==~0U) p2 = imgin._spectrum;
+                  else if (_cimg_mp_is_constant(p1)) {
+                    p3 = (unsigned int)cimg::mod((int)mem[p1],listin.width());
+                    p2 = listin[p3]._spectrum;
+                  }
+                  _cimg_mp_check_vector0(p2);
+                } else p2 = 0;
+                _cimg_mp_check_type(arg2,2,*ss>='i'?1:3,p2);
+
+                if (p_ref) {
+                  *p_ref = _cimg_mp_is_vector(arg2)?4:2;
+                  p_ref[1] = p1;
+                  p_ref[2] = (unsigned int)is_relative;
+                  p_ref[3] = arg1;
+                  if (_cimg_mp_is_vector(arg2))
+                    set_variable_vector(arg2); // Prevent from being used in further optimization
+                  else if (_cimg_mp_is_temp(arg2)) memtype[arg2] = -1;
+                  if (p1!=~0U && _cimg_mp_is_temp(p1)) memtype[p1] = -1;
+                  if (_cimg_mp_is_temp(arg1)) memtype[arg1] = -1;
+                }
+                if (p1!=~0U) {
+                  if (!listout) _cimg_mp_return(arg2);
+                  if (*ss>='i')
+                    CImg<ulongT>::vector((ulongT)(is_relative?mp_list_set_joff:mp_list_set_ioff),
+                                        arg2,p1,arg1).move_to(code);
+                  else if (_cimg_mp_is_scalar(arg2))
+                    CImg<ulongT>::vector((ulongT)(is_relative?mp_list_set_Joff_s:mp_list_set_Ioff_s),
+                                        arg2,p1,arg1).move_to(code);
+                  else
+                    CImg<ulongT>::vector((ulongT)(is_relative?mp_list_set_Joff_v:mp_list_set_Ioff_v),
+                                        arg2,p1,arg1).move_to(code);
+                } else {
+                  if (!imgout) _cimg_mp_return(arg2);
+                  if (*ss>='i')
+                    CImg<ulongT>::vector((ulongT)(is_relative?mp_set_joff:mp_set_ioff),
+                                        arg2,arg1).move_to(code);
+                  if (_cimg_mp_is_scalar(arg2))
+                    CImg<ulongT>::vector((ulongT)(is_relative?mp_set_Joff_s:mp_set_Ioff_s),
+                                        arg2,arg1).move_to(code);
+                  else
+                    CImg<ulongT>::vector((ulongT)(is_relative?mp_set_Joff_v:mp_set_Ioff_v),
+                                        arg2,arg1).move_to(code);
+                }
+                _cimg_mp_return(arg2);
+              }
 
-            if (l_variable_name>2 && (*ss=='i' || *ss=='j')) {
-              const bool is_relative = *ss=='j';
-              if (*ss1=='(' && *ve1==')') { // i/j(_x,_y,_z,_c)=value.
-                unsigned int
-                  indx = is_relative?0U:16U, indy = is_relative?0U:17U,
-                  indz = is_relative?0U:18U, indc = is_relative?0U:19U;
-                if (ss2!=ve1) {
-                  char *s1 = ss2; while (s1<ve1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
-                  indx = compile(ss2,s1);
-                  if (s1<ve1) {
-                    char *s2 = ++s1; while (s2<ve1 && (*s2!=',' || level[s2 - expr._data]!=clevel1)) ++s2;
-                    indy = compile(s1,s2);
-                    if (s2<ve1) {
-                      char *s3 = ++s2; while (s3<ve1 && (*s3!=',' || level[s3 - expr._data]!=clevel1)) ++s3;
-                      indz = compile(s2,s3);
-                      if (s3<ve1) indc = compile(++s3,ve1);
+              if (*ss1=='(' && *ve1==')') { // i/j/I/J(_#ind,_x,_y,_z,_c) = value
+                is_parallelizable = false;
+                if (*ss2=='#') { // Index specified
+                  s0 = ss3; while (s0<ve1 && (*s0!=',' || level[s0 - expr._data]!=clevel1)) ++s0;
+                  p1 = compile(ss3,s0++,depth1,0);
+                  _cimg_mp_check_list(true);
+                } else { p1 = ~0U; s0 = ss2; }
+                arg1 = is_relative?0U:(unsigned int)_cimg_mp_x;
+                arg2 = is_relative?0U:(unsigned int)_cimg_mp_y;
+                arg3 = is_relative?0U:(unsigned int)_cimg_mp_z;
+                arg4 = is_relative?0U:(unsigned int)_cimg_mp_c;
+                arg5 = compile(s + 1,se,depth1,0); // Value to assign
+                if (s0<ve1) { // X or [ X,_Y,_Z,_C ]
+                  s1 = s0; while (s1<ve1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
+                  arg1 = compile(s0,s1,depth1,0);
+                  if (_cimg_mp_is_vector(arg1)) { // Coordinates specified as a vector
+                    p2 = _cimg_mp_vector_size(arg1); // Vector size
+                    ++arg1;
+                    if (p2>1) {
+                      arg2 = arg1 + 1;
+                      if (p2>2) {
+                        arg3 = arg2 + 1;
+                        if (p2>3) arg4 = arg3 + 1;
+                      }
+                    }
+                  } else if (s1<ve1) { // Y
+                    s2 = ++s1; while (s2<ve1 && (*s2!=',' || level[s2 - expr._data]!=clevel1)) ++s2;
+                    arg2 = compile(s1,s2,depth1,0);
+                    if (s2<ve1) { // Z
+                      s3 = ++s2; while (s3<ve1 && (*s3!=',' || level[s3 - expr._data]!=clevel1)) ++s3;
+                      arg3 = compile(s2,s3,depth1,0);
+                      if (s3<ve1) arg4 = compile(++s3,ve1,depth1,0); // C
                     }
                   }
                 }
-                const unsigned int value = opcode1(mp_replace,compile(s + 1,se));
-                _cimg_mp_opcode5(is_relative?mp_set_jxyzc:mp_set_ixyzc,indx,indy,indz,indc,value);
-              } else if (*ss1=='[' && *ve1==']') { // i/j[off]=value.
-                unsigned int off = 0;
-                if (ss2!=ve1) off = compile(ss2,ve1);
-                const unsigned int value = opcode1(mp_replace,compile(s + 1,se));
-                _cimg_mp_opcode2(is_relative?mp_set_joff:mp_set_ioff,off,value);
-              }
-            }
-
-            bool is_valid_name = true;
-            if (*variable_name>='0' && *variable_name<='9') is_valid_name = false;
-            else for (const char *ns = variable_name._data + 1; *ns; ++ns)
-                   if ((*ns<'a' || *ns>'z') && (*ns<'A' || *ns>'Z') && (*ns<'0' || *ns>'9') && *ns!='_') {
-                     is_valid_name = false; break;
-                   }
-            if (!is_valid_name) {
-              *se = saved_char;
-              throw CImgArgumentException("[_cimg_math_parser] "
-                                          "CImg<%s>::%s(): Invalid variable name '%s' in expression "
-                                          "'%s%s%s'.",
-                                          pixel_type(),calling_function,
-                                          variable_name._data,
-                                          (ss - 8)>expr._data?"...":"",
-                                          (ss - 8)>expr._data?ss - 8:expr._data,
-                                          se<&expr.back()?"...":"");
+
+                if (_cimg_mp_is_vector(arg5)) {
+                  p2 = ~0U; // 'p2' must the dimension of the vector-valued operand if any
+                  if (p1==~0U) p2 = imgin._spectrum;
+                  else if (_cimg_mp_is_constant(p1)) {
+                    p3 = (unsigned int)cimg::mod((int)mem[p1],listin.width());
+                    p2 = listin[p3]._spectrum;
+                  }
+                  _cimg_mp_check_vector0(p2);
+                } else p2 = 0;
+                _cimg_mp_check_type(arg5,2,*ss>='i'?1:3,p2);
+
+                if (p_ref) {
+                  *p_ref = _cimg_mp_is_vector(arg5)?5:3;
+                  p_ref[1] = p1;
+                  p_ref[2] = (unsigned int)is_relative;
+                  p_ref[3] = arg1;
+                  p_ref[4] = arg2;
+                  p_ref[5] = arg3;
+                  p_ref[6] = arg4;
+                  if (_cimg_mp_is_vector(arg5))
+                    set_variable_vector(arg5); // Prevent from being used in further optimization
+                  else if (_cimg_mp_is_temp(arg5)) memtype[arg5] = -1;
+                  if (p1!=~0U && _cimg_mp_is_temp(p1)) memtype[p1] = -1;
+                  if (_cimg_mp_is_temp(arg1)) memtype[arg1] = -1;
+                  if (_cimg_mp_is_temp(arg2)) memtype[arg2] = -1;
+                  if (_cimg_mp_is_temp(arg3)) memtype[arg3] = -1;
+                  if (_cimg_mp_is_temp(arg4)) memtype[arg4] = -1;
+                }
+                if (p1!=~0U) {
+                  if (!listout) _cimg_mp_return(arg5);
+                  if (*ss>='i')
+                    CImg<ulongT>::vector((ulongT)(is_relative?mp_list_set_jxyzc:mp_list_set_ixyzc),
+                                        arg5,p1,arg1,arg2,arg3,arg4).move_to(code);
+                  else if (_cimg_mp_is_scalar(arg5))
+                    CImg<ulongT>::vector((ulongT)(is_relative?mp_list_set_Jxyz_s:mp_list_set_Ixyz_s),
+                                        arg5,p1,arg1,arg2,arg3).move_to(code);
+                  else
+                    CImg<ulongT>::vector((ulongT)(is_relative?mp_list_set_Jxyz_v:mp_list_set_Ixyz_v),
+                                        arg5,p1,arg1,arg2,arg3).move_to(code);
+                } else {
+                  if (!imgout) _cimg_mp_return(arg5);
+                  if (*ss>='i')
+                    CImg<ulongT>::vector((ulongT)(is_relative?mp_set_jxyzc:mp_set_ixyzc),
+                                        arg5,arg1,arg2,arg3,arg4).move_to(code);
+                  else if (_cimg_mp_is_scalar(arg5))
+                    CImg<ulongT>::vector((ulongT)(is_relative?mp_set_Jxyz_s:mp_set_Ixyz_s),
+                                        arg5,arg1,arg2,arg3).move_to(code);
+                  else
+                    CImg<ulongT>::vector((ulongT)(is_relative?mp_set_Jxyz_v:mp_set_Ixyz_v),
+                                        arg5,arg1,arg2,arg3).move_to(code);
+                }
+                _cimg_mp_return(arg5);
+              }
             }
 
-            // Ensure variable gets a new memory slot (makes it updatable).
-            const unsigned int pos = opcode1(mp_replace,compile(s + 1,se));
-
-            // Check for particular case of a reserved variable.
-            if (variable_name[1] && !variable_name[2]) { // Two-chars variable.
-              const char c1 = variable_name[0], c2 = variable_name[1];
-              if (c1=='w' && c2=='h') variable_name.fill((char)0,(char)0); // wh
-              else if (c1=='p' && c2=='i') variable_name.fill(3,0); // pi
-              else if (c1=='i') {
-                if (c2=='m') variable_name.fill(4,0); // im
-                else if (c2=='M') variable_name.fill(5,0); // iM
-                else if (c2=='a') variable_name.fill(6,0); // ia
-                else if (c2=='v') variable_name.fill(7,0); // iv
-                else if (c2=='s') variable_name.fill(8,0); // is
-                else if (c2=='p') variable_name.fill(9,0); // ip
-                else if (c2=='c') variable_name.fill(10,0); // ic
-              } else if (c2=='m') {
-                if (c1=='x') variable_name.fill(11,0); // xm
-                else if (c1=='y') variable_name.fill(12,0); // ym
-                else if (c1=='z') variable_name.fill(13,0); // zm
-                else if (c1=='c') variable_name.fill(14,0); // cm
-              } else if (c2=='M') {
-                if (c1=='x') variable_name.fill(15,0); // xM
-                else if (c1=='y') variable_name.fill(16,0); // yM
-                else if (c1=='z') variable_name.fill(17,0); // zM
-                else if (c1=='c') variable_name.fill(18,0); // cM
-              }
-            } else if (variable_name[1] && variable_name[2] && !variable_name[3]) { // Three-chars variable.
-              const char c1 = variable_name[0], c2 = variable_name[1], c3 = variable_name[2];
-              if (c1=='w' && c2=='h' && c3=='d') variable_name.fill(1,0,0); // whd
-            } else if (variable_name[1] && variable_name[2] && variable_name[3] &&
-                       !variable_name[4]) { // Four-chars variable.
-              const char c1 = variable_name[0], c2 = variable_name[1], c3 = variable_name[2],
-                c4 = variable_name[3];
-              if (c1=='w' && c2=='h' && c3=='d' && c4=='s') variable_name.fill(2,0,0,0); // whds
+            // Assign vector value (direct).
+            if (l_variable_name>3 && *ve1==']' && *ss!='[') {
+              s0 = ve1; while (s0>ss && *s0!='[') --s0;
+              is_sth = true; // is_valid_variable_name?
+              if (*ss>='0' && *ss<='9') is_sth = false;
+              else for (ns = ss; ns<s0; ++ns)
+                     if (!is_varchar(*ns)) { is_sth = false; break; }
+              if (is_sth && s0>ss) {
+                variable_name[s0 - ss] = 0; // Remove brackets in variable name
+                arg1 = ~0U; // Vector slot
+                arg2 = compile(++s0,ve1,depth1,0); // Index
+                arg3 = compile(s + 1,se,depth1,0); // Value to assign
+                _cimg_mp_check_type(arg3,2,1,0);
+
+                if (variable_name[1]) { // Multi-char variable
+                  cimglist_for(variable_def,i) if (!std::strcmp(variable_name,variable_def[i])) {
+                    arg1 = variable_pos[i]; break;
+                  }
+                } else arg1 = reserved_label[*variable_name]; // Single-char variable
+                if (arg1==~0U) compile(ss,s0 - 1,depth1,0); // Variable does not exist -> error
+                else { // Variable already exists
+                  if (_cimg_mp_is_scalar(arg1)) compile(ss,s,depth1,0); // Variable is not a vector -> error
+                  if (_cimg_mp_is_constant(arg2)) { // Constant index -> return corresponding variable slot directly
+                    nb = (int)mem[arg2];
+                    if (nb>=0 && nb<(int)_cimg_mp_vector_size(arg1)) {
+                      arg1+=nb + 1;
+                      CImg<ulongT>::vector((ulongT)mp_copy,arg1,arg3).move_to(code);
+                      _cimg_mp_return(arg1);
+                    }
+                    compile(ss,s,depth1,0); // Out-of-bounds reference -> error
+                  }
+
+                  // Case of non-constant index -> return assigned value + linked reference
+                  if (p_ref) {
+                    *p_ref = 1;
+                    p_ref[1] = arg1;
+                    p_ref[2] = arg2;
+                    if (_cimg_mp_is_temp(arg3)) memtype[arg3] = -1; // Prevent from being used in further optimization
+                    if (_cimg_mp_is_temp(arg2)) memtype[arg2] = -1;
+                  }
+                  CImg<ulongT>::vector((ulongT)mp_vector_set_off,arg3,arg1,_cimg_mp_vector_size(arg1),arg2,arg3).
+                    move_to(code);
+                  _cimg_mp_return(arg3);
+                }
+              }
             }
 
-            // Set new variable value.
-            if (!variable_name[1]) {
-              const unsigned int var_pos = reserved_label[*variable_name];
-              if (var_pos==~0U) reserved_label[*variable_name] = pos;
-              else {
-                CImg<longT>::vector(_cimg_mp_enfunc(mp_replace),var_pos,pos).move_to(code);
-                _cimg_mp_return(var_pos);
+            // Assign user-defined macro.
+            if (l_variable_name>2 && *ve1==')' && *ss!='(') {
+              s0 = ve1; while (s0>ss && *s0!='(') --s0;
+              is_sth = std::strncmp(variable_name,"debug(",6) &&
+                std::strncmp(variable_name,"print(",6); // is_valid_function_name?
+              if (*ss>='0' && *ss<='9') is_sth = false;
+              else for (ns = ss; ns<s0; ++ns)
+                     if (!is_varchar(*ns)) { is_sth = false; break; }
+
+              if (is_sth && s0>ss) { // Looks like a valid function declaration
+                s0 = variable_name._data + (s0 - ss);
+                *s0 = 0;
+                s1 = variable_name._data + l_variable_name - 1; // Pointer to closing parenthesis
+                CImg<charT>(variable_name._data,(unsigned int)(s0 - variable_name._data + 1)).move_to(function_def,0);
+                ++s; while (*s && *s<=' ') ++s;
+                CImg<charT>(s,(unsigned int)(se - s + 1)).move_to(function_body,0);
+
+                p1 = 1; // Indice of current parsed argument
+                for (s = s0 + 1; s<=s1; ++p1, s = ns + 1) { // Parse function arguments
+                  if (p1>24) {
+                    *se = saved_char; cimg::strellipsize(variable_name,64); cimg::strellipsize(expr,64);
+                    throw CImgArgumentException("[_cimg_math_parser] "
+                                                "CImg<%s>::%s: %s: Too much specified arguments (>24) when defining "
+                                                "function '%s()', in expression '%s%s%s'.",
+                                                pixel_type(),_cimg_mp_calling_function,s_op,
+                                                variable_name._data,
+                                                (ss - 4)>expr._data?"...":"",
+                                                (ss - 4)>expr._data?ss - 4:expr._data,
+                                                se<&expr.back()?"...":"");
+                  }
+                  while (*s && *s<=' ') ++s;
+                  if (*s==')' && p1==1) break; // Function has no arguments
+
+                  s2 = s; // Start of the argument name
+                  is_sth = true; // is_valid_argument_name?
+                  if (*s>='0' && *s<='9') is_sth = false;
+                  else for (ns = s; ns<s1 && *ns!=',' && *ns>' '; ++ns)
+                         if (!is_varchar(*ns)) { is_sth = false; break; }
+                  s3 = ns; // End of the argument name
+                  while (*ns && *ns<=' ') ++ns;
+                  if (!is_sth || s2==s3 || (*ns!=',' && ns!=s1)) {
+                    *se = saved_char; cimg::strellipsize(variable_name,64); cimg::strellipsize(expr,64);
+                    throw CImgArgumentException("[_cimg_math_parser] "
+                                                "CImg<%s>::%s: %s: %s name specified for argument %u when defining "
+                                                "function '%s()', in expression '%s%s%s'.",
+                                                pixel_type(),_cimg_mp_calling_function,s_op,
+                                                is_sth?"Empty":"Invalid",p1,
+                                                variable_name._data,
+                                                (ss - 4)>expr._data?"...":"",
+                                                (ss - 4)>expr._data?ss - 4:expr._data,
+                                                se<&expr.back()?"...":"");
+                  }
+                  if (ns==s1 || *ns==',') { // New argument found
+                    *s3 = 0;
+                    p2 = (unsigned int)(s3 - s2); // Argument length
+                    p3 = function_body[0]._width - p2 + 1; // Related to copy length
+                    for (ps = std::strstr(function_body[0],s2); ps; ps = std::strstr(ps,s2)) { // Replace by arg number
+                      if (!((ps>function_body[0]._data && is_varchar(*(ps - 1))) ||
+                            (ps + p2<function_body[0].end() && is_varchar(*(ps + p2))))) {
+                        *(ps++) = (char)p1;
+                        if (p2>1) {
+                          std::memmove(ps,ps + p2 - 1,function_body[0]._data + p3 - ps);
+                          function_body[0]._width-=p2 - 1;
+                        }
+                      } else ++ps;
+                    }
+                  }
+                }
+                // Store number of arguments
+                function_def[0].resize(function_def[0]._width + 1,1,1,1,0).back() = (char)(p1 - 1);
+                _cimg_mp_return(28);
               }
             }
-            else {
-              int label_pos = -1;
-              cimglist_for(labelM,i) // Check for existing variable with same name.
-                if (!std::strcmp(variable_name,labelM[i])) { label_pos = i; break; }
-              if (label_pos<0) { // If new variable.
-                if (labelM._width>=labelMpos._width) labelMpos.resize(-200,1,1,1,0);
-                label_pos = labelM.width();
-                variable_name.move_to(labelM);
-                labelMpos[label_pos] = pos;
-              } else { // Existing variable.
-                const unsigned int var_pos = labelMpos[label_pos];
-                CImg<longT>::vector(_cimg_mp_enfunc(mp_replace),var_pos,pos).move_to(code);
-                _cimg_mp_return(var_pos);
+
+            // Check if the variable name could be valid. If not, this is probably an lvalue assignment.
+            is_sth = true; // is_valid_variable_name?
+            if (*variable_name>='0' && *variable_name<='9') is_sth = false;
+            else for (ns = variable_name._data; *ns; ++ns)
+                   if (!is_varchar(*ns)) { is_sth = false; break; }
+
+            // Assign variable (direct).
+            if (is_sth) {
+              if (variable_name[1] && !variable_name[2]) { // Two-chars variable
+                c1 = variable_name[0];
+                c2 = variable_name[1];
+                if (c1=='w' && c2=='h') variable_name.fill((char)0,(char)0); // wh
+                else if (c1=='p' && c2=='i') variable_name.fill(3,0); // pi
+                else if (c1=='i') {
+                  if (c2>='0' && c2<='9') variable_name.fill(19 + c2 - '0',0); // i0...i9
+                  else if (c2=='m') variable_name.fill(4,0); // im
+                  else if (c2=='M') variable_name.fill(5,0); // iM
+                  else if (c2=='a') variable_name.fill(6,0); // ia
+                  else if (c2=='v') variable_name.fill(7,0); // iv
+                  else if (c2=='s') variable_name.fill(8,0); // is
+                  else if (c2=='p') variable_name.fill(9,0); // ip
+                  else if (c2=='c') variable_name.fill(10,0); // ic
+                } else if (c2=='m') {
+                  if (c1=='x') variable_name.fill(11,0); // xm
+                  else if (c1=='y') variable_name.fill(12,0); // ym
+                  else if (c1=='z') variable_name.fill(13,0); // zm
+                  else if (c1=='c') variable_name.fill(14,0); // cm
+                } else if (c2=='M') {
+                  if (c1=='x') variable_name.fill(15,0); // xM
+                  else if (c1=='y') variable_name.fill(16,0); // yM
+                  else if (c1=='z') variable_name.fill(17,0); // zM
+                  else if (c1=='c') variable_name.fill(18,0); // cM
+                }
+              } else if (variable_name[1] && variable_name[2] && !variable_name[3]) { // Three-chars variable
+                c1 = variable_name[0];
+                c2 = variable_name[1];
+                c3 = variable_name[2];
+                if (c1=='w' && c2=='h' && c3=='d') variable_name.fill(1,0); // whd
+              } else if (variable_name[1] && variable_name[2] && variable_name[3] &&
+                         !variable_name[4]) { // Four-chars variable
+                c1 = variable_name[0];
+                c2 = variable_name[1];
+                c3 = variable_name[2];
+                c4 = variable_name[3];
+                if (c1=='w' && c2=='h' && c3=='d' && c4=='s') variable_name.fill(2,0); // whds
+              } else if (!std::strcmp(variable_name,"interpolation")) variable_name.fill(29,0);
+              else if (!std::strcmp(variable_name,"boundary")) variable_name.fill(30,0);
+
+              arg1 = ~0U;
+              arg2 = compile(s + 1,se,depth1,0);
+              if (!variable_name[1]) // One-char variable, or variable in reserved_labels
+                arg1 = reserved_label[*variable_name];
+              else // Multi-char variable name : check for existing variable with same name
+                cimglist_for(variable_def,i)
+                  if (!std::strcmp(variable_name,variable_def[i])) { arg1 = variable_pos[i]; break; }
+
+              if (arg1==~0U || arg1<=_cimg_mp_c) { // Create new variable
+                if (_cimg_mp_is_vector(arg2)) { // Vector variable
+                  arg1 = vector_copy(arg2);
+                  set_variable_vector(arg1);
+                } else { // Scalar variable
+                  arg1 = scalar1(mp_copy,arg2);
+                  memtype[arg1] = -1;
+                }
+
+                if (!variable_name[1]) reserved_label[*variable_name] = arg1;
+                else {
+                  if (variable_def._width>=variable_pos._width) variable_pos.resize(-200,1,1,1,0);
+                  variable_pos[variable_def._width] = arg1;
+                  variable_name.move_to(variable_def);
+                }
+
+              } else { // Variable already exists -> assign a new value
+                _cimg_mp_check_type(arg2,2,_cimg_mp_is_vector(arg1)?3:1,_cimg_mp_vector_size(arg1));
+                if (_cimg_mp_is_vector(arg1)) { // Vector
+                  if (_cimg_mp_is_vector(arg2)) // From vector
+                    CImg<ulongT>::vector((ulongT)mp_vector_copy,arg1,arg2,(ulongT)_cimg_mp_vector_size(arg1)).
+                      move_to(code);
+                  else // From scalar
+                    CImg<ulongT>::vector((ulongT)mp_vector_init,arg1,(ulongT)_cimg_mp_vector_size(arg1),arg2).
+                      move_to(code);
+                } else // Scalar
+                  CImg<ulongT>::vector((ulongT)mp_copy,arg1,arg2).move_to(code);
+              }
+              _cimg_mp_return(arg1);
+            }
+
+            // Assign lvalue (variable name was not valid).
+            is_sth = (bool)std::strchr(variable_name,'?'); // Contains_ternary_operator?
+            if (is_sth) break; // Do nothing and make ternary operator prioritary over assignment
+
+            if (l_variable_name>2 && (std::strchr(variable_name,'(') || std::strchr(variable_name,'['))) {
+              ref.assign(7);
+              arg1 = compile(ss,s,depth1,ref); // Lvalue slot
+              arg2 = compile(s + 1,se,depth1,0); // Value to assign
+
+              if (*ref==1) { // Vector value (scalar): V[k] = scalar
+                _cimg_mp_check_type(arg2,2,1,0);
+                arg3 = ref[1]; // Vector slot
+                arg4 = ref[2]; // Index
+                if (p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int));
+                CImg<ulongT>::vector((ulongT)mp_vector_set_off,arg2,arg3,(ulongT)_cimg_mp_vector_size(arg3),arg4,arg2).
+                  move_to(code);
+                _cimg_mp_return(arg2);
+              }
+
+              if (*ref==2) { // Image value (scalar): i/j[_#ind,off] = scalar
+                _cimg_mp_check_type(arg2,2,1,0);
+                is_parallelizable = false;
+                p1 = ref[1]; // Index
+                is_relative = (bool)ref[2];
+                arg3 = ref[3]; // Offset
+                if (p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int));
+                if (p1!=~0U) {
+                  if (!listout) _cimg_mp_return(arg2);
+                  CImg<ulongT>::vector((ulongT)(is_relative?mp_list_set_joff:mp_list_set_ioff),
+                                      arg2,p1,arg3).move_to(code);
+                } else {
+                  if (!imgout) _cimg_mp_return(arg2);
+                  CImg<ulongT>::vector((ulongT)(is_relative?mp_set_joff:mp_set_ioff),
+                                      arg2,arg3).move_to(code);
+                }
+                _cimg_mp_return(arg2);
+              }
+
+              if (*ref==3) { // Image value (scalar): i/j(_#ind,_x,_y,_z,_c) = scalar
+                _cimg_mp_check_type(arg2,2,1,0);
+                is_parallelizable = false;
+                p1 = ref[1]; // Index
+                is_relative = (bool)ref[2];
+                arg3 = ref[3]; // X
+                arg4 = ref[4]; // Y
+                arg5 = ref[5]; // Z
+                arg6 = ref[6]; // C
+                if (p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int));
+                if (p1!=~0U) {
+                  if (!listout) _cimg_mp_return(arg2);
+                  CImg<ulongT>::vector((ulongT)(is_relative?mp_list_set_jxyzc:mp_list_set_ixyzc),
+                                      arg2,p1,arg3,arg4,arg5,arg6).move_to(code);
+                } else {
+                  if (!imgout) _cimg_mp_return(arg2);
+                  CImg<ulongT>::vector((ulongT)(is_relative?mp_set_jxyzc:mp_set_ixyzc),
+                                      arg2,arg3,arg4,arg5,arg6).move_to(code);
+                }
+                _cimg_mp_return(arg2);
+              }
+
+              if (*ref==4) { // Image value (vector): I/J[_#ind,off] = value
+                _cimg_mp_check_type(arg2,2,3,_cimg_mp_vector_size(arg1));
+                is_parallelizable = false;
+                p1 = ref[1]; // Index
+                is_relative = (bool)ref[2];
+                arg3 = ref[3]; // Offset
+                if (p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int));
+                if (p1!=~0U) {
+                  if (!listout) _cimg_mp_return(arg2);
+                  if (_cimg_mp_is_scalar(arg2))
+                    CImg<ulongT>::vector((ulongT)(is_relative?mp_list_set_Joff_s:mp_list_set_Ioff_s),
+                                        arg2,p1,arg3).move_to(code);
+                  else
+                    CImg<ulongT>::vector((ulongT)(is_relative?mp_list_set_Joff_v:mp_list_set_Ioff_v),
+                                        arg2,p1,arg3).move_to(code);
+                } else {
+                  if (!imgout) _cimg_mp_return(arg2);
+                  if (_cimg_mp_is_scalar(arg2))
+                    CImg<ulongT>::vector((ulongT)(is_relative?mp_set_Joff_s:mp_set_Ioff_s),
+                                        arg2,arg3).move_to(code);
+                  else
+                    CImg<ulongT>::vector((ulongT)(is_relative?mp_set_Joff_v:mp_set_Ioff_v),
+                                        arg2,arg3).move_to(code);
+                }
+                _cimg_mp_return(arg2);
+              }
+
+              if (*ref==5) { // Image value (vector): I/J(_#ind,_x,_y,_z,_c) = value
+                _cimg_mp_check_type(arg2,2,3,_cimg_mp_vector_size(arg1));
+                is_parallelizable = false;
+                p1 = ref[1]; // Index
+                is_relative = (bool)ref[2];
+                arg3 = ref[3]; // X
+                arg4 = ref[4]; // Y
+                arg5 = ref[5]; // Z
+                if (p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int));
+                if (p1!=~0U) {
+                  if (!listout) _cimg_mp_return(arg2);
+                  if (_cimg_mp_is_scalar(arg2))
+                    CImg<ulongT>::vector((ulongT)(is_relative?mp_list_set_Jxyz_s:mp_list_set_Ixyz_s),
+                                        arg2,p1,arg3,arg4,arg5).move_to(code);
+                  else
+                    CImg<ulongT>::vector((ulongT)(is_relative?mp_list_set_Jxyz_v:mp_list_set_Ixyz_v),
+                                        arg2,p1,arg3,arg4,arg5).move_to(code);
+                } else {
+                  if (!imgout) _cimg_mp_return(arg2);
+                  if (_cimg_mp_is_scalar(arg2))
+                    CImg<ulongT>::vector((ulongT)(is_relative?mp_set_Jxyz_s:mp_set_Ixyz_s),
+                                        arg2,arg3,arg4,arg5).move_to(code);
+                  else
+                    CImg<ulongT>::vector((ulongT)(is_relative?mp_set_Jxyz_v:mp_set_Ixyz_v),
+                                        arg2,arg3,arg4,arg5).move_to(code);
+                }
+                _cimg_mp_return(arg2);
+              }
+
+              if (_cimg_mp_is_vector(arg1)) { // Vector variable: V = value
+                _cimg_mp_check_type(arg2,2,1,0);
+                if (_cimg_mp_is_vector(arg2)) // From vector
+                  CImg<ulongT>::vector((ulongT)mp_vector_copy,arg1,arg2,(ulongT)_cimg_mp_vector_size(arg1)).
+                    move_to(code);
+                else // From scalar
+                  CImg<ulongT>::vector((ulongT)mp_vector_init,arg1,(ulongT)_cimg_mp_vector_size(arg1),arg2).
+                    move_to(code);
+                _cimg_mp_return(arg1);
+              }
+
+              if (_cimg_mp_is_variable(arg1)) { // Scalar variable: s = scalar
+                _cimg_mp_check_type(arg2,2,1,0);
+                CImg<ulongT>::vector((ulongT)mp_copy,arg1,arg2).move_to(code);
+                _cimg_mp_return(arg1);
+
               }
             }
-            _cimg_mp_return(pos);
-          }
 
-        // Look for unary/binary operators. The operator precedences is defined as in C++.
-        for (char *s = se3, *ns = se2; s>ss; --s, --ns) if (*s=='|' && *ns=='|' && level[s - expr._data]==clevel) {
-            const unsigned int mem_left = compile(ss,s), p_right = code._width, mem_right = compile(s + 2,se);
-            if (mempos>=mem._width) mem.resize(-200,1,1,1,0);
-            const unsigned int pos = mempos++;
-            CImg<longT>::vector(_cimg_mp_enfunc(mp_logical_or),pos,mem_left,mem_right,code._width - p_right).
-              move_to(code,p_right);
-            _cimg_mp_return(pos);
-          }
-        for (char *s = se3, *ns = se2; s>ss; --s, --ns) if (*s=='&' && *ns=='&' && level[s - expr._data]==clevel) {
-            const unsigned int mem_left = compile(ss,s), p_right = code._width, mem_right = compile(s + 2,se);
-            if (mempos>=mem._width) mem.resize(-200,1,1,1,0);
-            const unsigned int pos = mempos++;
-            CImg<longT>::vector(_cimg_mp_enfunc(mp_logical_and),pos,mem_left,mem_right,code._width - p_right).
-              move_to(code,p_right);
+            // No assignment expressions match -> error
+            *se = saved_char; cimg::strellipsize(variable_name,64); cimg::strellipsize(expr,64);
+            throw CImgArgumentException("[_cimg_math_parser] "
+                                        "CImg<%s>::%s: %s: Invalid left-hand operand '%s', "
+                                        "in expression '%s%s%s'.",
+                                        pixel_type(),_cimg_mp_calling_function,s_op,
+                                        variable_name._data,
+                                        (ss - 4)>expr._data?"...":"",
+                                        (ss - 4)>expr._data?ss - 4:expr._data,
+                                        se<&expr.back()?"...":"");
+          }
+
+        // Apply unary/binary/ternary operators. The operator precedences should be roughly the same as in C++.
+        for (s = se2, ps = se3, ns = ps - 1; s>ss1; --s, --ps, --ns) // Here, ns = ps - 1
+          if (*s=='=' && (*ps=='*' || *ps=='/' || *ps=='^') && *ns==*ps &&
+              level[s - expr._data]==clevel) { // Self-operators for complex numbers only (**=,//=,^^=)
+            _cimg_mp_op(*ps=='*'?"Operator '**='":*ps=='/'?"Operator '//='":"Operator '^^='");
+
+            ref.assign(7);
+            arg1 = compile(ss,ns,depth1,ref); // Vector slot
+            arg2 = compile(s + 1,se,depth1,0); // Right operand
+            if (*ps!='*') {
+              _cimg_mp_check_type(arg1,2,2,2);
+              _cimg_mp_check_type(arg2,2,2,2);
+            }
+            if (_cimg_mp_is_vector(arg2)) { // Complex **= complex or Matrix **= matrix
+              if (*ps=='*') {
+                if (_cimg_mp_vector_size(arg1)==2 && _cimg_mp_vector_size(arg2)==2)
+                  CImg<ulongT>::vector((ulongT)mp_complex_mul,arg1,arg1,arg2).move_to(code);
+                else {
+                  _cimg_mp_check_matrix_square(arg2,2);
+                  p3 = _cimg_mp_vector_size(arg1);
+                  p2 = (unsigned int)std::sqrt((float)_cimg_mp_vector_size(arg2));
+                  p1 = p3/p2;
+                  if (p1*p2!=p3) {
+                    *se = saved_char; cimg::strellipsize(expr,64);
+                    throw CImgArgumentException("[_cimg_math_parser] "
+                                                "CImg<%s>::%s: %s: Types of left-hand and right-hand operands "
+                                                "('%s' and '%s') do not match, in expression '%s%s%s'.",
+                                                pixel_type(),_cimg_mp_calling_function,s_op,
+                                                s_type(arg1)._data,s_type(arg2)._data,
+                                                (ss - 4)>expr._data?"...":"",
+                                                (ss - 4)>expr._data?ss - 4:expr._data,
+                                                se<&expr.back()?"...":"");
+                  }
+                  CImg<ulongT>::vector((ulongT)mp_matrix_mul,arg1,arg1,arg2,p1,p2,p2).move_to(code);
+                }
+              } else if (*ps=='/')
+                CImg<ulongT>::vector((ulongT)mp_complex_div_vv,arg1,arg1,arg2).move_to(code);
+              else
+                CImg<ulongT>::vector((ulongT)mp_complex_pow_vv,arg1,arg1,arg2).move_to(code);
+            } else { // Complex **= scalar
+              if (*ps=='*') self_vector_s(arg1,mp_self_mul,arg2);
+              else if (*ps=='/') self_vector_s(arg1,mp_self_div,arg2);
+              else CImg<ulongT>::vector((ulongT)mp_complex_pow_vs,arg1,arg1,arg2).move_to(code);
+            }
+
+            // Write computed value back in image if necessary.
+            if (*ref==4) { // Image value (vector): I/J[_#ind,off] **= value
+              is_parallelizable = false;
+              p1 = ref[1]; // Index
+              is_relative = (bool)ref[2];
+              arg3 = ref[3]; // Offset
+              if (p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int));
+              if (p1!=~0U) {
+                if (!listout) _cimg_mp_return(arg1);
+                CImg<ulongT>::vector((ulongT)(is_relative?mp_list_set_Joff_v:mp_list_set_Ioff_v),
+                                    arg1,p1,arg3).move_to(code);
+              } else {
+                if (!imgout) _cimg_mp_return(arg1);
+                CImg<ulongT>::vector((ulongT)(is_relative?mp_set_Joff_v:mp_set_Ioff_v),
+                                    arg1,arg3).move_to(code);
+              }
+
+            } else if (*ref==5) { // Image value (vector): I/J(_#ind,_x,_y,_z,_c) **= value
+              is_parallelizable = false;
+              p1 = ref[1]; // Index
+              is_relative = (bool)ref[2];
+              arg3 = ref[3]; // X
+              arg4 = ref[4]; // Y
+              arg5 = ref[5]; // Z
+              if (p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int));
+              if (p1!=~0U) {
+                if (!listout) _cimg_mp_return(arg1);
+                CImg<ulongT>::vector((ulongT)(is_relative?mp_list_set_Jxyz_v:mp_list_set_Ixyz_v),
+                                    arg1,p1,arg3,arg4,arg5).move_to(code);
+              } else {
+                if (!imgout) _cimg_mp_return(arg1);
+                CImg<ulongT>::vector((ulongT)(is_relative?mp_set_Jxyz_v:mp_set_Ixyz_v),
+                                    arg1,arg3,arg4,arg5).move_to(code);
+              }
+            }
+
+            _cimg_mp_return(arg1);
+          }
+
+        for (s = se2, ps = se3, ns = ps - 1; s>ss1; --s, --ps, --ns) // Here, ns = ps - 1
+          if (*s=='=' && (*ps=='+' || *ps=='-' || *ps=='*' || *ps=='/' || *ps=='%' ||
+                          *ps=='&' || *ps=='^' || *ps=='|' ||
+                          (*ps=='>' && *ns=='>') || (*ps=='<' && *ns=='<')) &&
+              level[s - expr._data]==clevel) { // Self-operators (+=,-=,*=,/=,%=,>>=,<<=,&=,^=,|=)
+            switch (*ps) {
+            case '+' : op = mp_self_add; _cimg_mp_op("Operator '+='"); break;
+            case '-' : op = mp_self_sub; _cimg_mp_op("Operator '-='"); break;
+            case '*' : op = mp_self_mul; _cimg_mp_op("Operator '*='"); break;
+            case '/' : op = mp_self_div; _cimg_mp_op("Operator '/='"); break;
+            case '%' : op = mp_self_modulo; _cimg_mp_op("Operator '%='"); break;
+            case '<' : op = mp_self_bitwise_left_shift; _cimg_mp_op("Operator '<<='"); break;
+            case '>' : op = mp_self_bitwise_right_shift; _cimg_mp_op("Operator '>=='"); break;
+            case '&' : op = mp_self_bitwise_and; _cimg_mp_op("Operator '&='"); break;
+            case '|' : op = mp_self_bitwise_or; _cimg_mp_op("Operator '|='"); break;
+            default : op = mp_self_pow; _cimg_mp_op("Operator '^='"); break;
+            }
+            s1 = *ps=='>' || *ps=='<'?ns:ps;
+
+            ref.assign(7);
+            arg1 = compile(ss,s1,depth1,ref); // Variable slot
+            arg2 = compile(s + 1,se,depth1,0); // Value to apply
+
+            if (*ref>0 && !_cimg_mp_is_temp(arg1)) { // Apply operator on a copy if necessary.
+              if (_cimg_mp_is_vector(arg1)) arg1 = vector_copy(arg1);
+              else arg1 = scalar1(mp_copy,arg1);
+            }
+
+            if (*ref==1) { // Vector value (scalar): V[k] += scalar
+              _cimg_mp_check_type(arg2,2,1,0);
+              arg3 = ref[1]; // Vector slot
+              arg4 = ref[2]; // Index
+              if (p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int));
+              CImg<ulongT>::vector((ulongT)op,arg1,arg2).move_to(code);
+              CImg<ulongT>::vector((ulongT)mp_vector_set_off,arg1,arg3,(ulongT)_cimg_mp_vector_size(arg3),arg4,arg1).
+                move_to(code);
+              _cimg_mp_return(arg1);
+            }
+
+            if (*ref==2) { // Image value (scalar): i/j[_#ind,off] += scalar
+              _cimg_mp_check_type(arg2,2,1,0);
+              is_parallelizable = false;
+              p1 = ref[1]; // Index
+              is_relative = (bool)ref[2];
+              arg3 = ref[3]; // Offset
+              if (p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int));
+              CImg<ulongT>::vector((ulongT)op,arg1,arg2).move_to(code);
+              if (p1!=~0U) {
+                if (!listout) _cimg_mp_return(arg1);
+                CImg<ulongT>::vector((ulongT)(is_relative?mp_list_set_joff:mp_list_set_ioff),
+                                    arg1,p1,arg3).move_to(code);
+              } else {
+                if (!imgout) _cimg_mp_return(arg1);
+                CImg<ulongT>::vector((ulongT)(is_relative?mp_set_joff:mp_set_ioff),
+                                    arg1,arg3).move_to(code);
+              }
+              _cimg_mp_return(arg1);
+            }
+
+            if (*ref==3) { // Image value (scalar): i/j(_#ind,_x,_y,_z,_c) += scalar
+              _cimg_mp_check_type(arg2,2,1,0);
+              is_parallelizable = false;
+              p1 = ref[1]; // Index
+              is_relative = (bool)ref[2];
+              arg3 = ref[3]; // X
+              arg4 = ref[4]; // Y
+              arg5 = ref[5]; // Z
+              arg6 = ref[6]; // C
+              if (p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int));
+              CImg<ulongT>::vector((ulongT)op,arg1,arg2).move_to(code);
+              if (p1!=~0U) {
+                if (!listout) _cimg_mp_return(arg1);
+                CImg<ulongT>::vector((ulongT)(is_relative?mp_list_set_jxyzc:mp_list_set_ixyzc),
+                                    arg1,p1,arg3,arg4,arg5,arg6).move_to(code);
+              } else {
+                if (!imgout) _cimg_mp_return(arg1);
+                CImg<ulongT>::vector((ulongT)(is_relative?mp_set_jxyzc:mp_set_ixyzc),
+                                    arg1,arg3,arg4,arg5,arg6).move_to(code);
+              }
+              _cimg_mp_return(arg1);
+            }
+
+            if (*ref==4) { // Image value (vector): I/J[_#ind,off] += value
+              _cimg_mp_check_type(arg2,2,3,_cimg_mp_vector_size(arg1));
+              is_parallelizable = false;
+              p1 = ref[1]; // Index
+              is_relative = (bool)ref[2];
+              arg3 = ref[3]; // Offset
+              if (p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int));
+              if (_cimg_mp_is_scalar(arg2)) self_vector_s(arg1,op,arg2); else self_vector_v(arg1,op,arg2);
+              if (p1!=~0U) {
+                if (!listout) _cimg_mp_return(arg1);
+                CImg<ulongT>::vector((ulongT)(is_relative?mp_list_set_Joff_v:mp_list_set_Ioff_v),
+                                    arg1,p1,arg3).move_to(code);
+              } else {
+                if (!imgout) _cimg_mp_return(arg1);
+                CImg<ulongT>::vector((ulongT)(is_relative?mp_set_Joff_v:mp_set_Ioff_v),
+                                    arg1,arg3).move_to(code);
+              }
+              _cimg_mp_return(arg1);
+            }
+
+            if (*ref==5) { // Image value (vector): I/J(_#ind,_x,_y,_z,_c) += value
+              _cimg_mp_check_type(arg2,2,3,_cimg_mp_vector_size(arg1));
+              is_parallelizable = false;
+              p1 = ref[1]; // Index
+              is_relative = (bool)ref[2];
+              arg3 = ref[3]; // X
+              arg4 = ref[4]; // Y
+              arg5 = ref[5]; // Z
+              if (p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int));
+              if (_cimg_mp_is_scalar(arg2)) self_vector_s(arg1,op,arg2); else self_vector_v(arg1,op,arg2);
+              if (p1!=~0U) {
+                if (!listout) _cimg_mp_return(arg1);
+                CImg<ulongT>::vector((ulongT)(is_relative?mp_list_set_Jxyz_v:mp_list_set_Ixyz_v),
+                                    arg1,p1,arg3,arg4,arg5).move_to(code);
+              } else {
+                if (!imgout) _cimg_mp_return(arg1);
+                CImg<ulongT>::vector((ulongT)(is_relative?mp_set_Jxyz_v:mp_set_Ixyz_v),
+                                    arg1,arg3,arg4,arg5).move_to(code);
+              }
+              _cimg_mp_return(arg1);
+            }
+
+            if (_cimg_mp_is_vector(arg1)) { // Vector variable: V += value
+              _cimg_mp_check_type(arg2,2,3,_cimg_mp_vector_size(arg1));
+              if (_cimg_mp_is_vector(arg2)) self_vector_v(arg1,op,arg2); // Vector += vector
+              else self_vector_s(arg1,op,arg2); // Vector += scalar
+              _cimg_mp_return(arg1);
+            }
+
+            if (_cimg_mp_is_variable(arg1)) { // Scalar variable: s += scalar
+              _cimg_mp_check_type(arg2,2,1,0);
+              CImg<ulongT>::vector((ulongT)op,arg1,arg2).move_to(code);
+              _cimg_mp_return(arg1);
+            }
+
+            variable_name.assign(ss,(unsigned int)(s - ss)).back() = 0;
+            *se = saved_char; cimg::strellipsize(expr,64);
+            throw CImgArgumentException("[_cimg_math_parser] "
+                                        "CImg<%s>::%s: %s: Invalid left-hand operand '%s', "
+                                        "in expression '%s%s%s'.",
+                                        pixel_type(),_cimg_mp_calling_function,s_op,
+                                        variable_name._data,
+                                        (ss - 4)>expr._data?"...":"",
+                                        (ss - 4)>expr._data?ss - 4:expr._data,
+                                        se<&expr.back()?"...":"");
+          }
+
+        for (s = ss1; s<se1; ++s)
+          if (*s=='?' && level[s - expr._data]==clevel) { // Ternary operator 'cond?expr1:expr2'
+            _cimg_mp_op("Operator '?:'");
+            s1 = s + 1; while (s1<se1 && (*s1!=':' || level[s1 - expr._data]!=clevel)) ++s1;
+            arg1 = compile(ss,s,depth1,0);
+            _cimg_mp_check_type(arg1,1,1,0);
+            if (_cimg_mp_is_constant(arg1)) {
+              if ((bool)mem[arg1]) return compile(s + 1,*s1!=':'?se:s1,depth1,0);
+              else return *s1!=':'?0:compile(++s1,se,depth1,0);
+            }
+            p2 = code._width;
+            arg2 = compile(s + 1,*s1!=':'?se:s1,depth1,0);
+            p3 = code._width;
+            arg3 = *s1==':'?compile(++s1,se,depth1,0):_cimg_mp_is_vector(arg2)?vector(_cimg_mp_vector_size(arg2),0):0;
+            _cimg_mp_check_type(arg3,3,_cimg_mp_is_vector(arg2)?2:1,_cimg_mp_vector_size(arg2));
+            arg4 = _cimg_mp_is_vector(arg2)?_cimg_mp_vector_size(arg2):0; // Output vector size (or 0 if scalar)
+            if (arg4) pos = vector(arg4); else pos = scalar();
+            CImg<ulongT>::vector((ulongT)mp_if,pos,arg1,arg2,arg3,
+                                p3 - p2,code._width - p3,arg4).move_to(code,p2);
             _cimg_mp_return(pos);
           }
-        for (char *s = se2; s>ss; --s)
-          if (*s=='|' && level[s - expr._data]==clevel)
-            _cimg_mp_opcode2(mp_bitwise_or,compile(ss,s),compile(s + 1,se));
-        for (char *s = se2; s>ss; --s)
-          if (*s=='&' && level[s - expr._data]==clevel)
-            _cimg_mp_opcode2(mp_bitwise_and,compile(ss,s),compile(s + 1,se));
-        for (char *s = se3, *ns = se2; s>ss; --s, --ns)
-          if (*s=='!' && *ns=='=' && level[s - expr._data]==clevel)
-            _cimg_mp_opcode2(mp_noteq,compile(ss,s),compile(s + 2,se));
-        for (char *s = se3, *ns = se2; s>ss; --s, --ns)
-          if (*s=='=' && *ns=='=' && level[s - expr._data]==clevel)
-            _cimg_mp_opcode2(mp_eqeq,compile(ss,s),compile(s + 2,se));
-        for (char *s = se3, *ns = se2; s>ss; --s, --ns)
-          if (*s=='<' && *ns=='=' && level[s - expr._data]==clevel)
-            _cimg_mp_opcode2(mp_infeq,compile(ss,s),compile(s + 2,se));
-        for (char *s = se3, *ns = se2; s>ss; --s, --ns)
-          if (*s=='>' && *ns=='=' && level[s - expr._data]==clevel)
-            _cimg_mp_opcode2(mp_supeq,compile(ss,s),compile(s + 2,se));
-        for (char *s = se2, *ns = se1, *ps = se3; s>ss; --s, --ns, --ps)
-          if (*s=='<' && *ns!='<' && *ps!='<' && level[s - expr._data]==clevel)
-            _cimg_mp_opcode2(mp_inf,compile(ss,s),compile(s + 1,se));
-        for (char *s = se2, *ns = se1, *ps = se3; s>ss; --s, --ns, --ps)
-          if (*s=='>' && *ns!='>' && *ps!='>' && level[s - expr._data]==clevel)
-            _cimg_mp_opcode2(mp_sup,compile(ss,s),compile(s + 1,se));
-        for (char *s = se3, *ns = se2; s>ss; --s, --ns)
-          if (*s=='<' && *ns=='<' && level[s - expr._data]==clevel)
-            _cimg_mp_opcode2(mp_lsl,compile(ss,s),compile(s + 2,se));
-        for (char *s = se3, *ns = se2; s>ss; --s, --ns)
-          if (*s=='>' && *ns=='>' && level[s - expr._data]==clevel)
-            _cimg_mp_opcode2(mp_lsr,compile(ss,s),compile(s + 2,se));
-        for (char *s = se2, *ps = se3; s>ss; --s, --ps)
-          if (*s=='+' && *ps!='-' && *ps!='+' && *ps!='*' && *ps!='/' && *ps!='%' &&
-              *ps!='&' && *ps!='|' && *ps!='^' && *ps!='!' && *ps!='~' &&
-              (*ps!='e' || !(ps>ss && (*(ps - 1)=='.' || (*(ps - 1)>='0' && *(ps - 1)<='9')))) &&
-              level[s - expr._data]==clevel)
-            _cimg_mp_opcode2(mp_add,compile(ss,s),compile(s + 1,se));
-        for (char *s = se2, *ps = se3; s>ss; --s, --ps)
-          if (*s=='-' && *ps!='-' && *ps!='+' && *ps!='*' && *ps!='/' && *ps!='%' &&
-              *ps!='&' && *ps!='|' && *ps!='^' && *ps!='!' && *ps!='~' &&
-              (*ps!='e' || !(ps>ss && (*(ps - 1)=='.' || (*(ps - 1)>='0' && *(ps - 1)<='9')))) &&
-              level[s - expr._data]==clevel)
-            _cimg_mp_opcode2(mp_sub,compile(ss,s),compile(s + 1,se));
-        for (char *s = se2; s>ss; --s) if (*s=='*' && level[s - expr._data]==clevel) {
-            const unsigned int mem_left = compile(ss,s), p_right = code._width, mem_right = compile(s + 1,se);
-            if (mempos>=mem._width) mem.resize(-200,1,1,1,0);
-            const unsigned int pos = mempos++;
-            CImg<longT>::vector(_cimg_mp_enfunc(mp_mul),pos,mem_left,mem_right,code._width - p_right).
-              move_to(code,p_right);
+
+        for (s = se3, ns = se2; s>ss; --s, --ns)
+          if (*s=='|' && *ns=='|' && level[s - expr._data]==clevel) { // Logical or ('||')
+            _cimg_mp_op("Operator '||'");
+            arg1 = compile(ss,s,depth1,0);
+            p2 = code._width;
+            arg2 = compile(s + 2,se,depth1,0);
+            _cimg_mp_check_type(arg1,1,1,0);
+            _cimg_mp_check_type(arg2,2,1,0);
+            if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2))
+              _cimg_mp_constant(mem[arg1] || mem[arg2]);
+            pos = scalar();
+            CImg<ulongT>::vector((ulongT)mp_logical_or,pos,arg1,arg2,code._width - p2).
+              move_to(code,p2);
             _cimg_mp_return(pos);
           }
-        for (char *s = se2; s>ss; --s)
-          if (*s=='/' && level[s - expr._data]==clevel)
-            _cimg_mp_opcode2(mp_div,compile(ss,s),compile(s + 1,se));
-        for (char *s = se2, *ns = se1; s>ss; --s, --ns)
-          if (*s=='%' && *ns!='^' && level[s - expr._data]==clevel)
-            _cimg_mp_opcode2(mp_modulo,compile(ss,s),compile(s + 1,se));
-        if (ss<se1) {
-          if (*ss=='+') _cimg_mp_return(compile(ss1,se));
-          if (*ss=='-') _cimg_mp_opcode1(mp_minus,compile(ss1,se));
-          if (*ss=='!') _cimg_mp_opcode1(mp_logical_not,compile(ss1,se));
-          if (*ss=='~') _cimg_mp_opcode1(mp_bitwise_not,compile(ss1,se));
-        }
-        for (char *s = se2; s>ss; --s)
-          if (*s=='^' && level[s - expr._data]==clevel)
-            _cimg_mp_opcode2(mp_pow,compile(ss,s),compile(s + 1,se));
 
-        // Array-like access to image values 'i[offset]' and 'j[offset]'.
-        if (*se1==']') {
-          const bool is_relative = *ss=='j';
-          if ((*ss=='i' || is_relative) && *ss1=='[') {
-            if (*ss2==']') _cimg_mp_opcode0(mp_i);
-            _cimg_mp_opcode1(is_relative?mp_joff:mp_ioff,compile(ss2,se1));
+        for (s = se3, ns = se2; s>ss; --s, --ns)
+          if (*s=='&' && *ns=='&' && level[s - expr._data]==clevel) { // Logical and ('&&')
+            _cimg_mp_op("Operator '&&'");
+            arg1 = compile(ss,s,depth1,0);
+            p2 = code._width;
+            arg2 = compile(s + 2,se,depth1,0);
+            _cimg_mp_check_type(arg1,1,1,0);
+            _cimg_mp_check_type(arg2,2,1,0);
+            if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2))
+              _cimg_mp_constant(mem[arg1] && mem[arg2]);
+            pos = scalar();
+            CImg<ulongT>::vector((ulongT)mp_logical_and,pos,arg1,arg2,code._width - p2).
+              move_to(code,p2);
+            _cimg_mp_return(pos);
           }
-        }
 
-        // Look for a function call or a parenthesis.
-        if (*se1==')') {
-          if (*ss=='(') _cimg_mp_return(compile(ss1,se1));
-
-          const bool is_relative = *ss=='j';
-          if ((*ss=='i' || is_relative) && *ss1=='(') {
-            if (*ss2==')') _cimg_mp_opcode0(mp_i);
-            unsigned int
-              indx = is_relative?0U:16U, indy = is_relative?0U:17U,
-              indz = is_relative?0U:18U, indc = is_relative?0U:19U,
-              borders = 0, interpolation = 0;
-            if (ss2!=se1) {
-              char *s1 = ss2; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
-              indx = compile(ss2,s1);
-              if (s1<se1) {
-                char *s2 = ++s1; while (s2<se1 && (*s2!=',' || level[s2 - expr._data]!=clevel1)) ++s2;
-                indy = compile(s1,s2);
-                if (s2<se1) {
-                  char *s3 = ++s2; while (s3<se1 && (*s3!=',' || level[s3 - expr._data]!=clevel1)) ++s3;
-                  indz = compile(s2,s3);
-                  if (s3<se1) {
-                    char *s4 = ++s3; while (s4<se1 && (*s4!=',' || level[s4 - expr._data]!=clevel1)) ++s4;
-                    indc = compile(s3,s4);
-                    if (s4<se1) {
-                      char *s5 = ++s4; while (s5<se1 && (*s5!=',' || level[s5 - expr._data]!=clevel1)) ++s5;
-                      interpolation = compile(s4,s5);
-                      if (s5<se1) borders = compile(++s5,se1);
-                    }
-                  }
+        for (s = se2; s>ss; --s)
+          if (*s=='|' && level[s - expr._data]==clevel) { // Bitwise or ('|')
+            _cimg_mp_op("Operator '|'");
+            arg1 = compile(ss,s,depth1,0);
+            arg2 = compile(s + 1,se,depth1,0);
+            _cimg_mp_check_type(arg2,2,3,_cimg_mp_vector_size(arg1));
+            if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_bitwise_or,arg1,arg2);
+            if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_bitwise_or,arg1,arg2);
+            if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_bitwise_or,arg1,arg2);
+            if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2))
+              _cimg_mp_constant((ulongT)mem[arg1] | (ulongT)mem[arg2]);
+            _cimg_mp_scalar2(mp_bitwise_or,arg1,arg2);
+          }
+
+        for (s = se2; s>ss; --s)
+          if (*s=='&' && level[s - expr._data]==clevel) { // Bitwise and ('&')
+            _cimg_mp_op("Operator '&'");
+            arg1 = compile(ss,s,depth1,0);
+            arg2 = compile(s + 1,se,depth1,0);
+            _cimg_mp_check_type(arg2,2,3,_cimg_mp_vector_size(arg1));
+            if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_bitwise_and,arg1,arg2);
+            if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_bitwise_and,arg1,arg2);
+            if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_bitwise_and,arg1,arg2);
+            if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2))
+              _cimg_mp_constant((ulongT)mem[arg1] & (ulongT)mem[arg2]);
+            _cimg_mp_scalar2(mp_bitwise_and,arg1,arg2);
+          }
+
+        for (s = se3, ns = se2; s>ss; --s, --ns)
+          if (*s=='!' && *ns=='=' && level[s - expr._data]==clevel) { // Not equal to ('!=')
+            _cimg_mp_op("Operator '!='");
+            arg1 = compile(ss,s,depth1,0);
+            arg2 = compile(s + 2,se,depth1,0);
+            _cimg_mp_check_type(arg2,2,3,_cimg_mp_vector_size(arg1));
+            if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_neq,arg1,arg2);
+            if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_neq,arg1,arg2);
+            if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_neq,arg1,arg2);
+            if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1]!=mem[arg2]);
+            _cimg_mp_scalar2(mp_neq,arg1,arg2);
+          }
+
+        for (s = se3, ns = se2; s>ss; --s, --ns)
+          if (*s=='=' && *ns=='=' && level[s - expr._data]==clevel) { // Equal to ('==')
+            _cimg_mp_op("Operator '=='");
+            arg1 = compile(ss,s,depth1,0);
+            arg2 = compile(s + 2,se,depth1,0);
+            _cimg_mp_check_type(arg2,2,3,_cimg_mp_vector_size(arg1));
+            if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_eq,arg1,arg2);
+            if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_eq,arg1,arg2);
+            if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_eq,arg1,arg2);
+            if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1]==mem[arg2]);
+            _cimg_mp_scalar2(mp_eq,arg1,arg2);
+          }
+
+        for (s = se3, ns = se2; s>ss; --s, --ns)
+          if (*s=='<' && *ns=='=' && level[s - expr._data]==clevel) { // Less or equal than ('<=')
+            _cimg_mp_op("Operator '<='");
+            arg1 = compile(ss,s,depth1,0);
+            arg2 = compile(s + 2,se,depth1,0);
+            _cimg_mp_check_type(arg2,2,3,_cimg_mp_vector_size(arg1));
+            if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_lte,arg1,arg2);
+            if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_lte,arg1,arg2);
+            if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_lte,arg1,arg2);
+            if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1]<=mem[arg2]);
+            _cimg_mp_scalar2(mp_lte,arg1,arg2);
+          }
+
+        for (s = se3, ns = se2; s>ss; --s, --ns)
+          if (*s=='>' && *ns=='=' && level[s - expr._data]==clevel) { // Greater or equal than ('>=')
+            _cimg_mp_op("Operator '>='");
+            arg1 = compile(ss,s,depth1,0);
+            arg2 = compile(s + 2,se,depth1,0);
+            _cimg_mp_check_type(arg2,2,3,_cimg_mp_vector_size(arg1));
+            if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_gte,arg1,arg2);
+            if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_gte,arg1,arg2);
+            if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_gte,arg1,arg2);
+            if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1]>=mem[arg2]);
+            _cimg_mp_scalar2(mp_gte,arg1,arg2);
+          }
+
+        for (s = se2, ns = se1, ps = se3; s>ss; --s, --ns, --ps)
+          if (*s=='<' && *ns!='<' && *ps!='<' && level[s - expr._data]==clevel) { // Less than ('<')
+            _cimg_mp_op("Operator '<'");
+            arg1 = compile(ss,s,depth1,0);
+            arg2 = compile(s + 1,se,depth1,0);
+            _cimg_mp_check_type(arg2,2,3,_cimg_mp_vector_size(arg1));
+            if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_lt,arg1,arg2);
+            if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_lt,arg1,arg2);
+            if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_lt,arg1,arg2);
+            if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1]<mem[arg2]);
+            _cimg_mp_scalar2(mp_lt,arg1,arg2);
+          }
+
+        for (s = se2, ns = se1, ps = se3; s>ss; --s, --ns, --ps)
+          if (*s=='>' && *ns!='>' && *ps!='>' && level[s - expr._data]==clevel) { // Greather than ('>')
+            _cimg_mp_op("Operator '>'");
+            arg1 = compile(ss,s,depth1,0);
+            arg2 = compile(s + 1,se,depth1,0);
+            _cimg_mp_check_type(arg2,2,3,_cimg_mp_vector_size(arg1));
+            if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_gt,arg1,arg2);
+            if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_gt,arg1,arg2);
+            if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_gt,arg1,arg2);
+            if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1]>mem[arg2]);
+            _cimg_mp_scalar2(mp_gt,arg1,arg2);
+          }
+
+        for (s = se3, ns = se2; s>ss; --s, --ns)
+          if (*s=='<' && *ns=='<' && level[s - expr._data]==clevel) { // Left bit shift ('<<')
+            _cimg_mp_op("Operator '<<'");
+            arg1 = compile(ss,s,depth1,0);
+            arg2 = compile(s + 2,se,depth1,0);
+            _cimg_mp_check_type(arg2,2,3,_cimg_mp_vector_size(arg1));
+            if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2))
+              _cimg_mp_vector2_vv(mp_bitwise_left_shift,arg1,arg2);
+            if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2))
+              _cimg_mp_vector2_vs(mp_bitwise_left_shift,arg1,arg2);
+            if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2))
+              _cimg_mp_vector2_sv(mp_bitwise_left_shift,arg1,arg2);
+            if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2))
+              _cimg_mp_constant((longT)mem[arg1]<<(unsigned int)mem[arg2]);
+            _cimg_mp_scalar2(mp_bitwise_left_shift,arg1,arg2);
+          }
+
+        for (s = se3, ns = se2; s>ss; --s, --ns)
+          if (*s=='>' && *ns=='>' && level[s - expr._data]==clevel) { // Right bit shift ('>>')
+            _cimg_mp_op("Operator '>>'");
+            arg1 = compile(ss,s,depth1,0);
+            arg2 = compile(s + 2,se,depth1,0);
+            _cimg_mp_check_type(arg2,2,3,_cimg_mp_vector_size(arg1));
+            if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2))
+              _cimg_mp_vector2_vv(mp_bitwise_right_shift,arg1,arg2);
+            if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2))
+              _cimg_mp_vector2_vs(mp_bitwise_right_shift,arg1,arg2);
+            if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2))
+              _cimg_mp_vector2_sv(mp_bitwise_right_shift,arg1,arg2);
+            if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2))
+              _cimg_mp_constant((longT)mem[arg1]>>(unsigned int)mem[arg2]);
+            _cimg_mp_scalar2(mp_bitwise_right_shift,arg1,arg2);
+          }
+
+        for (ns = se1, s = se2, ps = pexpr._data + (se3 - expr._data); s>ss; --ns, --s, --ps)
+          if (*s=='+' && (*ns!='+' || ns!=se1) && *ps!='-' && *ps!='+' && *ps!='*' && *ps!='/' && *ps!='%' &&
+              *ps!='&' && *ps!='|' && *ps!='^' && *ps!='!' && *ps!='~' && *ps!='#' &&
+              (*ps!='e' || !(ps - pexpr._data>ss - expr._data && (*(ps - 1)=='.' || (*(ps - 1)>='0' &&
+                                                                                     *(ps - 1)<='9')))) &&
+              level[s - expr._data]==clevel) { // Addition ('+')
+            _cimg_mp_op("Operator '+'");
+            arg1 = compile(ss,s,depth1,0);
+            arg2 = compile(s + 1,se,depth1,0);
+            _cimg_mp_check_type(arg2,2,3,_cimg_mp_vector_size(arg1));
+            if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_add,arg1,arg2);
+            if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_add,arg1,arg2);
+            if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_add,arg1,arg2);
+            if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1] + mem[arg2]);
+            if (arg2==1) _cimg_mp_scalar1(mp_increment,arg1);
+            if (arg1==1) _cimg_mp_scalar1(mp_increment,arg2);
+            _cimg_mp_scalar2(mp_add,arg1,arg2);
+          }
+
+        for (ns = se1, s = se2, ps = pexpr._data + (se3 - expr._data); s>ss; --ns, --s, --ps)
+          if (*s=='-' && (*ns!='-' || ns!=se1) && *ps!='-' && *ps!='+' && *ps!='*' && *ps!='/' && *ps!='%' &&
+              *ps!='&' && *ps!='|' && *ps!='^' && *ps!='!' && *ps!='~' && *ps!='#' &&
+              (*ps!='e' || !(ps - pexpr._data>ss - expr._data && (*(ps - 1)=='.' || (*(ps - 1)>='0' &&
+                                                                                     *(ps - 1)<='9')))) &&
+              level[s - expr._data]==clevel) { // Subtraction ('-')
+            _cimg_mp_op("Operator '-'");
+            arg1 = compile(ss,s,depth1,0);
+            arg2 = compile(s + 1,se,depth1,0);
+            _cimg_mp_check_type(arg2,2,3,_cimg_mp_vector_size(arg1));
+            if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_sub,arg1,arg2);
+            if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_sub,arg1,arg2);
+            if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_sub,arg1,arg2);
+            if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1] - mem[arg2]);
+            if (arg2==1) _cimg_mp_scalar1(mp_decrement,arg1);
+            _cimg_mp_scalar2(mp_sub,arg1,arg2);
+          }
+
+        for (s = se3, ns = se2; s>ss; --s, --ns)
+          if (*s=='*' && *ns=='*' && level[s - expr._data]==clevel) { // Complex/matrix multiplication ('**')
+            _cimg_mp_op("Operator '**'");
+            arg1 = compile(ss,s,depth1,0);
+            arg2 = compile(s + 2,se,depth1,0);
+            if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) {
+              if (_cimg_mp_vector_size(arg1)==2 && _cimg_mp_vector_size(arg2)==2) { // Complex multiplication
+                pos = vector(2);
+                CImg<ulongT>::vector((ulongT)mp_complex_mul,pos,arg1,arg2).move_to(code);
+                _cimg_mp_return(pos);
+              } else { // Matrix multiplication
+                p1 = _cimg_mp_vector_size(arg1);
+                p2 = _cimg_mp_vector_size(arg2);
+                arg4 = p1/p2;
+                if (arg4*p2!=p1) {
+                  *se = saved_char; cimg::strellipsize(expr,64);
+                  throw CImgArgumentException("[_cimg_math_parser] "
+                                              "CImg<%s>::%s: %s: Types of left-hand and right-hand operands "
+                                              "('%s' and '%s') do not match, in expression '%s%s%s'.",
+                                              pixel_type(),_cimg_mp_calling_function,s_op,
+                                              s_type(arg1)._data,s_type(arg2)._data,
+                                              (ss - 4)>expr._data?"...":"",
+                                              (ss - 4)>expr._data?ss - 4:expr._data,
+                                              se<&expr.back()?"...":"");
                 }
+                pos = vector(arg4);
+                CImg<ulongT>::vector((ulongT)mp_matrix_mul,pos,arg1,arg2,arg4,p2,1).move_to(code);
+                _cimg_mp_return(pos);
               }
             }
-            _cimg_mp_opcode6(is_relative?mp_jxyzc:mp_ixyzc,indx,indy,indz,indc,interpolation,borders);
-          }
-          if (!std::strncmp(ss,"sin(",4)) _cimg_mp_opcode1(mp_sin,compile(ss4,se1));
-          if (!std::strncmp(ss,"cos(",4)) _cimg_mp_opcode1(mp_cos,compile(ss4,se1));
-          if (!std::strncmp(ss,"tan(",4)) _cimg_mp_opcode1(mp_tan,compile(ss4,se1));
-          if (!std::strncmp(ss,"log(",4)) _cimg_mp_opcode1(mp_log,compile(ss4,se1));
-          if (!std::strncmp(ss,"exp(",4)) _cimg_mp_opcode1(mp_exp,compile(ss4,se1));
-          if (!std::strncmp(ss,"abs(",4)) _cimg_mp_opcode1(mp_abs,compile(ss4,se1));
-          if (!std::strncmp(ss,"int(",4)) _cimg_mp_opcode1(mp_int,compile(ss4,se1));
-          if (!std::strncmp(ss,"sqr(",4)) _cimg_mp_opcode1(mp_sqr,compile(ss4,se1));
-          if (!std::strncmp(ss,"asin(",5)) _cimg_mp_opcode1(mp_asin,compile(ss5,se1));
-          if (!std::strncmp(ss,"acos(",5)) _cimg_mp_opcode1(mp_acos,compile(ss5,se1));
-          if (!std::strncmp(ss,"atan(",5)) _cimg_mp_opcode1(mp_atan,compile(ss5,se1));
-          if (!std::strncmp(ss,"sinh(",5)) _cimg_mp_opcode1(mp_sinh,compile(ss5,se1));
-          if (!std::strncmp(ss,"cosh(",5)) _cimg_mp_opcode1(mp_cosh,compile(ss5,se1));
-          if (!std::strncmp(ss,"tanh(",5)) _cimg_mp_opcode1(mp_tanh,compile(ss5,se1));
-          if (!std::strncmp(ss,"log2(",5)) _cimg_mp_opcode1(mp_log2,compile(ss5,se1));
-          if (!std::strncmp(ss,"sqrt(",5)) _cimg_mp_opcode1(mp_sqrt,compile(ss5,se1));
-          if (!std::strncmp(ss,"cbrt(",5)) _cimg_mp_opcode1(mp_cbrt,compile(ss5,se1));
-          if (!std::strncmp(ss,"sign(",5)) _cimg_mp_opcode1(mp_sign,compile(ss5,se1));
-          if (!std::strncmp(ss,"sinc(",5)) _cimg_mp_opcode1(mp_sinc,compile(ss5,se1));
-          if (!std::strncmp(ss,"log10(",6)) _cimg_mp_opcode1(mp_log10,compile(ss6,se1));
-
-          if ((*ss=='?' || *ss=='u') && *ss1=='(') { // ?() and u().
-            if (*ss2==')') _cimg_mp_opcode2(mp_u,0,1);
-            char *s1 = ss2; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
-            if (s1<se1) _cimg_mp_opcode2(mp_u,compile(ss2,s1),compile(s1 + 1,se1));
-            _cimg_mp_opcode2(mp_u,0,compile(ss2,s1));
-          }
-          if (*ss=='i' && *ss1=='f' && *ss2=='(') { // if().
-            char *s1 = ss3; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
-            char *s2 = s1 + 1; while (s2<se1 && (*s2!=',' || level[s2 - expr._data]!=clevel1)) ++s2;
-            const unsigned int
-              mem_cond = compile(ss3,s1),
-              p_left = code._width, mem_left = compile(s1 + 1,s2),
-              p_right = code._width, mem_right = compile(s2 + 1,se1);
-            if (mempos>=mem._width) mem.resize(-200,1,1,1,0);
-            const unsigned int pos = mempos++;
-            CImg<longT>::vector(_cimg_mp_enfunc(mp_if),pos,mem_cond,mem_left,mem_right,
-                                p_right - p_left,code._width - p_right).move_to(code,p_left);
-            _cimg_mp_return(pos);
+            if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_mul,arg1,arg2);
+            if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_mul,arg1,arg2);
+            if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1]*mem[arg2]);
+            _cimg_mp_scalar2(mp_mul,arg1,arg2);
+          }
+
+        for (s = se3, ns = se2; s>ss; --s, --ns)
+          if (*s=='/' && *ns=='/' && level[s - expr._data]==clevel) { // Complex division ('//')
+            _cimg_mp_op("Operator '//'");
+            arg1 = compile(ss,s,depth1,0);
+            arg2 = compile(s + 2,se,depth1,0);
+            _cimg_mp_check_type(arg1,1,3,2);
+            _cimg_mp_check_type(arg2,2,3,2);
+            if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) {
+              pos = vector(2);
+              CImg<ulongT>::vector((ulongT)mp_complex_div_vv,pos,arg1,arg2).move_to(code);
+              _cimg_mp_return(pos);
+            }
+            if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_div,arg1,arg2);
+            if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) {
+              pos = vector(2);
+              CImg<ulongT>::vector((ulongT)mp_complex_div_sv,pos,arg1,arg2).move_to(code);
+              _cimg_mp_return(pos);
+            }
+            if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1]/mem[arg2]);
+            _cimg_mp_scalar2(mp_div,arg1,arg2);
+          }
+
+        for (s = se2; s>ss; --s) if (*s=='*' && level[s - expr._data]==clevel) { // Multiplication ('*')
+            _cimg_mp_op("Operator '*'");
+            arg1 = compile(ss,s,depth1,0);
+            arg2 = compile(s + 1,se,depth1,0);
+            _cimg_mp_check_type(arg2,2,3,_cimg_mp_vector_size(arg1));
+            if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_mul,arg1,arg2);
+            if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_mul,arg1,arg2);
+            if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_mul,arg1,arg2);
+            if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1]*mem[arg2]);
+            _cimg_mp_scalar2(mp_mul,arg1,arg2);
+          }
+
+
+        for (s = se2; s>ss; --s) if (*s=='/' && level[s - expr._data]==clevel) { // Division ('/')
+            _cimg_mp_op("Operator '/'");
+            arg1 = compile(ss,s,depth1,0);
+            arg2 = compile(s + 1,se,depth1,0);
+            _cimg_mp_check_type(arg2,2,3,_cimg_mp_vector_size(arg1));
+            if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_div,arg1,arg2);
+            if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_div,arg1,arg2);
+            if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_div,arg1,arg2);
+            if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1]/mem[arg2]);
+            _cimg_mp_scalar2(mp_div,arg1,arg2);
+          }
+
+        for (s = se2, ns = se1; s>ss; --s, --ns)
+          if (*s=='%' && *ns!='^' && level[s - expr._data]==clevel) { // Modulo ('%')
+            _cimg_mp_op("Operator '%'");
+            arg1 = compile(ss,s,depth1,0);
+            arg2 = compile(s + 1,se,depth1,0);
+            _cimg_mp_check_type(arg2,2,3,_cimg_mp_vector_size(arg1));
+            if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_modulo,arg1,arg2);
+            if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_modulo,arg1,arg2);
+            if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_modulo,arg1,arg2);
+            if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2))
+              _cimg_mp_constant(cimg::mod(mem[arg1],mem[arg2]));
+            _cimg_mp_scalar2(mp_modulo,arg1,arg2);
+          }
+
+        if (se1>ss) {
+          if (*ss=='+' && (*ss1!='+' || (ss2<se && *ss2>='0' && *ss2<='9'))) { // Unary plus ('+')
+            _cimg_mp_op("Operator '+'");
+            _cimg_mp_return(compile(ss1,se,depth1,0));
+          }
+
+          if (*ss=='-' && (*ss1!='-' || (ss2<se && *ss2>='0' && *ss2<='9'))) { // Unary minus ('-')
+            _cimg_mp_op("Operator '-'");
+            arg1 = compile(ss1,se,depth1,0);
+            if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_minus,arg1);
+            if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(-mem[arg1]);
+            _cimg_mp_scalar1(mp_minus,arg1);
+          }
+
+          if (*ss=='!') { // Logical not ('!')
+            _cimg_mp_op("Operator '!'");
+            arg1 = compile(ss1,se,depth1,0);
+            if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_logical_not,arg1);
+            if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(!mem[arg1]);
+            _cimg_mp_scalar1(mp_logical_not,arg1);
+          }
+
+          if (*ss=='~') { // Bitwise not ('~')
+            _cimg_mp_op("Operator '~'");
+            arg1 = compile(ss1,se,depth1,0);
+            if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_bitwise_not,arg1);
+            if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(~(ulongT)mem[arg1]);
+            _cimg_mp_scalar1(mp_bitwise_not,arg1);
+          }
+        }
+
+        for (s = se3, ns = se2; s>ss; --s, --ns)
+          if (*s=='^' && *ns=='^' && level[s - expr._data]==clevel) { // Complex power ('^^')
+            _cimg_mp_op("Operator '^^'");
+            arg1 = compile(ss,s,depth1,0);
+            arg2 = compile(s + 2,se,depth1,0);
+            _cimg_mp_check_type(arg1,1,3,2);
+            _cimg_mp_check_type(arg2,2,3,2);
+            pos = (_cimg_mp_is_vector(arg1) || _cimg_mp_is_vector(arg2))?vector(2):0;
+            if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) {
+              CImg<ulongT>::vector((ulongT)mp_complex_pow_vv,pos,arg1,arg2).move_to(code);
+              _cimg_mp_return(pos);
+            }
+            if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) {
+              CImg<ulongT>::vector((ulongT)mp_complex_pow_vs,pos,arg1,arg2).move_to(code);
+              _cimg_mp_return(pos);
+            }
+            if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) {
+              CImg<ulongT>::vector((ulongT)mp_complex_pow_sv,pos,arg1,arg2).move_to(code);
+              _cimg_mp_return(pos);
+            }
+            if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2))
+              _cimg_mp_constant(std::pow(mem[arg1],mem[arg2]));
+            switch (arg2) {
+            case 0 : _cimg_mp_return(1);
+            case 1 : _cimg_mp_return(arg1);
+            case 2 : _cimg_mp_scalar1(mp_sqr,arg1);
+            case 3 : _cimg_mp_scalar1(mp_pow3,arg1);
+            case 4 : _cimg_mp_scalar1(mp_pow4,arg1);
+            default : _cimg_mp_scalar2(mp_pow,arg1,arg2);
+            }
+          }
+
+        for (s = se2; s>ss; --s)
+          if (*s=='^' && level[s - expr._data]==clevel) { // Power ('^')
+            _cimg_mp_op("Operator '^'");
+            arg1 = compile(ss,s,depth1,0);
+            arg2 = compile(s + 1,se,depth1,0);
+            _cimg_mp_check_type(arg2,2,3,_cimg_mp_vector_size(arg1));
+            if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_pow,arg1,arg2);
+            if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_pow,arg1,arg2);
+            if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_pow,arg1,arg2);
+            if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2))
+              _cimg_mp_constant(std::pow(mem[arg1],mem[arg2]));
+            switch (arg2) {
+            case 0 : _cimg_mp_return(1);
+            case 1 : _cimg_mp_return(arg1);
+            case 2 : _cimg_mp_scalar1(mp_sqr,arg1);
+            case 3 : _cimg_mp_scalar1(mp_pow3,arg1);
+            case 4 : _cimg_mp_scalar1(mp_pow4,arg1);
+            default : _cimg_mp_scalar2(mp_pow,arg1,arg2);
+            }
+          }
+
+        is_sth = ss1<se1 && (*ss=='+' || *ss=='-') && *ss1==*ss; // is pre-?
+        if (is_sth || (se2>ss && (*se1=='+' || *se1=='-') && *se2==*se1)) { // Pre/post-decrement and increment
+          if ((is_sth && *ss=='+') || (!is_sth && *se1=='+')) {
+            _cimg_mp_op("Operator '++'");
+            op = mp_self_increment;
+          } else {
+            _cimg_mp_op("Operator '--'");
+            op = mp_self_decrement;
           }
-          if (*ss=='f' && *ss1=='o' && *ss2=='r' && *ss3=='(') { // for().
-            char *s1 = ss4; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
-            char *s2 = s1 + 1; while (s2<se1 && (*s2!=',' || level[s2 - expr._data]!=clevel1)) ++s2;
-            char *s3 = s2 + 1; while (s3<se1 && (*s3!=',' || level[s3 - expr._data]!=clevel1)) ++s3;
-            compile(ss4,s1);
-            const unsigned int p_cond = code._width, mem_cond = compile(s1 + 1,s2), p_proc = code._width;
-            unsigned int mem_return;
-            if (s3<se1) { mem_return = compile(s3 + 1,se1); compile(s2 + 1,s3); } // Body + proc.
-            else mem_return = compile(s2 + 1,se1); // Proc only.
-            CImg<longT>::vector(_cimg_mp_enfunc(mp_whiledo),mem_return,mem_cond,p_proc - p_cond,code._width - p_proc).
-              move_to(code,p_cond);
-            _cimg_mp_return(mem_return);
-          }
-          if (!std::strncmp(ss,"dowhile(",8)) {
-            char *s1 = ss8; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
-            const unsigned int
-              p_proc = code._width, mem_proc = compile(ss8,s1), mem_cond = compile(s1 + 1,se1);
-            CImg<longT>::vector(_cimg_mp_enfunc(mp_dowhile),mem_proc,mem_cond,code._width - p_proc).
-              move_to(code,p_proc);
-            _cimg_mp_return(mem_proc);
+          ref.assign(7);
+          arg1 = is_sth?compile(ss2,se,depth1,ref):compile(ss,se2,depth1,ref); // Variable slot
+
+          if (*ref>0 && !_cimg_mp_is_temp(arg1)) { // Apply operator on a copy if necessary.
+            if (_cimg_mp_is_vector(arg1)) arg1 = vector_copy(arg1);
+            else arg1 = scalar1(mp_copy,arg1);
           }
-          if (!std::strncmp(ss,"whiledo(",8)) {
-            char *s1 = ss8; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
-            const unsigned int
-              p_cond = code._width, mem_cond = compile(ss8,s1),
-              p_proc = code._width, mem_proc = compile(s1 + 1,se1);
-            CImg<longT>::vector(_cimg_mp_enfunc(mp_whiledo),mem_proc,mem_cond,p_proc - p_cond,code._width - p_proc).
-              move_to(code,p_cond);
-            _cimg_mp_return(mem_proc);
+
+          if (is_sth) pos = arg1; // Determine return indice, depending on pre/post action
+          else {
+            if (_cimg_mp_is_vector(arg1)) pos = vector_copy(arg1);
+            else pos = scalar1(mp_copy,arg1);
           }
-          if (!std::strncmp(ss,"min(",4) || !std::strncmp(ss,"max(",4) ||
-              !std::strncmp(ss,"med(",4) || !std::strncmp(ss,"kth(",4) ||
-              !std::strncmp(ss,"arg(",4) ||
-              !std::strncmp(ss,"argmin(",7) || !std::strncmp(ss,"argmax(",7)) {
-            if (mempos>=mem.size()) mem.resize(-200,1,1,1,0);
-            const unsigned int pos = mempos++;
-            const bool is_argm = *ss=='a' && ss[3]!='(';
-            CImg<longT>::vector(_cimg_mp_enfunc(*ss=='a'?(ss[3]=='('?mp_arg:ss[4]=='i'?mp_argmin:mp_argmax):
-                                                *ss=='k'?mp_kth:ss[1]=='i'?mp_min:
-                                                ss[1]=='a'?mp_max:mp_med),pos).
-              move_to(_opcode);
-            for (char *s = is_argm?ss7:ss4; s<se; ++s) {
-              char *ns = s; while (ns<se && (*ns!=',' || level[ns - expr._data]!=clevel1) &&
-                                   (*ns!=')' || level[ns - expr._data]!=clevel)) ++ns;
-              CImg<longT>::vector(compile(s,ns)).move_to(_opcode);
-              s = ns;
+
+          if (*ref==1) { // Vector value (scalar): V[k]++
+            arg3 = ref[1]; // Vector slot
+            arg4 = ref[2]; // Index
+            if (p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int));
+            CImg<ulongT>::vector((ulongT)op,arg1,1).move_to(code);
+            CImg<ulongT>::vector((ulongT)mp_vector_set_off,arg1,arg3,(ulongT)_cimg_mp_vector_size(arg3),arg4,arg1).
+              move_to(code);
+            _cimg_mp_return(pos);
+          }
+
+          if (*ref==2) { // Image value (scalar): i/j[_#ind,off]++
+            is_parallelizable = false;
+            p1 = ref[1]; // Index
+            is_relative = (bool)ref[2];
+            arg3 = ref[3]; // Offset
+            if (p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int));
+            CImg<ulongT>::vector((ulongT)op,arg1).move_to(code);
+            if (p1!=~0U) {
+              if (!listout) _cimg_mp_return(pos);
+              CImg<ulongT>::vector((ulongT)(is_relative?mp_list_set_joff:mp_list_set_ioff),
+                                  arg1,p1,arg3).move_to(code);
+            } else {
+              if (!imgout) _cimg_mp_return(pos);
+              CImg<ulongT>::vector((ulongT)(is_relative?mp_set_joff:mp_set_ioff),
+                                  arg1,arg3).move_to(code);
             }
-            (_opcode>'y').move_to(code);
             _cimg_mp_return(pos);
           }
-          if (!std::strncmp(ss,"rol(",4) || !std::strncmp(ss,"ror(",4)) {
-            unsigned int value = 0, nb = 1;
-            char *s1 = ss4; while (s1<se1 && (*s1!=',' || level[s1-expr._data]!=clevel1)) ++s1;
-            value = compile(ss4,s1==se2?++s1:s1);
-            if (s1<se1) {
-              char *s2 = s1 + 1; while (s2<se1 && (*s2!=',' || level[s2-expr._data]!=clevel1)) ++s2;
-              nb = compile(s1 + 1,se1);
-            }
-            _cimg_mp_opcode2(*ss2=='l'?mp_rol:mp_ror,value,nb);
-          }
-          if (!std::strncmp(ss,"narg(",5)) {
-            if (*ss5==')') _cimg_mp_return(0);
-            unsigned int nb_args = 0;
-            for (char *s = ss5; s<se; ++s) {
-              char *ns = s; while (ns<se && (*ns!=',' || level[ns - expr._data]!=clevel1) &&
-                                   (*ns!=')' || level[ns - expr._data]!=clevel)) ++ns;
-              ++nb_args; s = ns;
-            }
-            if (nb_args==0 || nb_args==1) _cimg_mp_return(nb_args);
-            if (mempos>=mem.size()) mem.resize(-200,1,1,1,0);
-            const unsigned int pos = mempos++;
-            mem[pos] = nb_args;
+
+          if (*ref==3) { // Image value (scalar): i/j(_#ind,_x,_y,_z,_c)++
+            is_parallelizable = false;
+            p1 = ref[1]; // Index
+            is_relative = (bool)ref[2];
+            arg3 = ref[3]; // X
+            arg4 = ref[4]; // Y
+            arg5 = ref[5]; // Z
+            arg6 = ref[6]; // C
+            if (p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int));
+            CImg<ulongT>::vector((ulongT)op,arg1).move_to(code);
+            if (p1!=~0U) {
+              if (!listout) _cimg_mp_return(pos);
+              CImg<ulongT>::vector((ulongT)(is_relative?mp_list_set_jxyzc:mp_list_set_ixyzc),
+                                  arg1,p1,arg3,arg4,arg5,arg6).move_to(code);
+            } else {
+              if (!imgout) _cimg_mp_return(pos);
+              CImg<ulongT>::vector((ulongT)(is_relative?mp_set_jxyzc:mp_set_ixyzc),
+                                  arg1,arg3,arg4,arg5,arg6).move_to(code);
+            }
             _cimg_mp_return(pos);
           }
-          if (!std::strncmp(ss,"atan2(",6)) {
-            char *s1 = ss6; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
-            _cimg_mp_opcode2(mp_atan2,compile(ss6,s1),compile(s1 + 1,se1));
-          }
-          if (!std::strncmp(ss,"hypot(",6)) {
-            char *s1 = ss6; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
-            _cimg_mp_opcode2(mp_hypot,compile(ss6,s1),compile(s1 + 1,se1));
-          }
-          if (!std::strncmp(ss,"round(",6)) {
-            unsigned int value = 0, round = 1, direction = 0;
-            char *s1 = ss6; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
-            value = compile(ss6,s1==se2?++s1:s1);
-            if (s1<se1) {
-              char *s2 = s1 + 1; while (s2<se1 && (*s2!=',' || level[s2 - expr._data]!=clevel1)) ++s2;
-              round = compile(s1 + 1,s2==se2?++s2:s2);
-              if (s2<se1) direction = compile(s2 + 1,se1);
-            }
-            _cimg_mp_opcode3(mp_round,value,round,direction);
-          }
-          unsigned int norm_type = ~0U;
-          if ((cimg_sscanf(ss,"norm%u%c",&norm_type,&sep)==2 && sep=='(') ||
-              !std::strncmp(ss,"norminf(",8)) {
-            if (mempos>=mem.size()) mem.resize(-200,1,1,1,0);
-            const unsigned int pos = mempos++;
-            CImg<longT>::vector(_cimg_mp_enfunc(mp_norm),pos,(longT)(norm_type==~0U?-1:(int)norm_type)).
-              move_to(_opcode);
-            for (char *s = std::strchr(ss5,'(') + 1; s<se; ++s) {
-              char *ns = s; while (ns<se && (*ns!=',' || level[ns - expr._data]!=clevel1) &&
-                                   (*ns!=')' || level[ns - expr._data]!=clevel)) ++ns;
-              CImg<longT>::vector(compile(s,ns)).move_to(_opcode);
-              s = ns;
+
+          if (*ref==4) { // Image value (vector): I/J[_#ind,off]++
+            is_parallelizable = false;
+            p1 = ref[1]; // Index
+            is_relative = (bool)ref[2];
+            arg3 = ref[3]; // Offset
+            if (p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int));
+            self_vector_s(arg1,op==mp_self_increment?mp_self_add:mp_self_sub,1);
+            if (p1!=~0U) {
+              if (!listout) _cimg_mp_return(pos);
+              CImg<ulongT>::vector((ulongT)(is_relative?mp_list_set_Joff_v:mp_list_set_Ioff_v),
+                                  arg1,p1,arg3).move_to(code);
+            } else {
+              if (!imgout) _cimg_mp_return(pos);
+              CImg<ulongT>::vector((ulongT)(is_relative?mp_set_Joff_v:mp_set_Ioff_v),
+                                  arg1,arg3).move_to(code);
             }
-            (_opcode>'y').move_to(code);
             _cimg_mp_return(pos);
           }
-          if (!std::strncmp(ss,"date(",5)) {
-            char *s1 = ss5; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
-            unsigned int attr;
-            int d = -1;
-            if (cimg_sscanf(ss5,"%u%c",&attr,&sep)==2 && sep==')') {
-              *se1 = 0;
-              d = cimg::date(attr);
-              *se1 = ')';
+
+          if (*ref==5) { // Image value (vector): I/J(_#ind,_x,_y,_z,_c)++
+            is_parallelizable = false;
+            p1 = ref[1]; // Index
+            is_relative = (bool)ref[2];
+            arg3 = ref[3]; // X
+            arg4 = ref[4]; // Y
+            arg5 = ref[5]; // Z
+            if (p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int));
+            self_vector_s(arg1,op==mp_self_increment?mp_self_add:mp_self_sub,1);
+            if (p1!=~0U) {
+              if (!listout) _cimg_mp_return(pos);
+              CImg<ulongT>::vector((ulongT)(is_relative?mp_list_set_Jxyz_v:mp_list_set_Ixyz_v),
+                                  arg1,p1,arg3,arg4,arg5).move_to(code);
+            } else {
+              if (!imgout) _cimg_mp_return(pos);
+              CImg<ulongT>::vector((ulongT)(is_relative?mp_set_Jxyz_v:mp_set_Ixyz_v),
+                                  arg1,arg3,arg4,arg5).move_to(code);
             }
-            if (d==0 || d==1) _cimg_mp_return((unsigned int)d);
-            if (mempos>=mem.size()) mem.resize(-200,1,1,1,0);
-            const unsigned int pos = mempos++;
-            mem[pos] = d;
             _cimg_mp_return(pos);
           }
-          if (!std::strncmp(ss,"fdate(",6)) {
-            char *s1 = ss6; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
-            unsigned int attr;
-            int d = -1;
-            if (cimg_sscanf(ss6,"%u%c",&attr,&(sep=0))==2 && sep) {
-              *se1 = 0;
-              d = cimg::fdate(s1+1,attr);
-              *se1 = ')';
+
+          if (_cimg_mp_is_vector(arg1)) { // Vector variable: V++
+            self_vector_s(arg1,op==mp_self_increment?mp_self_add:mp_self_sub,1);
+            _cimg_mp_return(pos);
+          }
+
+          if (_cimg_mp_is_variable(arg1)) { // Scalar variable: s++
+            CImg<ulongT>::vector((ulongT)op,arg1).move_to(code);
+            _cimg_mp_return(pos);
+          }
+
+          if (is_sth) variable_name.assign(ss2,(unsigned int)(se - ss1));
+          else variable_name.assign(ss,(unsigned int)(se1 - ss));
+          variable_name.back() = 0;
+          *se = saved_char; cimg::strellipsize(variable_name,64); cimg::strellipsize(expr,64);
+          throw CImgArgumentException("[_cimg_math_parser] "
+                                      "CImg<%s>::%s: %s: Invalid operand '%s', "
+                                      "in expression '%s%s%s'.",
+                                      pixel_type(),_cimg_mp_calling_function,s_op,
+                                      variable_name._data,
+                                      (ss - 4)>expr._data?"...":"",
+                                      (ss - 4)>expr._data?ss - 4:expr._data,
+                                      se<&expr.back()?"...":"");
+        }
+
+        // Array-like access to vectors and  image values 'i/j[_#ind,offset,_boundary]' and 'vector[offset]'.
+        if (*se1==']' && *ss!='[') {
+          _cimg_mp_op("Operator '[]'");
+          is_relative = *ss=='j' || *ss=='J';
+
+          if ((*ss=='I' || *ss=='J') && *ss1=='[' &&
+              (reserved_label[*ss]==~0U || !_cimg_mp_is_vector(reserved_label[*ss]))) { // Image value as a vector
+            if (*ss2=='#') { // Index specified
+              s0 = ss3; while (s0<se1 && (*s0!=',' || level[s0 - expr._data]!=clevel1)) ++s0;
+              p1 = compile(ss3,s0++,depth1,0);
+              _cimg_mp_check_list(false);
+            } else { p1 = ~0U; s0 = ss2; }
+            s1 = s0; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
+            arg1 = compile(s0,s1,depth1,0); // Offset
+            arg2 = s1<se1?compile(++s1,se1,depth1,0):~0U; // Boundary
+            if (p_ref && arg2==~0U) {
+              *p_ref = 4;
+              p_ref[1] = p1;
+              p_ref[2] = (unsigned int)is_relative;
+              p_ref[3] = arg1;
+              if (p1!=~0U && _cimg_mp_is_temp(p1)) memtype[p1] = -1; // Prevent from being used in further optimization
+              if (_cimg_mp_is_temp(arg1)) memtype[arg1] = -1;
+            }
+            p2 = ~0U; // 'p2' must the dimension of the vector-valued operand if any
+            if (p1==~0U) p2 = imgin._spectrum;
+            else if (_cimg_mp_is_constant(p1)) {
+              p3 = (unsigned int)cimg::mod((int)mem[p1],listin.width());
+              p2 = listin[p3]._spectrum;
+            }
+            _cimg_mp_check_vector0(p2);
+            pos = vector(p2);
+            if (p1!=~0U) {
+              CImg<ulongT>::vector((ulongT)(is_relative?mp_list_Joff:mp_list_Ioff),
+                                  pos,p1,arg1,arg2==~0U?reserved_label[30]:arg2).move_to(code);
+            } else {
+              need_input_copy = true;
+              CImg<ulongT>::vector((ulongT)(is_relative?mp_Joff:mp_Ioff),
+                                  pos,arg1,arg2==~0U?reserved_label[30]:arg2).move_to(code);
             }
-            if (d==0 || d==1) _cimg_mp_return((unsigned int)d);
-            if (mempos>=mem.size()) mem.resize(-200,1,1,1,0);
-            const unsigned int pos = mempos++;
-            mem[pos] = d;
             _cimg_mp_return(pos);
           }
-          if (!std::strncmp(ss,"print(",6)) {
-            const unsigned int pos = compile(ss6,se1);
-            *se1 = 0;
-            ((CImg<longT>::vector(_cimg_mp_enfunc(mp_print),pos),CImg<longT>::string(ss6).unroll('y'))>'y').
-              move_to(code);
-            *se1 = ')';
+
+          if ((*ss=='i' || *ss=='j') && *ss1=='[' &&
+              (reserved_label[*ss]==~0U || !_cimg_mp_is_vector(reserved_label[*ss]))) { // Image value as a scalar
+            if (*ss2=='#') { // Index specified
+              s0 = ss3; while (s0<se1 && (*s0!=',' || level[s0 - expr._data]!=clevel1)) ++s0;
+              p1 = compile(ss3,s0++,depth1,0);
+            } else { p1 = ~0U; s0 = ss2; }
+            s1 = s0; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
+            arg1 = compile(s0,s1,depth1,0); // Offset
+            arg2 = s1<se1?compile(++s1,se1,depth1,0):~0U; // Boundary
+            if (p_ref && arg2==~0U) {
+              *p_ref = 2;
+              p_ref[1] = p1;
+              p_ref[2] = (unsigned int)is_relative;
+              p_ref[3] = arg1;
+              if (p1!=~0U && _cimg_mp_is_temp(p1)) memtype[p1] = -1; // Prevent from being used in further optimization
+              if (_cimg_mp_is_temp(arg1)) memtype[arg1] = -1;
+            }
+            if (p1!=~0U) {
+              if (!listin) _cimg_mp_return(0);
+              pos = scalar3(is_relative?mp_list_joff:mp_list_ioff,p1,arg1,arg2==~0U?reserved_label[30]:arg2);
+            } else {
+              if (!imgin) _cimg_mp_return(0);
+              need_input_copy = true;
+              pos = scalar2(is_relative?mp_joff:mp_ioff,arg1,arg2==~0U?reserved_label[30]:arg2);
+            }
+            memtype[pos] = -1; // Create it as a variable to prevent from being used in further optimization
             _cimg_mp_return(pos);
           }
 
-          // Sub-family of 'is_?()' functions.
-          if (*ss=='i' && *ss1=='s') {
-            if (!std::strncmp(ss,"isin(",5)) {
-              if (mempos>=mem.size()) mem.resize(-200,1,1,1,0);
-              const unsigned int pos = mempos++;
-              CImg<longT>::vector(_cimg_mp_enfunc(mp_isin),pos).move_to(_opcode);
-              for (char *s = ss5; s<se; ++s) {
-                char *ns = s; while (ns<se && (*ns!=',' || level[ns - expr._data]!=clevel1) &&
-                                     (*ns!=')' || level[ns - expr._data]!=clevel)) ++ns;
-                CImg<longT>::vector(compile(s,ns)).move_to(_opcode);
-                s = ns;
+          s0 = se1; while (s0>ss && *s0!='[') --s0;
+          if (s0>ss) { // Vector value
+            arg1 = compile(ss,s0,depth1,0);
+            s1 = s0 + 1; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
+
+            if (s1<se1) { // Two arguments -> sub-vector extraction
+              arg2 = compile(++s0,s1,depth1,0);
+              arg3 = compile(++s1,se1,depth1,0);
+              _cimg_mp_check_constant(arg2,1,false);
+              _cimg_mp_check_constant(arg3,2,false);
+              p1 = (unsigned int)mem[arg2];
+              p2 = (unsigned int)mem[arg3];
+              p3 = _cimg_mp_vector_size(arg1);
+              if (p1>=p3 || p2>=p3) {
+                variable_name.assign(ss,(unsigned int)(s0 - ss)).back() = 0;
+                *se = saved_char; cimg::strellipsize(variable_name,64); cimg::strellipsize(expr,64);
+                throw CImgArgumentException("[_cimg_math_parser] "
+                                            "CImg<%s>::%s: %s: Out-of-bounds request for sub-vector '%s[%d,%d]' "
+                                            "(vector '%s' has dimension %u), "
+                                            "in expression '%s%s%s'.",
+                                            pixel_type(),_cimg_mp_calling_function,s_op,
+                                            variable_name._data,(int)mem[arg2],(int)mem[arg3],
+                                            variable_name._data,p3,
+                                            (ss - 4)>expr._data?"...":"",
+                                            (ss - 4)>expr._data?ss - 4:expr._data,
+                                            se<&expr.back()?"...":"");
               }
-              (_opcode>'y').move_to(code);
+              if (p1>p2) cimg::swap(p1,p2);
+              (p2-=p1)++;
+              pos = vector(p2);
+              CImg<ulongT>::vector((ulongT)mp_vector_crop,pos,arg1,p1,p2).move_to(code);
               _cimg_mp_return(pos);
             }
-            if (!std::strncmp(ss,"isval(",6)) {
-              double val = 0;
-              if (cimg_sscanf(ss6,"%lf%c%c",&val,&sep,&end)==2 && sep==')') _cimg_mp_return(1);
-              _cimg_mp_return(0);
-            }
-            if (!std::strncmp(ss,"isdir(",6)) {
-              *se1 = 0;
-              const bool is_dir = cimg::is_directory(ss6);
-              *se1 = ')';
-              _cimg_mp_return(is_dir?1U:0U);
+
+            // One argument -> vector value reference
+            if (_cimg_mp_is_scalar(arg1)) {
+              variable_name.assign(ss,(unsigned int)(s0 - ss)).back() = 0;
+              *se = saved_char; cimg::strellipsize(variable_name,64); cimg::strellipsize(expr,64);
+              throw CImgArgumentException("[_cimg_math_parser] "
+                                          "CImg<%s>::%s: %s: Array brackets used on non-vector variable '%s', "
+                                          "in expression '%s%s%s'.",
+                                          pixel_type(),_cimg_mp_calling_function,s_op,
+                                          variable_name._data,
+                                          (ss - 4)>expr._data?"...":"",
+                                          (ss - 4)>expr._data?ss - 4:expr._data,
+                                          se<&expr.back()?"...":"");
             }
-            if (!std::strncmp(ss,"isfile(",7)) {
-              *se1 = 0;
-              const bool is_file = cimg::is_file(ss7);
-              *se1 = ')';
-              _cimg_mp_return(is_file?1U:0U);
+
+            arg2 = compile(++s0,se1,depth1,0);
+            if (_cimg_mp_is_constant(arg2)) { // Constant index
+              nb = (int)mem[arg2];
+              if (nb>=0 && nb<(int)_cimg_mp_vector_size(arg1)) _cimg_mp_return(arg1 + 1 + nb);
+              variable_name.assign(ss,(unsigned int)(s0 - ss)).back() = 0;
+              *se = saved_char; cimg::strellipsize(variable_name,64); cimg::strellipsize(expr,64);
+              throw CImgArgumentException("[_cimg_math_parser] "
+                                          "CImg<%s>::%s: Out-of-bounds reference '%s[%d]' "
+                                          "(vector '%s' has dimension %u), "
+                                          "in expression '%s%s%s'.",
+                                          pixel_type(),_cimg_mp_calling_function,
+                                          variable_name._data,nb,
+                                          variable_name._data,_cimg_mp_vector_size(arg1),
+                                          (ss - 4)>expr._data?"...":"",
+                                          (ss - 4)>expr._data?ss - 4:expr._data,
+                                          se<&expr.back()?"...":"");
             }
-            if (!std::strncmp(ss,"isnan(",6)) {
-              if (ss6==se1) _cimg_mp_return(0);
-              _cimg_mp_opcode1(mp_isnan,compile(ss6,se1));
+            if (p_ref) {
+              *p_ref = 1;
+              p_ref[1] = arg1;
+              p_ref[2] = arg2;
+              if (_cimg_mp_is_temp(arg2)) memtype[arg2] = -1; // Prevent from being used in further optimization
             }
-            if (!std::strncmp(ss,"isinf(",6)) {
-              if (ss6==se1) _cimg_mp_return(0);
-              _cimg_mp_opcode1(mp_isinf,compile(ss6,se1));
+            _cimg_mp_scalar3(mp_vector_off,arg1,(ulongT)_cimg_mp_vector_size(arg1),arg2);
+          }
+        }
+
+        // Look for a function call, an access to image value, or a parenthesis.
+        if (*se1==')') {
+          if (*ss=='(') _cimg_mp_return(compile(ss1,se1,depth1,p_ref)); // Simple parentheses
+          is_relative = *ss=='j' || *ss=='J';
+          _cimg_mp_op("Operator '()'");
+
+          // I/J(_#ind,_x,_y,_z,_interpolation,_boundary)
+          if ((*ss=='I' || *ss=='J') && *ss1=='(') { // Image value as scalar
+            if (*ss2=='#') { // Index specified
+              s0 = ss3; while (s0<se1 && (*s0!=',' || level[s0 - expr._data]!=clevel1)) ++s0;
+              p1 = compile(ss3,s0++,depth1,0);
+              _cimg_mp_check_list(false);
+            } else { p1 = ~0U; s0 = ss2; }
+            arg1 = is_relative?0U:(unsigned int)_cimg_mp_x;
+            arg2 = is_relative?0U:(unsigned int)_cimg_mp_y;
+            arg3 = is_relative?0U:(unsigned int)_cimg_mp_z;
+            arg4 = arg5 = ~0U;
+            if (s0<se1) {
+              s1 = s0; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
+              arg1 = compile(s0,s1,depth1,0);
+              if (_cimg_mp_is_vector(arg1)) { // Coordinates specified as a vector
+                p2 = _cimg_mp_vector_size(arg1);
+                ++arg1;
+                if (p2>1) {
+                  arg2 = arg1 + 1;
+                  if (p2>2) arg3 = arg2 + 1;
+                }
+                if (s1<se1) {
+                  s2 = ++s1; while (s2<se1 && (*s2!=',' || level[s2 - expr._data]!=clevel1)) ++s2;
+                  arg4 = compile(s1,s2,depth1,0);
+                  arg5 = s2<se1?compile(++s2,se1,depth1,0):~0U;
+                }
+              } else if (s1<se1) {
+                s2 = ++s1; while (s2<se1 && (*s2!=',' || level[s2 - expr._data]!=clevel1)) ++s2;
+                arg2 = compile(s1,s2,depth1,0);
+                if (s2<se1) {
+                  s3 = ++s2; while (s3<se1 && (*s3!=',' || level[s3 - expr._data]!=clevel1)) ++s3;
+                  arg3 = compile(s2,s3,depth1,0);
+                  if (s3<se1) {
+                    s2 = ++s3; while (s2<se1 && (*s2!=',' || level[s2 - expr._data]!=clevel1)) ++s2;
+                    arg4 = compile(s3,s2,depth1,0);
+                    arg5 = s2<se1?compile(++s2,se1,depth1,0):~0U;
+                  }
+                }
+              }
             }
-            if (!std::strncmp(ss,"isint(",6)) {
-              if (ss6==se1) _cimg_mp_return(0);
-              _cimg_mp_opcode1(mp_isint,compile(ss6,se1));
+            if (p_ref && arg4==~0U && arg5==~0U) {
+              *p_ref = 5;
+              p_ref[1] = p1;
+              p_ref[2] = (unsigned int)is_relative;
+              p_ref[3] = arg1;
+              p_ref[4] = arg2;
+              p_ref[5] = arg3;
+              if (p1!=~0U && _cimg_mp_is_temp(p1)) memtype[p1] = -1; // Prevent from being used in further optimization
+              if (_cimg_mp_is_temp(arg1)) memtype[arg1] = -1;
+              if (_cimg_mp_is_temp(arg2)) memtype[arg2] = -1;
+              if (_cimg_mp_is_temp(arg3)) memtype[arg3] = -1;
+            }
+            p2 = ~0U; // 'p2' must the dimension of the vector-valued operand if any
+            if (p1==~0U) p2 = imgin._spectrum;
+            else if (_cimg_mp_is_constant(p1)) {
+              p3 = (unsigned int)cimg::mod((int)mem[p1],listin.width());
+              p2 = listin[p3]._spectrum;
+            }
+            _cimg_mp_check_vector0(p2);
+            pos = vector(p2);
+            if (p1!=~0U)
+              CImg<ulongT>::vector((ulongT)(is_relative?mp_list_Jxyz:mp_list_Ixyz),
+                                  pos,p1,arg1,arg2,arg3,
+                                  arg4==~0U?reserved_label[29]:arg4,
+                                  arg5==~0U?reserved_label[30]:arg5).move_to(code);
+            else {
+              need_input_copy = true;
+              CImg<ulongT>::vector((ulongT)(is_relative?mp_Jxyz:mp_Ixyz),
+                                  pos,arg1,arg2,arg3,
+                                  arg4==~0U?reserved_label[29]:arg4,
+                                  arg5==~0U?reserved_label[30]:arg5).move_to(code);
             }
-            if (!std::strncmp(ss,"isbool(",7)) {
-              if (ss7==se1) _cimg_mp_return(0);
-              _cimg_mp_opcode1(mp_isbool,compile(ss7,se1));
+            _cimg_mp_return(pos);
+          }
+
+          // i/j(_#ind,_x,_y,_z,_c,_interpolation,_boundary)
+          if ((*ss=='i' || *ss=='j') && *ss1=='(') { // Image value as scalar
+            if (*ss2=='#') { // Index specified
+              s0 = ss3; while (s0<se1 && (*s0!=',' || level[s0 - expr._data]!=clevel1)) ++s0;
+              p1 = compile(ss3,s0++,depth1,0);
+            } else { p1 = ~0U; s0 = ss2; }
+            arg1 = is_relative?0U:(unsigned int)_cimg_mp_x;
+            arg2 = is_relative?0U:(unsigned int)_cimg_mp_y;
+            arg3 = is_relative?0U:(unsigned int)_cimg_mp_z;
+            arg4 = is_relative?0U:(unsigned int)_cimg_mp_c;
+            arg5 = arg6 = ~0U;
+            if (s0<se1) {
+              s1 = s0; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
+              arg1 = compile(s0,s1,depth1,0);
+              if (_cimg_mp_is_vector(arg1)) { // Coordinates specified as a vector
+                p2 = _cimg_mp_vector_size(arg1);
+                ++arg1;
+                if (p2>1) {
+                  arg2 = arg1 + 1;
+                  if (p2>2) {
+                    arg3 = arg2 + 1;
+                    if (p2>3) arg4 = arg3 + 1;
+                  }
+                }
+                if (s1<se1) {
+                  s2 = ++s1; while (s2<se1 && (*s2!=',' || level[s2 - expr._data]!=clevel1)) ++s2;
+                  arg5 = compile(s1,s2,depth1,0);
+                  arg6 = s2<se1?compile(++s2,se1,depth1,0):~0U;
+                }
+              } else if (s1<se1) {
+                s2 = ++s1; while (s2<se1 && (*s2!=',' || level[s2 - expr._data]!=clevel1)) ++s2;
+                arg2 = compile(s1,s2,depth1,0);
+                if (s2<se1) {
+                  s3 = ++s2; while (s3<se1 && (*s3!=',' || level[s3 - expr._data]!=clevel1)) ++s3;
+                  arg3 = compile(s2,s3,depth1,0);
+                  if (s3<se1) {
+                    s2 = ++s3; while (s2<se1 && (*s2!=',' || level[s2 - expr._data]!=clevel1)) ++s2;
+                    arg4 = compile(s3,s2,depth1,0);
+                    if (s2<se1) {
+                      s3 = ++s2; while (s3<se1 && (*s3!=',' || level[s3 - expr._data]!=clevel1)) ++s3;
+                      arg5 = compile(s2,s3,depth1,0);
+                      arg6 = s3<se1?compile(++s3,se1,depth1,0):~0U;
+                    }
+                  }
+                }
+              }
             }
+            if (p_ref && arg5==~0U && arg6==~0U) {
+              *p_ref = 3;
+              p_ref[1] = p1;
+              p_ref[2] = (unsigned int)is_relative;
+              p_ref[3] = arg1;
+              p_ref[4] = arg2;
+              p_ref[5] = arg3;
+              p_ref[6] = arg4;
+              if (p1!=~0U && _cimg_mp_is_temp(p1)) memtype[p1] = -1; // Prevent from being used in further optimization
+              if (_cimg_mp_is_temp(arg1)) memtype[arg1] = -1;
+              if (_cimg_mp_is_temp(arg2)) memtype[arg2] = -1;
+              if (_cimg_mp_is_temp(arg3)) memtype[arg3] = -1;
+              if (_cimg_mp_is_temp(arg4)) memtype[arg4] = -1;
+            }
+
+            if (p1!=~0U) {
+              if (!listin) _cimg_mp_return(0);
+              pos = scalar7(is_relative?mp_list_jxyzc:mp_list_ixyzc,
+                            p1,arg1,arg2,arg3,arg4,
+                            arg5==~0U?reserved_label[29]:arg5,
+                            arg6==~0U?reserved_label[30]:arg6);
+            } else {
+              if (!imgin) _cimg_mp_return(0);
+              need_input_copy = true;
+              pos = scalar6(is_relative?mp_jxyzc:mp_ixyzc,
+                            arg1,arg2,arg3,arg4,
+                            arg5==~0U?reserved_label[29]:arg5,
+                            arg6==~0U?reserved_label[30]:arg6);
+            }
+            memtype[pos] = -1; // Create it as a variable to prevent from being used in further optimization
+            _cimg_mp_return(pos);
           }
-        }
 
-        // No known item found, assuming this is an already initialized variable.
-        CImg<charT> variable_name(ss,(unsigned int)(se - ss + 1));
-        variable_name.back() = 0;
-        if (variable_name[1]) { // Multi-char variable.
-          cimglist_for(labelM,i) if (!std::strcmp(variable_name,labelM[i])) _cimg_mp_return(labelMpos[i]);
-        } else if (reserved_label[*variable_name]!=~0U) // Single-char variable.
-          _cimg_mp_return(reserved_label[*variable_name]);
-        *se = saved_char;
-        throw CImgArgumentException("[_cimg_math_parser] "
-                                    "CImg<%s>::%s(): Invalid item '%s' in expression '%s%s%s'.",
-                                    pixel_type(),calling_function,
-                                    variable_name._data,
-                                    (ss - 8)>expr._data?"...":"",
-                                    (ss - 8)>expr._data?ss - 8:expr._data,
-                                    se<&expr.back()?"...":"");
-      }
+          // Mathematical functions.
+          switch (*ss) {
+          case 'a' :
+            if (!std::strncmp(ss,"abs(",4)) { // Absolute value
+              _cimg_mp_op("Function 'abs()'");
+              arg1 = compile(ss4,se1,depth1,0);
+              if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_abs,arg1);
+              if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(cimg::abs(mem[arg1]));
+              _cimg_mp_scalar1(mp_abs,arg1);
+            }
+
+            if (!std::strncmp(ss,"acos(",5)) { // Arccos
+              _cimg_mp_op("Function 'acos()'");
+              arg1 = compile(ss5,se1,depth1,0);
+              if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_acos,arg1);
+              if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::acos(mem[arg1]));
+              _cimg_mp_scalar1(mp_acos,arg1);
+            }
+
+            if (!std::strncmp(ss,"asin(",5)) { // Arcsin
+              _cimg_mp_op("Function 'asin()'");
+              arg1 = compile(ss5,se1,depth1,0);
+              if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_asin,arg1);
+              if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::asin(mem[arg1]));
+              _cimg_mp_scalar1(mp_asin,arg1);
+            }
+
+            if (!std::strncmp(ss,"atan(",5)) { // Arctan
+              _cimg_mp_op("Function 'atan()'");
+              arg1 = compile(ss5,se1,depth1,0);
+              if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_atan,arg1);
+              if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::atan(mem[arg1]));
+              _cimg_mp_scalar1(mp_atan,arg1);
+            }
+
+            if (!std::strncmp(ss,"atan2(",6)) { // Arctan2
+              _cimg_mp_op("Function 'atan2()'");
+              s1 = ss6; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
+              arg1 = compile(ss6,s1,depth1,0);
+              arg2 = compile(++s1,se1,depth1,0);
+              _cimg_mp_check_type(arg2,2,3,_cimg_mp_vector_size(arg1));
+              if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_atan2,arg1,arg2);
+              if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_atan2,arg1,arg2);
+              if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_atan2,arg1,arg2);
+              if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2))
+                _cimg_mp_constant(std::atan2(mem[arg1],mem[arg2]));
+              _cimg_mp_scalar2(mp_atan2,arg1,arg2);
+            }
+            break;
 
-      // Evaluation functions, known by the parser.
-      // Defining these functions 'static' ensures that sizeof(mp_func)==sizeof(ulong), so we can store pointers to them
-      // directly in the opcode vectors.
-      static double mp_u(_cimg_math_parser& mp) {
-        return mp.mem[mp.opcode(2)] + cimg::rand()*(mp.mem[mp.opcode(3)] - mp.mem[mp.opcode(2)]);
-      }
+          case 'c' :
+            if (!std::strncmp(ss,"cabs(",5)) { // Complex absolute value
+              _cimg_mp_op("Function 'cabs()'");
+              arg1 = compile(ss5,se1,depth1,0);
+              _cimg_mp_check_type(arg1,0,2,2);
+              _cimg_mp_scalar2(mp_hypot,arg1 + 1,arg1 + 2);
+            }
 
-      static double mp_g(_cimg_math_parser& mp) {
-        cimg::unused(mp);
-        return cimg::grand();
-      }
+            if (!std::strncmp(ss,"carg(",5)) { // Complex argument
+              _cimg_mp_op("Function 'carg()'");
+              arg1 = compile(ss5,se1,depth1,0);
+              _cimg_mp_check_type(arg1,0,2,2);
+              _cimg_mp_scalar2(mp_atan2,arg1 + 2,arg1 + 1);
+            }
 
-      static double mp_i(_cimg_math_parser& mp) {
-        return (double)mp.input.atXYZC((int)mp.mem[16],(int)mp.mem[17],(int)mp.mem[18],(int)mp.mem[19],0);
-      }
+            if (!std::strncmp(ss,"cbrt(",5)) { // Cubic root
+              _cimg_mp_op("Function 'cbrt()'");
+              arg1 = compile(ss5,se1,depth1,0);
+              if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_cbrt,arg1);
+              if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::pow(mem[arg1],1.0/3));
+              _cimg_mp_scalar1(mp_cbrt,arg1);
+            }
 
-      static double mp_logical_and(_cimg_math_parser& mp) {
-        const bool value_left = (bool)mp.mem[mp.opcode(2)];
-        const CImg<longT> *const p_end = ++mp.p_code + mp.opcode(4);
-        if (!value_left) { mp.p_code = p_end - 1; return 0; }
-        const unsigned int mem_right = (unsigned int)mp.opcode(3);
-        for ( ; mp.p_code<p_end; ++mp.p_code) {
-          cimg_test_abort();
-          const CImg<longT> &op = *mp.p_code;
-          mp.opcode._data = op._data; mp.opcode._height = op._height;
-          const unsigned int target = (unsigned int)mp.opcode[1];
-          mp.mem[target] = _cimg_mp_defunc(mp);
-        }
-        --mp.p_code;
-        return (double)(bool)mp.mem[mem_right];
-      }
+            if (!std::strncmp(ss,"cconj(",6)) { // Complex conjugate
+              _cimg_mp_op("Function 'cconj()'");
+              arg1 = compile(ss6,se1,depth1,0);
+              _cimg_mp_check_type(arg1,0,2,2);
+              pos = vector(2);
+              CImg<ulongT>::vector((ulongT)mp_complex_conj,pos,arg1).move_to(code);
+              _cimg_mp_return(pos);
+            }
 
-      static double mp_logical_or(_cimg_math_parser& mp) {
-        const bool value_left = (bool)mp.mem[mp.opcode(2)];
-        const CImg<longT> *const p_end = ++mp.p_code + mp.opcode(4);
-        if (value_left) { mp.p_code = p_end - 1; return 1; }
-        const unsigned int mem_right = (unsigned int)mp.opcode(3);
-        for ( ; mp.p_code<p_end; ++mp.p_code) {
-          cimg_test_abort();
-          const CImg<longT> &op = *mp.p_code;
-          mp.opcode._data = op._data; mp.opcode._height = op._height;
-          const unsigned int target = (unsigned int)mp.opcode[1];
-          mp.mem[target] = _cimg_mp_defunc(mp);
-        }
-        --mp.p_code;
-        return (double)(bool)mp.mem[mem_right];
-      }
+            if (!std::strncmp(ss,"cexp(",5)) { // Complex exponential
+              _cimg_mp_op("Function 'cexp()'");
+              arg1 = compile(ss5,se1,depth1,0);
+              _cimg_mp_check_type(arg1,0,2,2);
+              pos = vector(2);
+              CImg<ulongT>::vector((ulongT)mp_complex_exp,pos,arg1).move_to(code);
+              _cimg_mp_return(pos);
+            }
 
-      static double mp_infeq(_cimg_math_parser& mp) {
-        return (double)(mp.mem[mp.opcode(2)]<=mp.mem[mp.opcode(3)]);
-      }
+            if (!std::strncmp(ss,"clog(",5)) { // Complex logarithm
+              _cimg_mp_op("Function 'clog()'");
+              arg1 = compile(ss5,se1,depth1,0);
+              _cimg_mp_check_type(arg1,0,2,2);
+              pos = vector(2);
+              CImg<ulongT>::vector((ulongT)mp_complex_log,pos,arg1).move_to(code);
+              _cimg_mp_return(pos);
+            }
 
-      static double mp_supeq(_cimg_math_parser& mp) {
-        return (double)(mp.mem[mp.opcode(2)]>=mp.mem[mp.opcode(3)]);
-      }
+            if (!std::strncmp(ss,"copy(",5)) { // Memory copy
+              _cimg_mp_op("Function 'copy()'");
+              ref.assign(14);
+              s1 = ss5; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
+              arg1 = p1 = compile(ss5,s1,depth1,ref);
+              s2 = ++s1; while (s2<se1 && (*s2!=',' || level[s2 - expr._data]!=clevel1)) ++s2;
+              arg2 = compile(s1,s2,depth1,ref._data + 7);
+              arg3 = ~0U; arg4 = arg5 = 1;
+              if (s2<se1) {
+                s3 = ++s2; while (s3<se1 && (*s3!=',' || level[s3 - expr._data]!=clevel1)) ++s3;
+                arg3 = compile(s2,s3,depth1,0);
+                if (s3<se1) {
+                  s1 = ++s3; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
+                  arg4 = compile(s3,s1,depth1,0);
+                  arg5 = s1<se1?compile(++s1,se1,depth1,0):1;
+                }
+              }
+              if (_cimg_mp_is_vector(arg1) && !ref[0]) ++arg1;
+              if (_cimg_mp_is_vector(arg2)) {
+                if (arg3==~0U) arg3 = _cimg_mp_vector_size(arg2);
+                if (!ref[7]) ++arg2;
+              }
+              if (arg3==~0U) arg3 = 1;
+              _cimg_mp_check_type(arg3,3,1,0);
+              _cimg_mp_check_type(arg4,4,1,0);
+              _cimg_mp_check_type(arg5,5,1,0);
+              CImg<ulongT>(1,21).move_to(code);
+              code.back().get_shared_rows(0,6).fill((ulongT)mp_memcopy,p1,arg1,arg2,arg3,arg4,arg5);
+              code.back().get_shared_rows(7,20).fill(ref);
+              _cimg_mp_return(p1);
+            }
+
+            if (!std::strncmp(ss,"cos(",4)) { // Cosine
+              _cimg_mp_op("Function 'cos()'");
+              arg1 = compile(ss4,se1,depth1,0);
+              if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_cos,arg1);
+              if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::cos(mem[arg1]));
+              _cimg_mp_scalar1(mp_cos,arg1);
+            }
+
+            if (!std::strncmp(ss,"cosh(",5)) { // Hyperbolic cosine
+              _cimg_mp_op("Function 'cosh()'");
+              arg1 = compile(ss5,se1,depth1,0);
+              if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_cosh,arg1);
+              if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::cosh(mem[arg1]));
+              _cimg_mp_scalar1(mp_cosh,arg1);
+            }
+
+            if (!std::strncmp(ss,"crop(",5)) { // Image crop
+              _cimg_mp_op("Function 'crop()'");
+              if (*ss5=='#') { // Index specified
+                s0 = ss6; while (s0<se1 && (*s0!=',' || level[s0 - expr._data]!=clevel1)) ++s0;
+                p1 = compile(ss6,s0++,depth1,0);
+                _cimg_mp_check_list(false);
+              } else { p1 = ~0U; s0 = ss5; need_input_copy = true; }
+              pos = 0;
+              is_sth = false; // Coordinates specified as a vector?
+              if (ss5<se1) for (s = s0; s<se; ++s, ++pos) {
+                ns = s; while (ns<se && (*ns!=',' || level[ns - expr._data]!=clevel1) &&
+                               (*ns!=')' || level[ns - expr._data]!=clevel)) ++ns;
+                arg1 = compile(s,ns,depth1,0);
+                if (!pos && _cimg_mp_is_vector(arg1)) { // Coordinates specified as a vector
+                  opcode = CImg<ulongT>::sequence((ulongT)_cimg_mp_vector_size(arg1),arg1 + 1,
+                                                 arg1 + (ulongT)_cimg_mp_vector_size(arg1));
+                  opcode.resize(1,cimg::min(opcode._height,4U),1,1,0).move_to(_opcode);
+                  is_sth = true;
+                } else {
+                  _cimg_mp_check_type(arg1,pos + 1,1,0);
+                  CImg<ulongT>::vector(arg1).move_to(_opcode);
+                }
+                s = ns;
+              }
+              (_opcode>'y').move_to(opcode);
 
-      static double mp_noteq(_cimg_math_parser& mp) {
-        return (double)(mp.mem[mp.opcode(2)]!=mp.mem[mp.opcode(3)]);
-      }
+              arg1 = 0; arg2 = p1!=~0U?1:0;
+              switch (opcode._height) {
+              case 0 : case 1 :
+                CImg<ulongT>::vector(0,0,0,0,~0U,~0U,~0U,~0U,0).move_to(opcode);
+                break;
+              case 2 :
+                CImg<ulongT>::vector(*opcode,0,0,0,opcode[1],~0U,~0U,~0U,reserved_label[30]).move_to(opcode);
+                arg1 = arg2?3:2;
+                break;
+              case 3 :
+                CImg<ulongT>::vector(*opcode,0,0,0,opcode[1],~0U,~0U,~0U,opcode[2]).move_to(opcode);
+                arg1 = arg2?3:2;
+                break;
+              case 4 :
+                CImg<ulongT>::vector(*opcode,opcode[1],0,0,opcode[2],opcode[3],~0U,~0U,reserved_label[30]).
+                  move_to(opcode);
+                arg1 = (is_sth?2:1) + arg2;
+                break;
+              case 5 :
+                CImg<ulongT>::vector(*opcode,opcode[1],0,0,opcode[2],opcode[3],~0U,~0U,opcode[4]).
+                  move_to(opcode);
+                arg1 = (is_sth?2:1) + arg2;
+                break;
+              case 6 :
+                CImg<ulongT>::vector(*opcode,opcode[1],opcode[2],0,opcode[3],opcode[4],opcode[5],~0U,
+                                    reserved_label[30]).move_to(opcode);
+                arg1 = (is_sth?2:4) + arg2;
+                break;
+              case 7 :
+                CImg<ulongT>::vector(*opcode,opcode[1],opcode[2],0,opcode[3],opcode[4],opcode[5],~0U,
+                                    opcode[6]).move_to(opcode);
+                arg1 = (is_sth?2:4) + arg2;
+                break;
+              case 8 :
+                CImg<ulongT>::vector(*opcode,opcode[1],opcode[2],opcode[3],opcode[4],opcode[5],opcode[6],
+                                    opcode[7],reserved_label[30]).move_to(opcode);
+                arg1 = (is_sth?2:5) + arg2;
+                break;
+              case 9 :
+                arg1 = (is_sth?2:5) + arg2;
+                break;
+              default : // Error -> too much arguments
+                throw CImgArgumentException("[_cimg_math_parser] "
+                                            "CImg<%s>::%s: %s: Too much arguments specified, "
+                                            "in expression '%s%s%s'.",
+                                            pixel_type(),_cimg_mp_calling_function,s_op,
+                                            (ss - 4)>expr._data?"...":"",
+                                            (ss - 4)>expr._data?ss - 4:expr._data,
+                                            se<&expr.back()?"...":"");
+              }
+              _cimg_mp_check_type(*opcode,arg2 + 1,1,0);
+              _cimg_mp_check_type(opcode[1],arg2 + (is_sth?0:1),1,0);
+              _cimg_mp_check_type(opcode[2],arg2 + (is_sth?0:2),1,0);
+              _cimg_mp_check_type(opcode[3],arg2 + (is_sth?0:3),1,0);
+
+              if (opcode[4]!=(ulongT)~0U) {
+                _cimg_mp_check_constant(opcode[4],arg1,true);
+                opcode[4] = (ulongT)mem[opcode[4]];
+              }
+              if (opcode[5]!=(ulongT)~0U) {
+                _cimg_mp_check_constant(opcode[5],arg1 + 1,true);
+                opcode[5] = (ulongT)mem[opcode[5]];
+              }
+              if (opcode[6]!=(ulongT)~0U) {
+                _cimg_mp_check_constant(opcode[6],arg1 + 2,true);
+                opcode[6] = (ulongT)mem[opcode[6]];
+              }
+              if (opcode[7]!=(ulongT)~0U) {
+                _cimg_mp_check_constant(opcode[7],arg1 + 3,true);
+                opcode[7] = (ulongT)mem[opcode[7]];
+              }
+              _cimg_mp_check_type(opcode[8],arg1 + 4,1,0);
 
-      static double mp_eqeq(_cimg_math_parser& mp) {
-        return (double)(mp.mem[mp.opcode(2)]==mp.mem[mp.opcode(3)]);
-      }
+              if (opcode[4]==(ulongT)~0U || opcode[5]==(ulongT)~0U ||
+                  opcode[6]==(ulongT)~0U || opcode[7]==(ulongT)~0U) {
+                if (p1!=~0U) {
+                  _cimg_mp_check_constant(p1,1,false);
+                  p1 = (unsigned int)cimg::mod((int)mem[p1],listin.width());
+                }
+                const CImg<T> &img = p1!=~0U?listin[p1]:imgin;
+                if (!img)
+                  throw CImgArgumentException("[_cimg_math_parser] "
+                                              "CImg<%s>::%s: %s: Cannot crop empty image when "
+                                              "some xyzc-coordinates are unspecified, in expression '%s%s%s'.",
+                                              pixel_type(),_cimg_mp_calling_function,s_op,
+                                              (ss - 4)>expr._data?"...":"",
+                                              (ss - 4)>expr._data?ss - 4:expr._data,
+                                              se<&expr.back()?"...":"");
+                if (opcode[4]==(ulongT)~0U) opcode[4] = (ulongT)img._width;
+                if (opcode[5]==(ulongT)~0U) opcode[5] = (ulongT)img._height;
+                if (opcode[6]==(ulongT)~0U) opcode[6] = (ulongT)img._depth;
+                if (opcode[7]==(ulongT)~0U) opcode[7] = (ulongT)img._spectrum;
+              }
 
-      static double mp_inf(_cimg_math_parser& mp) {
-        return (double)(mp.mem[mp.opcode(2)]<mp.mem[mp.opcode(3)]);
-      }
+              pos = vector(opcode[4]*opcode[5]*opcode[6]*opcode[7]);
+              CImg<ulongT>::vector((ulongT)mp_crop,
+                                  pos,p1,
+                                  *opcode,opcode[1],opcode[2],opcode[3],
+                                  opcode[4],opcode[5],opcode[6],opcode[7],
+                                  opcode[8]).move_to(code);
+              _cimg_mp_return(pos);
+            }
 
-      static double mp_sup(_cimg_math_parser& mp) {
-        return (double)(mp.mem[mp.opcode(2)]>mp.mem[mp.opcode(3)]);
-      }
+            if (!std::strncmp(ss,"cross(",6)) { // Cross product
+              _cimg_mp_op("Function 'cross()'");
+              s1 = ss6; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
+              arg1 = compile(ss6,s1,depth1,0);
+              arg2 = compile(++s1,se1,depth1,0);
+              _cimg_mp_check_type(arg1,1,2,3);
+              _cimg_mp_check_type(arg2,2,2,3);
+              pos = vector(3);
+              CImg<ulongT>::vector((ulongT)mp_cross,pos,arg1,arg2).move_to(code);
+              _cimg_mp_return(pos);
+            }
 
-      static double mp_add(_cimg_math_parser& mp) {
-        return mp.mem[mp.opcode(2)] + mp.mem[mp.opcode(3)];
-      }
+            if (!std::strncmp(ss,"cut(",4)) { // Cut
+              _cimg_mp_op("Function 'cut()'");
+              s1 = ss4; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
+              arg1 = compile(ss4,s1,depth1,0);
+              s2 = s1 + 1; while (s2<se1 && (*s2!=',' || level[s2 - expr._data]!=clevel1)) ++s2;
+              arg2 = compile(++s1,s2,depth1,0);
+              arg3 = compile(++s2,se1,depth1,0);
+              if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector3_vss(mp_cut,arg1,arg2,arg3);
+              if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2) && _cimg_mp_is_constant(arg3)) {
+                val = mem[arg1];
+                val1 = mem[arg2];
+                val2 = mem[arg3];
+                _cimg_mp_constant(val<val1?val1:val>val2?val2:val);
+              }
+              _cimg_mp_scalar3(mp_cut,arg1,arg2,arg3);
+            }
+            break;
 
-      static double mp_sub(_cimg_math_parser& mp) {
-        return mp.mem[mp.opcode(2)] - mp.mem[mp.opcode(3)];
-      }
+          case 'd' :
+            if (!std::strncmp(ss,"date(",5)) { // Date and file date
+              _cimg_mp_op("Function 'date()'");
+              s1 = ss5; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
+              arg1 = 0;
+              is_sth = s1!=se1; // is_fdate
+              if (s1==se1 && ss5!=se1 && // Exactly one argument
+                  (cimg_sscanf(ss5,"%u%c",&arg1,&sep)!=2 || sep!=')')) is_sth = true;
+              if (is_sth) {
+                if (cimg_sscanf(ss5,"%u%c",&arg1,&sep)!=2 || sep!=',') { arg1 = 0; s1 = ss4; }
+                *se1 = 0; val = (double)cimg::fdate(++s1,arg1); *se1 = ')';
+              } else val = (double)cimg::date(arg1);
+              _cimg_mp_constant(val);
+            }
+
+            if (!std::strncmp(ss,"debug(",6)) { // Print debug info
+              _cimg_mp_op("Function 'debug()'");
+              p1 = code._width;
+              arg1 = compile(ss6,se1,depth1,p_ref);
+              *se1 = 0;
+              ((CImg<ulongT>::vector((ulongT)mp_debug,arg1,code._width - p1),
+                CImg<ulongT>::string(ss6).unroll('y'))>'y').move_to(code,p1);
+              *se1 = ')';
+              _cimg_mp_return(arg1);
+            }
 
-      static double mp_mul(_cimg_math_parser& mp) {
-        const double value_left = mp.mem[mp.opcode(2)];
-        const CImg<longT> *const p_end = ++mp.p_code + mp.opcode(4);
-        if (!value_left) { mp.p_code = p_end - 1; return 0; }
-        const unsigned int mem_right = (unsigned int)mp.opcode(3);
-        for ( ; mp.p_code<p_end; ++mp.p_code) {
-          cimg_test_abort();
-          const CImg<longT> &op = *mp.p_code;
-          mp.opcode._data = op._data; mp.opcode._height = op._height;
-          const unsigned int target = (unsigned int)mp.opcode[1];
-          mp.mem[target] = _cimg_mp_defunc(mp);
-        }
-        --mp.p_code;
-        return value_left*(double)mp.mem[mem_right];
-      }
+            if (!std::strncmp(ss,"det(",4)) { // Matrix determinant
+              _cimg_mp_op("Function 'det()'");
+              arg1 = compile(ss4,se1,depth1,0);
+              _cimg_mp_check_matrix_square(arg1,1);
+              p1 = (unsigned int)std::sqrt((float)_cimg_mp_vector_size(arg1));
+              _cimg_mp_scalar2(mp_det,arg1,p1);
+            }
 
-      static double mp_div(_cimg_math_parser& mp) {
-        return mp.mem[mp.opcode(2)] / mp.mem[mp.opcode(3)];
-      }
+            if (!std::strncmp(ss,"diag(",5)) { // Diagonal matrix
+              _cimg_mp_op("Function 'diag()'");
+              arg1 = compile(ss5,se1,depth1,0);
+              _cimg_mp_check_type(arg1,1,2,0);
+              p1 = _cimg_mp_vector_size(arg1);
+              pos = vector(p1*p1);
+              CImg<ulongT>::vector((ulongT)mp_diag,pos,arg1,p1).move_to(code);
+              _cimg_mp_return(pos);
+            }
 
-      static double mp_minus(_cimg_math_parser& mp) {
-        return -mp.mem[mp.opcode(2)];
-      }
+            if (!std::strncmp(ss,"dot(",4)) { // Dot product
+              _cimg_mp_op("Function 'dot()'");
+              s1 = ss4; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
+              arg1 = compile(ss4,s1,depth1,0);
+              arg2 = compile(++s1,se1,depth1,0);
+              _cimg_mp_check_type(arg1,1,2,0);
+              _cimg_mp_check_type(arg2,2,2,0);
+              if (_cimg_mp_is_vector(arg1)) _cimg_mp_scalar3(mp_dot,arg1,arg2,_cimg_mp_vector_size(arg1));
+              _cimg_mp_scalar2(mp_mul,arg1,arg2);
+            }
+
+            if (!std::strncmp(ss,"dowhile",7) && (*ss7=='(' || (*ss7 && *ss7<=' ' && *ss8=='('))) { // Do..while
+              _cimg_mp_op("Function 'dowhile()'");
+              if (*ss7<=' ') cimg::swap(*ss7,*ss8); // Allow space before opening brace
+              s1 = ss8; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
+              p1 = code._width;
+              arg1 = compile(ss8,s1,depth1,0);
+              arg2 = s1<se1?compile(++s1,se1,depth1,0):arg1;
+              _cimg_mp_check_type(arg2,2,1,0);
+              CImg<ulongT>::vector((ulongT)mp_dowhile,arg1,arg2,code._width - p1).move_to(code,p1);
+              _cimg_mp_return(arg1);
+            }
+
+            if (!std::strncmp(ss,"draw(",5)) { // Draw image
+              _cimg_mp_op("Function 'draw()'");
+              is_parallelizable = false;
+              if (*ss5=='#') { // Index specified
+                s0 = ss6; while (s0<se1 && (*s0!=',' || level[s0 - expr._data]!=clevel1)) ++s0;
+                p1 = compile(ss6,s0++,depth1,0);
+                _cimg_mp_check_list(true);
+              } else { p1 = ~0U; s0 = ss5; }
+              s1 = s0; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
+              arg1 = compile(s0,s1,depth1,0);
+              arg2 = is_relative?0U:(unsigned int)_cimg_mp_x;
+              arg3 = is_relative?0U:(unsigned int)_cimg_mp_y;
+              arg4 = is_relative?0U:(unsigned int)_cimg_mp_z;
+              arg5 = is_relative?0U:(unsigned int)_cimg_mp_c;
+              if (s1<se1) {
+                s0 = s1 + 1; while (s0<se1 && (*s0!=',' || level[s0 - expr._data]!=clevel1)) ++s0;
+                arg2 = compile(++s1,s0,depth1,0);
+                if (_cimg_mp_is_vector(arg2)) { // Coordinates specified as a vector
+                  p2 = _cimg_mp_vector_size(arg2);
+                  ++arg2;
+                  if (p2>1) {
+                    arg3 = arg2 + 1;
+                    if (p2>2) {
+                      arg4 = arg3 + 1;
+                      if (p2>3) arg5 = arg4 + 1;
+                    }
+                  }
+                  ++s0;
+                  is_sth = true;
+                } else {
+                  if (s0<se1) {
+                    is_sth = p1!=~0U;
+                    s1 = s0 + 1; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
+                    arg3 = compile(++s0,s1,depth1,0);
+                    _cimg_mp_check_type(arg3,is_sth?4:3,1,0);
+                    if (s1<se1) {
+                      s0 = s1 + 1; while (s0<se1 && (*s0!=',' || level[s0 - expr._data]!=clevel1)) ++s0;
+                      arg4 = compile(++s1,s0,depth1,0);
+                      _cimg_mp_check_type(arg4,is_sth?5:4,1,0);
+                      if (s0<se1) {
+                        s1 = s0 + 1; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
+                        arg5 = compile(++s0,s1,depth1,0);
+                        _cimg_mp_check_type(arg5,is_sth?6:5,1,0);
+                        s0 = ++s1;
+                      }
+                    }
+                  }
+                  is_sth = false;
+                }
+              }
 
-      static double mp_logical_not(_cimg_math_parser& mp) {
-        return !mp.mem[mp.opcode(2)];
-      }
+              CImg<ulongT>::vector((ulongT)mp_draw,arg1,p1,arg2,arg3,arg4,arg5,0,0,0,0,1,(ulongT)-1,0,1).
+                move_to(opcode);
+
+              arg2 = arg3 = arg4 = arg5 = ~0U;
+              p2 = p1!=~0U?0:1;
+              if (s0<se1) {
+                s1 = s0; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
+                arg2 = compile(s0,s1,depth1,0);
+                _cimg_mp_check_constant(arg2,p2 + (is_sth?3:6),true);
+                arg2 = (unsigned int)mem[arg2];
+                if (s1<se1) {
+                  s0 = s1 + 1; while (s0<se1 && (*s0!=',' || level[s0 - expr._data]!=clevel1)) ++s0;
+                  arg3 = compile(++s1,s0,depth1,0);
+                  _cimg_mp_check_constant(arg3,p2 + (is_sth?4:7),true);
+                  arg3 = (unsigned int)mem[arg3];
+                  if (s0<se1) {
+                    s1 = s0 + 1; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
+                    arg4 = compile(++s0,s1,depth1,0);
+                    _cimg_mp_check_constant(arg4,p2 + (is_sth?5:8),true);
+                    arg4 = (unsigned int)mem[arg4];
+                    if (s1<se1) {
+                      s0 = s1 + 1; while (s0<se1 && (*s0!=',' || level[s0 - expr._data]!=clevel1)) ++s0;
+                      arg5 = compile(++s1,s0,depth1,0);
+                      _cimg_mp_check_constant(arg5,p2 + (is_sth?6:9),true);
+                      arg5 = (unsigned int)mem[arg5];
+                    }
+                  }
+                }
+              }
+              if (s0<s1) s0 = s1;
+              if (arg2==~0U || arg3==~0U || arg4==~0U || arg5==~0U) {
+                if (p1!=~0U) {
+                  _cimg_mp_check_constant(p1,1,false);
+                  p1 = (unsigned int)cimg::mod((int)mem[p1],listout.width());
+                }
+                const CImg<T> &img = p1!=~0U?listout[p1]:imgout;
+                if (arg2==~0U) arg2 = img._width;
+                if (arg3==~0U) arg3 = img._height;
+                if (arg4==~0U) arg4 = img._depth;
+                if (arg5==~0U) arg5 = img._spectrum;
+              }
+              if (arg2*arg3*arg4*arg5!=_cimg_mp_vector_size(arg1)) {
+                *se = saved_char; cimg::strellipsize(expr,64);
+                throw CImgArgumentException("[_cimg_math_parser] "
+                                            "CImg<%s>::%s: %s: Type of %s argument ('%s') and specified size "
+                                            "(%u,%u,%u,%u) do not match, in expression '%s%s%s'.",
+                                            pixel_type(),_cimg_mp_calling_function,s_op,
+                                            p1==~0U?"first":"second",s_type(arg1)._data,
+                                            arg2,arg3,arg4,arg5,
+                                            (ss - 4)>expr._data?"...":"",
+                                            (ss - 4)>expr._data?ss - 4:expr._data,
+                                            se<&expr.back()?"...":"");
+              }
+              opcode[7] = (ulongT)arg2;
+              opcode[8] = (ulongT)arg3;
+              opcode[9] = (ulongT)arg4;
+              opcode[10] = (ulongT)arg5;
+
+              if (s0<se1) {
+                s1 = s0 + 1; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
+                arg6 = compile(++s0,s1,depth1,0);
+                _cimg_mp_check_type(arg6,0,1,0);
+                opcode[11] = arg6;
+                if (s1<se1) {
+                  s0 = s1 + 1; while (s0<se1 && (*s0!=',' || level[s0 - expr._data]!=clevel1)) ++s0;
+                  p2 = compile(++s1,s0,depth1,0);
+                  _cimg_mp_check_type(p2,0,2,0);
+                  if (arg2*arg3*arg4%_cimg_mp_vector_size(p2)) {
+                    *se = saved_char; cimg::strellipsize(expr,64);
+                    throw CImgArgumentException("[_cimg_math_parser] "
+                                                "CImg<%s>::%s: %s: Type of opacity mask ('%s') and specified size "
+                                                "(%u,%u,%u,%u) do not match, in expression '%s%s%s'.",
+                                                pixel_type(),_cimg_mp_calling_function,s_op,
+                                                s_type(p2)._data,
+                                                arg2,arg3,arg4,arg5,
+                                                (ss - 4)>expr._data?"...":"",
+                                                (ss - 4)>expr._data?ss - 4:expr._data,
+                                                se<&expr.back()?"...":"");
+                  }
+                  opcode[12] = p2;
+                  opcode[13] = _cimg_mp_vector_size(p2)/(arg2*arg3*arg4);
+                  p3 = s0<se1?compile(++s0,se1,depth1,0):1;
+                  _cimg_mp_check_type(p3,0,1,0);
+                  opcode[14] = p3;
+                }
+              }
+              opcode.move_to(code);
+              _cimg_mp_return(arg1);
+            }
+            break;
 
-      static double mp_bitwise_not(_cimg_math_parser& mp) {
-        return ~(unsigned long)mp.mem[mp.opcode(2)];
-      }
+          case 'e' :
+            if (!std::strncmp(ss,"eig(",4)) { // Matrix eigenvalues/eigenvector
+              _cimg_mp_op("Function 'eig()'");
+              arg1 = compile(ss4,se1,depth1,0);
+              _cimg_mp_check_matrix_square(arg1,1);
+              p1 = (unsigned int)std::sqrt((float)_cimg_mp_vector_size(arg1));
+              pos = vector((p1 + 1)*p1);
+              CImg<ulongT>::vector((ulongT)mp_eig,pos,arg1,p1).move_to(code);
+              _cimg_mp_return(pos);
+            }
 
-      static double mp_modulo(_cimg_math_parser& mp) {
-        return cimg::mod(mp.mem[mp.opcode(2)],mp.mem[mp.opcode(3)]);
-      }
+            if (!std::strncmp(ss,"exp(",4)) { // Exponential
+              _cimg_mp_op("Function 'exp()'");
+              arg1 = compile(ss4,se1,depth1,0);
+              if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_exp,arg1);
+              if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::exp(mem[arg1]));
+              _cimg_mp_scalar1(mp_exp,arg1);
+            }
 
-      static double mp_bitwise_and(_cimg_math_parser& mp) {
-        return ((unsigned long)mp.mem[mp.opcode(2)] & (unsigned long)mp.mem[mp.opcode(3)]);
-      }
+            if (!std::strncmp(ss,"eye(",4)) { // Identity matrix
+              _cimg_mp_op("Function 'eye()'");
+              arg1 = compile(ss4,se1,depth1,0);
+              _cimg_mp_check_constant(arg1,1,true);
+              p1 = (unsigned int)mem[arg1];
+              pos = vector(p1*p1);
+              CImg<ulongT>::vector((ulongT)mp_eye,pos,p1).move_to(code);
+              _cimg_mp_return(pos);
+            }
+            break;
 
-      static double mp_bitwise_or(_cimg_math_parser& mp) {
-        return ((unsigned long)mp.mem[mp.opcode(2)] | (unsigned long)mp.mem[mp.opcode(3)]);
-      }
+          case 'f' :
+            if (*ss1=='o' && *ss2=='r' && (*ss3=='(' || (*ss3 && *ss3<=' ' && *ss4=='('))) { // For loop
+              _cimg_mp_op("Function 'for()'");
+              if (*ss3<=' ') cimg::swap(*ss3,*ss4); // Allow space before opening brace
+              s1 = ss4; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
+              s2 = s1 + 1; while (s2<se1 && (*s2!=',' || level[s2 - expr._data]!=clevel1)) ++s2;
+              s3 = s2 + 1; while (s3<se1 && (*s3!=',' || level[s3 - expr._data]!=clevel1)) ++s3;
+              compile(ss4,s1,depth1,0);
+              p1 = code._width;
+              arg1 = compile(++s1,s2,depth1,0);
+              p2 = code._width;
+              if (s3<se1) { pos = compile(s3 + 1,se1,depth1,0); compile(++s2,s3,depth1,0); } // Body + proc
+              else pos = compile(++s2,se1,depth1,0); // Proc only
+              _cimg_mp_check_type(arg1,2,1,0);
+              arg2 = _cimg_mp_is_vector(pos)?_cimg_mp_vector_size(pos):0; // Output vector size (or 0 if scalar)
+              CImg<ulongT>::vector((ulongT)mp_whiledo,pos,arg1,p2 - p1,code._width - p2,arg2).move_to(code,p1);
+              _cimg_mp_return(pos);
+            }
+            break;
 
-      static double mp_pow(_cimg_math_parser& mp) {
-        const double v = mp.mem[mp.opcode(2)], p = mp.mem[mp.opcode(3)];
-        if (p==0) return 1;
-        if (p==0.5) return std::sqrt(v);
-        if (p==1) return v;
-        if (p==2) return v*v;
-        if (p==3) return v*v*v;
-        if (p==4) return v*v*v*v;
-        return std::pow(v,p);
-      }
+          case 'g' :
+            if (!std::strncmp(ss,"gauss(",6)) { // Gaussian function
+              _cimg_mp_op("Function 'gauss()'");
+              s1 = ss6; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
+              arg1 = compile(ss6,s1,depth1,0);
+              arg2 = s1<se1?compile(++s1,se1,depth1,0):1;
+              _cimg_mp_check_type(arg2,2,1,0);
+              if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector2_vs(mp_gauss,arg1,arg2);
+              if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) {
+                val1 = mem[arg1];
+                val2 = mem[arg2];
+                _cimg_mp_constant(std::exp(-val1*val1/(2*val2*val2))/std::sqrt(2*val2*val2*cimg::PI));
+              }
+              _cimg_mp_scalar2(mp_gauss,arg1,arg2);
+            }
+            break;
 
-      static double mp_sin(_cimg_math_parser& mp) {
-        return std::sin(mp.mem[mp.opcode(2)]);
-      }
+          case 'h' :
+            if (!std::strncmp(ss,"hypot(",6)) { // Hypothenuse
+              _cimg_mp_op("Function 'hypot()'");
+              s1 = ss6; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
+              arg1 = compile(ss6,s1,depth1,0);
+              arg2 = compile(++s1,se1,depth1,0);
+              _cimg_mp_check_type(arg1,1,1,0);
+              _cimg_mp_check_type(arg2,2,1,0);
+              if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) {
+                val1 = cimg::abs(mem[arg1]);
+                val2 = cimg::abs(mem[arg2]);
+                if (val1<val2) { val = val1; val1 = val2; } else val = val2;
+                if (val1>0) { val/=val1; _cimg_mp_constant(val1*std::sqrt(1+val*val)); }
+                _cimg_mp_constant(0);
+              }
+              _cimg_mp_scalar2(mp_hypot,arg1,arg2);
+            }
+            break;
 
-      static double mp_cos(_cimg_math_parser& mp) {
-        return std::cos(mp.mem[mp.opcode(2)]);
-      }
+          case 'i' :
+            if (*ss1=='f' && (*ss2=='(' || (*ss2 && *ss2<=' ' && *ss3=='('))) { // If..then[..else.]
+              _cimg_mp_op("Function 'if()'");
+              if (*ss2<=' ') cimg::swap(*ss2,*ss3); // Allow space before opening brace
+              s1 = ss3; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
+              s2 = s1 + 1; while (s2<se1 && (*s2!=',' || level[s2 - expr._data]!=clevel1)) ++s2;
+              arg1 = compile(ss3,s1,depth1,0);
+              _cimg_mp_check_type(arg1,1,1,0);
+              if (_cimg_mp_is_constant(arg1)) {
+                if ((bool)mem[arg1]) return compile(++s1,s2,depth1,0);
+                else return s2<se1?compile(++s2,se1,depth1,0):0;
+              }
+              p2 = code._width;
+              arg2 = compile(++s1,s2,depth1,0);
+              p3 = code._width;
+              arg3 = s2<se1?compile(++s2,se1,depth1,0):_cimg_mp_is_vector(arg2)?vector(_cimg_mp_vector_size(arg2),0):0;
+              _cimg_mp_check_type(arg3,3,_cimg_mp_is_vector(arg2)?2:1,_cimg_mp_vector_size(arg2));
+              arg4 = _cimg_mp_is_vector(arg2)?_cimg_mp_vector_size(arg2):0; // Output vector size (or 0 if scalar)
+              if (arg4) pos = vector(arg4); else pos = scalar();
+              CImg<ulongT>::vector((ulongT)mp_if,pos,arg1,arg2,arg3,
+                                  p3 - p2,code._width - p3,arg4).move_to(code,p2);
+              _cimg_mp_return(pos);
+            }
 
-      static double mp_tan(_cimg_math_parser& mp) {
-        return std::tan(mp.mem[mp.opcode(2)]);
-      }
+            if (!std::strncmp(ss,"init(",5)) { // Init
+              _cimg_mp_op("Function 'init()'");
+              if (ss0!=expr._data || code.width()) { // (only allowed as the first instruction)
+                *se = saved_char; cimg::strellipsize(expr,64);
+                throw CImgArgumentException("[_cimg_math_parser] "
+                                            "CImg<%s>::%s: %s: Init invokation not done at the "
+                                            "beginning of expression '%s%s%s'.",
+                                            pixel_type(),_cimg_mp_calling_function,s_op,
+                                            (ss - 4)>expr._data?"...":"",
+                                            (ss - 4)>expr._data?ss - 4:expr._data,
+                                            se<&expr.back()?"...":"");
+              }
+              arg1 = compile(ss5,se1,depth1,p_ref);
+              init_size = code.width();
+              _cimg_mp_return(arg1);
+            }
+
+            if (!std::strncmp(ss,"int(",4)) { // Integer cast
+              _cimg_mp_op("Function 'int()'");
+              arg1 = compile(ss4,se1,depth1,0);
+              if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_int,arg1);
+              if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant((longT)mem[arg1]);
+              _cimg_mp_scalar1(mp_int,arg1);
+            }
+
+            if (!std::strncmp(ss,"inv(",4)) { // Matrix/scalar inversion
+              _cimg_mp_op("Function 'inv()'");
+              arg1 = compile(ss4,se1,depth1,0);
+              _cimg_mp_check_matrix_square(arg1,1);
+              p1 = (unsigned int)std::sqrt((float)_cimg_mp_vector_size(arg1));
+              pos = vector(p1*p1);
+              CImg<ulongT>::vector((ulongT)mp_inv,pos,arg1,p1).move_to(code);
+              _cimg_mp_return(pos);
+            }
 
-      static double mp_asin(_cimg_math_parser& mp) {
-        return std::asin(mp.mem[mp.opcode(2)]);
-      }
+            if (*ss1=='s') { // Family of 'is_?()' functions
 
-      static double mp_acos(_cimg_math_parser& mp) {
-        return std::acos(mp.mem[mp.opcode(2)]);
-      }
+              if (!std::strncmp(ss,"isbool(",7)) { // Is boolean?
+                _cimg_mp_op("Function 'isbool()'");
+                if (ss7==se1) _cimg_mp_return(0);
+                arg1 = compile(ss7,se1,depth1,0);
+                if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_isbool,arg1);
+                if (_cimg_mp_is_constant(arg1)) _cimg_mp_return(mem[arg1]==0.0 || mem[arg1]==1.0);
+                _cimg_mp_scalar1(mp_isbool,arg1);
+              }
 
-      static double mp_atan(_cimg_math_parser& mp) {
-        return std::atan(mp.mem[mp.opcode(2)]);
-      }
+              if (!std::strncmp(ss,"isdir(",6)) { // Is directory?
+                _cimg_mp_op("Function 'isdir()'");
+                *se1 = 0;
+                is_sth = cimg::is_directory(ss6);
+                *se1 = ')';
+                _cimg_mp_return(is_sth?1U:0U);
+              }
 
-      static double mp_sinh(_cimg_math_parser& mp) {
-        return std::sinh(mp.mem[mp.opcode(2)]);
-      }
+              if (!std::strncmp(ss,"isfile(",7)) { // Is file?
+                _cimg_mp_op("Function 'isfile()'");
+                *se1 = 0;
+                is_sth = cimg::is_file(ss7);
+                *se1 = ')';
+                _cimg_mp_return(is_sth?1U:0U);
+              }
 
-      static double mp_cosh(_cimg_math_parser& mp) {
-        return std::cosh(mp.mem[mp.opcode(2)]);
-      }
+              if (!std::strncmp(ss,"isin(",5)) { // Is in sequence/vector?
+                if (ss5>=se1) _cimg_mp_return(0);
+                _cimg_mp_op("Function 'isin()'");
+                pos = scalar();
+                CImg<ulongT>::vector((ulongT)mp_isin,pos).move_to(_opcode);
+                for (s = ss5; s<se; ++s) {
+                  ns = s; while (ns<se && (*ns!=',' || level[ns - expr._data]!=clevel1) &&
+                                 (*ns!=')' || level[ns - expr._data]!=clevel)) ++ns;
+                  arg1 = compile(s,ns,depth1,0);
+                  if (_cimg_mp_is_vector(arg1))
+                    CImg<ulongT>::sequence((ulongT)_cimg_mp_vector_size(arg1),arg1 + 1,
+                                          arg1 + (ulongT)_cimg_mp_vector_size(arg1)).
+                      move_to(_opcode);
+                  else CImg<ulongT>::vector(arg1).move_to(_opcode);
+                  s = ns;
+                }
+                (_opcode>'y').move_to(code);
+                _cimg_mp_return(pos);
+              }
 
-      static double mp_tanh(_cimg_math_parser& mp) {
-        return std::tanh(mp.mem[mp.opcode(2)]);
-      }
+              if (!std::strncmp(ss,"isinf(",6)) { // Is infinite?
+                _cimg_mp_op("Function 'isinf()'");
+                if (ss6==se1) _cimg_mp_return(0);
+                arg1 = compile(ss6,se1,depth1,0);
+                if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_isinf,arg1);
+                if (_cimg_mp_is_constant(arg1)) _cimg_mp_return((unsigned int)cimg::type<double>::is_inf(mem[arg1]));
+                _cimg_mp_scalar1(mp_isinf,arg1);
+              }
 
-      static double mp_log10(_cimg_math_parser& mp) {
-        return std::log10(mp.mem[mp.opcode(2)]);
-      }
+              if (!std::strncmp(ss,"isint(",6)) { // Is integer?
+                _cimg_mp_op("Function 'isint()'");
+                if (ss6==se1) _cimg_mp_return(0);
+                arg1 = compile(ss6,se1,depth1,0);
+                if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_isint,arg1);
+                if (_cimg_mp_is_constant(arg1)) _cimg_mp_return((unsigned int)(cimg::mod(mem[arg1],1.0)==0));
+                _cimg_mp_scalar1(mp_isint,arg1);
+              }
 
-      static double mp_log2(_cimg_math_parser& mp) {
-        return cimg::log2(mp.mem[mp.opcode(2)]);
-      }
+              if (!std::strncmp(ss,"isnan(",6)) { // Is NaN?
+                _cimg_mp_op("Function 'isnan()'");
+                if (ss6==se1) _cimg_mp_return(0);
+                arg1 = compile(ss6,se1,depth1,0);
+                if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_isnan,arg1);
+                if (_cimg_mp_is_constant(arg1)) _cimg_mp_return((unsigned int)cimg::type<double>::is_nan(mem[arg1]));
+                _cimg_mp_scalar1(mp_isnan,arg1);
+              }
 
-      static double mp_log(_cimg_math_parser& mp) {
-        return std::log(mp.mem[mp.opcode(2)]);
-      }
+              if (!std::strncmp(ss,"isval(",6)) { // Is value?
+                _cimg_mp_op("Function 'isval()'");
+                val = 0;
+                if (cimg_sscanf(ss6,"%lf%c%c",&val,&sep,&end)==2 && sep==')') _cimg_mp_return(1);
+                _cimg_mp_return(0);
+              }
 
-      static double mp_exp(_cimg_math_parser& mp) {
-        return std::exp(mp.mem[mp.opcode(2)]);
-      }
+            }
+            break;
 
-      static double mp_sqr(_cimg_math_parser& mp) {
-        return cimg::sqr(mp.mem[mp.opcode(2)]);
+          case 'l' :
+            if (!std::strncmp(ss,"log(",4)) { // Natural logarithm
+              _cimg_mp_op("Function 'log()'");
+              arg1 = compile(ss4,se1,depth1,0);
+              if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_log,arg1);
+              if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::log(mem[arg1]));
+              _cimg_mp_scalar1(mp_log,arg1);
+            }
+
+            if (!std::strncmp(ss,"log2(",5)) { // Base-2 logarithm
+              _cimg_mp_op("Function 'log2()'");
+              arg1 = compile(ss5,se1,depth1,0);
+              if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_log2,arg1);
+              if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(cimg::log2(mem[arg1]));
+              _cimg_mp_scalar1(mp_log2,arg1);
+            }
+
+            if (!std::strncmp(ss,"log10(",6)) { // Base-10 logarithm
+              _cimg_mp_op("Function 'log10()'");
+              arg1 = compile(ss6,se1,depth1,0);
+              if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_log10,arg1);
+              if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::log10(mem[arg1]));
+              _cimg_mp_scalar1(mp_log10,arg1);
+            }
+            break;
+
+          case 'm' :
+            if (!std::strncmp(ss,"mul(",4)) { // Matrix multiplication
+              _cimg_mp_op("Function 'mul()'");
+              s1 = ss4; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
+              arg1 = compile(ss4,s1,depth1,0);
+              s2 = s1 + 1; while (s2<se1 && (*s2!=',' || level[s2 - expr._data]!=clevel1)) ++s2;
+              arg2 = compile(++s1,s2,depth1,0);
+              arg3 = s2<se1?compile(++s2,se1,depth1,0):1;
+              _cimg_mp_check_type(arg1,1,2,0);
+              _cimg_mp_check_type(arg2,2,2,0);
+              _cimg_mp_check_constant(arg3,3,true);
+              p1 = _cimg_mp_vector_size(arg1);
+              p2 = _cimg_mp_vector_size(arg2);
+              p3 = (unsigned int)mem[arg3];
+              arg5 = p2/p3;
+              arg4 = p1/arg5;
+              if (arg4*arg5!=p1 || arg5*p3!=p2) {
+                *se = saved_char; cimg::strellipsize(expr,64);
+                throw CImgArgumentException("[_cimg_math_parser] "
+                                            "CImg<%s>::%s: %s: Types of first and second arguments ('%s' and '%s') "
+                                            "do not match for third argument 'nb_colsB=%u', "
+                                            "in expression '%s%s%s'.",
+                                            pixel_type(),_cimg_mp_calling_function,s_op,
+                                            s_type(arg1)._data,s_type(arg2)._data,p3,
+                                            (ss - 4)>expr._data?"...":"",
+                                            (ss - 4)>expr._data?ss - 4:expr._data,
+                                            se<&expr.back()?"...":"");
+              }
+              pos = vector(arg4*p3);
+              CImg<ulongT>::vector((ulongT)mp_matrix_mul,pos,arg1,arg2,arg4,arg5,p3).move_to(code);
+              _cimg_mp_return(pos);
+            }
+            break;
+
+          case 'n' :
+            if (!std::strncmp(ss,"narg(",5)) { // Number of arguments
+              _cimg_mp_op("Function 'narg()'");
+              if (ss5>=se1) _cimg_mp_return(0);
+              arg1 = 0;
+              for (s = ss5; s<se; ++s) {
+                ns = s; while (ns<se && (*ns!=',' || level[ns - expr._data]!=clevel1) &&
+                               (*ns!=')' || level[ns - expr._data]!=clevel)) ++ns;
+                ++arg1; s = ns;
+              }
+              _cimg_mp_constant(arg1);
+            }
+
+            if ((cimg_sscanf(ss,"norm%u%c",&(arg1=~0U),&sep)==2 && sep=='(') ||
+                !std::strncmp(ss,"norminf(",8)) { // Lp norm
+              _cimg_mp_op("Function 'normP()'");
+              pos = scalar();
+              switch (arg1) {
+              case 0 : CImg<ulongT>::vector((ulongT)mp_norm0,pos).move_to(_opcode); break;
+              case 1 : CImg<ulongT>::vector((ulongT)mp_norm1,pos).move_to(_opcode); break;
+              case 2 : CImg<ulongT>::vector((ulongT)mp_norm2,pos).move_to(_opcode); break;
+              case ~0U : CImg<ulongT>::vector((ulongT)mp_norminf,pos).move_to(_opcode); break;
+              default :
+                CImg<ulongT>::vector((ulongT)mp_normp,pos,(ulongT)(arg1==~0U?-1:(int)arg1)).
+                  move_to(_opcode);
+              }
+              for (s = std::strchr(ss5,'(') + 1; s<se; ++s) {
+                ns = s; while (ns<se && (*ns!=',' || level[ns - expr._data]!=clevel1) &&
+                               (*ns!=')' || level[ns - expr._data]!=clevel)) ++ns;
+                arg2 = compile(s,ns,depth1,0);
+                if (_cimg_mp_is_vector(arg2))
+                  CImg<ulongT>::sequence((ulongT)_cimg_mp_vector_size(arg2),arg2 + 1,
+                                        arg2 + (ulongT)_cimg_mp_vector_size(arg2)).
+                    move_to(_opcode);
+                else CImg<ulongT>::vector(arg2).move_to(_opcode);
+                s = ns;
+              }
+              (_opcode>'y').move_to(code);
+              _cimg_mp_return(pos);
+            }
+            break;
+
+          case 'p' :
+            if (!std::strncmp(ss,"print(",6)) { // Print expression
+              _cimg_mp_op("Function 'print()'");
+              pos = compile(ss6,se1,depth1,p_ref);
+              *se1 = 0;
+              if (_cimg_mp_is_vector(pos)) // Vector
+                ((CImg<ulongT>::vector((ulongT)mp_vector_print,pos,(ulongT)_cimg_mp_vector_size(pos)),
+                  CImg<ulongT>::string(ss6).unroll('y'))>'y').move_to(code);
+              else // Scalar
+                ((CImg<ulongT>::vector((ulongT)mp_print,pos),
+                  CImg<ulongT>::string(ss6).unroll('y'))>'y').move_to(code);
+              *se1 = ')';
+              _cimg_mp_return(pos);
+            }
+            break;
+
+          case 'r' :
+            if (!std::strncmp(ss,"rol(",4) || !std::strncmp(ss,"ror(",4)) { // Bitwise rotation
+              _cimg_mp_op(ss[2]=='l'?"Function 'rol()'":"Function 'ror()'");
+              s1 = ss4; while (s1<se1 && (*s1!=',' || level[s1-expr._data]!=clevel1)) ++s1;
+              arg1 = compile(ss4,s1,depth1,0);
+              arg2 = s1<se1?compile(++s1,se1,depth1,0):1;
+              _cimg_mp_check_type(arg2,2,1,0);
+              if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector2_vs(*ss2=='l'?mp_rol:mp_ror,arg1,arg2);
+              if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2))
+                _cimg_mp_constant(*ss2=='l'?cimg::rol(mem[arg1],(unsigned int)mem[arg2]):
+                                  cimg::ror(mem[arg1],(unsigned int)mem[arg2]));
+              _cimg_mp_scalar2(*ss2=='l'?mp_rol:mp_ror,arg1,arg2);
+            }
+
+            if (!std::strncmp(ss,"rot(",4)) { // 2d/3d rotation matrix
+              _cimg_mp_op("Function 'rot()'");
+              s1 = ss4; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
+              arg1 = compile(ss4,s1,depth1,0);
+              if (s1<se1) { // 3d rotation
+                _cimg_mp_check_type(arg1,1,3,3);
+                is_sth = false; // Is coordinates as vector?
+                if (_cimg_mp_is_vector(arg1)) { // Coordinates specified as a vector
+                  is_sth = true;
+                  p2 = _cimg_mp_vector_size(arg1);
+                  ++arg1;
+                  arg2 = arg3 = 0;
+                  if (p2>1) {
+                    arg2 = arg1 + 1;
+                    if (p2>2) arg3 = arg2 + 1;
+                  }
+                  arg4 = compile(++s1,se1,depth1,0);
+                } else {
+                  s2 = s1 + 1; while (s2<se1 && (*s2!=',' || level[s2 - expr._data]!=clevel1)) ++s2;
+                  arg2 = compile(++s1,s2,depth1,0);
+                  s3 = s2 + 1; while (s3<se1 && (*s3!=',' || level[s3 - expr._data]!=clevel1)) ++s3;
+                  arg3 = compile(++s2,s3,depth1,0);
+                  arg4 = compile(++s3,se1,depth1,0);
+                  _cimg_mp_check_type(arg2,2,1,0);
+                  _cimg_mp_check_type(arg3,3,1,0);
+                }
+                _cimg_mp_check_type(arg4,is_sth?2:4,1,0);
+                pos = vector(9);
+                CImg<ulongT>::vector((ulongT)mp_rot3d,pos,arg1,arg2,arg3,arg4).move_to(code);
+              } else { // 2d rotation
+                _cimg_mp_check_type(arg1,1,1,0);
+                pos = vector(4);
+                CImg<ulongT>::vector((ulongT)mp_rot2d,pos,arg1).move_to(code);
+              }
+              _cimg_mp_return(pos);
+            }
+
+            if (!std::strncmp(ss,"round(",6)) { // Value rounding
+              _cimg_mp_op("Function 'round()'");
+              s1 = ss6; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
+              arg1 = compile(ss6,s1,depth1,0);
+              arg2 = 1;
+              arg3 = 0;
+              if (s1<se1) {
+                s2 = s1 + 1; while (s2<se1 && (*s2!=',' || level[s2 - expr._data]!=clevel1)) ++s2;
+                arg2 = compile(++s1,s2,depth1,0);
+                arg3 = s2<se1?compile(++s2,se1,depth1,0):0;
+              }
+              _cimg_mp_check_type(arg2,2,1,0);
+              _cimg_mp_check_type(arg3,3,1,0);
+              if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector3_vss(mp_round,arg1,arg2,arg3);
+              if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2) && _cimg_mp_is_constant(arg3))
+                _cimg_mp_constant(cimg::round(mem[arg1],mem[arg2],(int)mem[arg3]));
+              _cimg_mp_scalar3(mp_round,arg1,arg2,arg3);
+            }
+            break;
+
+          case 's' :
+            if (!std::strncmp(ss,"sign(",5)) { // Sign
+              _cimg_mp_op("Function 'sign()'");
+              arg1 = compile(ss5,se1,depth1,0);
+              if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_sign,arg1);
+              if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(cimg::sign(mem[arg1]));
+              _cimg_mp_scalar1(mp_sign,arg1);
+            }
+
+            if (!std::strncmp(ss,"sin(",4)) { // Sine
+              _cimg_mp_op("Function 'sin()'");
+              arg1 = compile(ss4,se1,depth1,0);
+              if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_sin,arg1);
+              if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::sin(mem[arg1]));
+              _cimg_mp_scalar1(mp_sin,arg1);
+            }
+
+            if (!std::strncmp(ss,"sinc(",5)) { // Sine cardinal
+              _cimg_mp_op("Function 'sinc()'");
+              arg1 = compile(ss5,se1,depth1,0);
+              if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_sinc,arg1);
+              if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(cimg::sinc(mem[arg1]));
+              _cimg_mp_scalar1(mp_sinc,arg1);
+            }
+
+            if (!std::strncmp(ss,"single(",7)) { // Force single thread execution
+              _cimg_mp_op("Function 'single()'");
+              p1 = code._width;
+              arg1 = compile(ss7,se1,depth1,p_ref);
+              CImg<ulongT>::vector((ulongT)mp_single,arg1,code._width - p1).move_to(code,p1);
+              _cimg_mp_return(arg1);
+            }
+
+            if (!std::strncmp(ss,"sinh(",5)) { // Hyperbolic sine
+              _cimg_mp_op("Function 'sinh()'");
+              arg1 = compile(ss5,se1,depth1,0);
+              if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_sinh,arg1);
+              if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::sinh(mem[arg1]));
+              _cimg_mp_scalar1(mp_sinh,arg1);
+            }
+
+            if (!std::strncmp(ss,"size(",5)) { // Vector size.
+              _cimg_mp_op("Function 'size()'");
+              arg1 = compile(ss5,se1,depth1,0);
+              _cimg_mp_constant(_cimg_mp_is_scalar(arg1)?0:_cimg_mp_vector_size(arg1));
+            }
+
+            if (!std::strncmp(ss,"solve(",6)) { // Solve linear system
+              _cimg_mp_op("Function 'solve()'");
+              s1 = ss6; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
+              arg1 = compile(ss6,s1,depth1,0);
+              s2 = s1 + 1; while (s2<se1 && (*s2!=',' || level[s2 - expr._data]!=clevel1)) ++s2;
+              arg2 = compile(++s1,s2,depth1,0);
+              arg3 = s2<se1?compile(++s2,se1,depth1,0):1;
+              _cimg_mp_check_type(arg1,1,2,0);
+              _cimg_mp_check_type(arg2,2,2,0);
+              _cimg_mp_check_constant(arg3,3,true);
+              p1 = _cimg_mp_vector_size(arg1);
+              p2 = _cimg_mp_vector_size(arg2);
+              p3 = (unsigned int)mem[arg3];
+              arg5 = p2/p3;
+              arg4 = p1/arg5;
+              if (arg4*arg5!=p1 || arg5*p3!=p2) {
+                *se = saved_char; cimg::strellipsize(expr,64);
+                throw CImgArgumentException("[_cimg_math_parser] "
+                                            "CImg<%s>::%s: %s: Types of first and second arguments ('%s' and '%s') "
+                                            "do not match for third argument 'nb_colsB=%u', "
+                                            "in expression '%s%s%s'.",
+                                            pixel_type(),_cimg_mp_calling_function,s_op,
+                                            s_type(arg1)._data,s_type(arg2)._data,p3,
+                                            (ss - 4)>expr._data?"...":"",
+                                            (ss - 4)>expr._data?ss - 4:expr._data,
+                                            se<&expr.back()?"...":"");
+              }
+              pos = vector(arg4*p3);
+              CImg<ulongT>::vector((ulongT)mp_solve,pos,arg1,arg2,arg4,arg5,p3).move_to(code);
+              _cimg_mp_return(pos);
+            }
+
+            if (!std::strncmp(ss,"sort(",5)) { // Sort vector
+              _cimg_mp_op("Function 'sort()'");
+              s1 = ss6; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
+              arg1 = compile(ss5,s1,depth1,0);
+              arg2 = arg3 = 1;
+              if (s1<se1) {
+                s0 = ++s1; while (s0<se1 && (*s0!=',' || level[s0 - expr._data]!=clevel1)) ++s0;
+                arg2 = compile(s1,s0,depth1,0);
+                arg3 = s0<se1?compile(++s0,se1,depth1,0):1;
+              }
+              _cimg_mp_check_type(arg1,1,2,0);
+              _cimg_mp_check_type(arg2,2,1,0);
+              _cimg_mp_check_constant(arg3,3,true);
+              arg3 = (unsigned int)mem[arg3];
+              p1 = _cimg_mp_vector_size(arg1);
+              if (p1%arg3) {
+                *se = saved_char; cimg::strellipsize(expr,64);
+                throw CImgArgumentException("[_cimg_math_parser] "
+                                            "CImg<%s>::%s: %s: Invalid specified chunk size (%u) for first argument "
+                                            "('%s'), in expression '%s%s%s'.",
+                                            pixel_type(),_cimg_mp_calling_function,s_op,
+                                            arg3,s_type(arg1)._data,
+                                            (ss - 4)>expr._data?"...":"",
+                                            (ss - 4)>expr._data?ss - 4:expr._data,
+                                            se<&expr.back()?"...":"");
+              }
+              pos = vector(p1);
+              CImg<ulongT>::vector((ulongT)mp_sort,pos,arg1,p1,arg2,arg3).move_to(code);
+              _cimg_mp_return(pos);
+            }
+
+            if (!std::strncmp(ss,"sqr(",4)) { // Square
+              _cimg_mp_op("Function 'sqr()'");
+              arg1 = compile(ss4,se1,depth1,0);
+              if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_sqr,arg1);
+              if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(cimg::sqr(mem[arg1]));
+              _cimg_mp_scalar1(mp_sqr,arg1);
+            }
+
+            if (!std::strncmp(ss,"sqrt(",5)) { // Square root
+              _cimg_mp_op("Function 'sqrt()'");
+              arg1 = compile(ss5,se1,depth1,0);
+              if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_sqrt,arg1);
+              if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::sqrt(mem[arg1]));
+              _cimg_mp_scalar1(mp_sqrt,arg1);
+            }
+            break;
+
+          case 't' :
+            if (!std::strncmp(ss,"tan(",4)) { // Tangent
+              _cimg_mp_op("Function 'tan()'");
+              arg1 = compile(ss4,se1,depth1,0);
+              if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_tan,arg1);
+              if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::tan(mem[arg1]));
+              _cimg_mp_scalar1(mp_tan,arg1);
+            }
+
+            if (!std::strncmp(ss,"tanh(",5)) { // Hyperbolic tangent
+              _cimg_mp_op("Function 'tanh()'");
+              arg1 = compile(ss5,se1,depth1,0);
+              if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_tanh,arg1);
+              if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::tanh(mem[arg1]));
+              _cimg_mp_scalar1(mp_tanh,arg1);
+            }
+
+            if (!std::strncmp(ss,"trace(",6)) { // Matrix trace
+              _cimg_mp_op("Function 'trace()'");
+              arg1 = compile(ss6,se1,depth1,0);
+              _cimg_mp_check_matrix_square(arg1,1);
+              p1 = (unsigned int)std::sqrt((float)_cimg_mp_vector_size(arg1));
+              _cimg_mp_scalar2(mp_trace,arg1,p1);
+            }
+
+            if (!std::strncmp(ss,"transp(",7)) { // Matrix transpose
+              _cimg_mp_op("Function 'transp()'");
+              s1 = ss7; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
+              arg1 = compile(ss7,s1,depth1,0);
+              arg2 = compile(++s1,se1,depth1,0);
+              _cimg_mp_check_type(arg1,1,2,0);
+              _cimg_mp_check_constant(arg2,2,true);
+              p1 = _cimg_mp_vector_size(arg1);
+              p2 = (unsigned int)mem[arg2];
+              p3 = p1/p2;
+              if (p2*p3!=p1) {
+                *se = saved_char; cimg::strellipsize(expr,64);
+                throw CImgArgumentException("[_cimg_math_parser] "
+                                            "CImg<%s>::%s: %s: Size of first argument ('%s') does not match"
+                                            "for second specified argument 'nb_cols=%u', "
+                                            "in expression '%s%s%s'.",
+                                            pixel_type(),_cimg_mp_calling_function,s_op,
+                                            s_type(arg1)._data,p2,
+                                            (ss - 4)>expr._data?"...":"",
+                                            (ss - 4)>expr._data?ss - 4:expr._data,
+                                            se<&expr.back()?"...":"");
+              }
+              pos = vector(p3*p2);
+              CImg<ulongT>::vector((ulongT)mp_transp,pos,arg1,p2,p3).move_to(code);
+              _cimg_mp_return(pos);
+            }
+            break;
+
+          case 'u' :
+            if (*ss1=='(') { // Random value with uniform distribution
+              _cimg_mp_op("Function 'u()'");
+              if (*ss2==')') _cimg_mp_scalar2(mp_u,0,1);
+              s1 = ss2; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
+              arg1 = compile(ss2,s1,depth1,0);
+              if (s1<se1) arg2 = compile(++s1,se1,depth1,0); else { arg2 = arg1; arg1 = 0; }
+              _cimg_mp_check_type(arg2,2,3,_cimg_mp_vector_size(arg1));
+              if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_u,arg1,arg2);
+              if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_u,arg1,arg2);
+              if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_u,arg1,arg2);
+              _cimg_mp_scalar2(mp_u,arg1,arg2);
+            }
+            break;
+
+          case 'v' :
+            if ((cimg_sscanf(ss,"vector%u%c",&(arg1=~0U),&sep)==2 && sep=='(' && arg1>0) ||
+                !std::strncmp(ss,"vector(",7)) { // Vector
+              _cimg_mp_op("Function 'vector()'");
+              arg2 = 0; // Number of specified values.
+              s = std::strchr(ss6,'(') + 1;
+              if (s<se1 || arg1==~0U) for (; s<se; ++s) {
+                  ns = s; while (ns<se && (*ns!=',' || level[ns - expr._data]!=clevel1) &&
+                                 (*ns!=')' || level[ns - expr._data]!=clevel)) ++ns;
+                  arg3 = compile(s,ns,depth1,0);
+                  if (_cimg_mp_is_vector(arg3)) {
+                    arg4 = _cimg_mp_vector_size(arg3);
+                    CImg<ulongT>::sequence(arg4,arg3 + 1,arg3 + arg4).move_to(_opcode);
+                    arg2+=arg4;
+                  } else { CImg<ulongT>::vector(arg3).move_to(_opcode); ++arg2; }
+                  s = ns;
+                }
+              if (arg1==~0U) arg1 = arg2;
+              _cimg_mp_check_vector0(arg1);
+              pos = vector(arg1);
+              _opcode.insert(CImg<ulongT>::vector((ulongT)mp_vector_init,pos,arg1),0);
+              (_opcode>'y').move_to(code);
+              _cimg_mp_return(pos);
+            }
+            break;
+
+          case 'w' :
+            if (!std::strncmp(ss,"whiledo",7) && (*ss7=='(' || (*ss7 && *ss7<=' ' && *ss8=='('))) { // While...do
+              _cimg_mp_op("Function 'whiledo()'");
+              if (*ss7<=' ') cimg::swap(*ss7,*ss8); // Allow space before opening brace
+              s1 = ss8; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
+              p1 = code._width;
+              arg1 = compile(ss8,s1,depth1,0);
+              p2 = code._width;
+              pos = compile(++s1,se1,depth1,0);
+              _cimg_mp_check_type(arg1,1,1,0);
+              arg2 = _cimg_mp_is_vector(pos)?_cimg_mp_vector_size(pos):0; // Output vector size (or 0 if scalar)
+              CImg<ulongT>::vector((ulongT)mp_whiledo,pos,arg1,p2 - p1,code._width - p2,arg2).move_to(code,p1);
+              _cimg_mp_return(pos);
+            }
+            break;
+          }
+
+          if (!std::strncmp(ss,"min(",4) || !std::strncmp(ss,"max(",4) ||
+              !std::strncmp(ss,"med(",4) || !std::strncmp(ss,"kth(",4) ||
+              !std::strncmp(ss,"arg(",4) || !std::strncmp(ss,"sum(",4) ||
+              !std::strncmp(ss,"std(",4) || !std::strncmp(ss,"var(",4) ||
+              !std::strncmp(ss,"prod(",5) || !std::strncmp(ss,"mean(",5) ||
+              !std::strncmp(ss,"argmin(",7) || !std::strncmp(ss,"argmax(",7)) { // Multi-argument functions
+            _cimg_mp_op(*ss=='a'?(ss[3]=='('?"Function 'arg()'":ss[4]=='i'?"Function 'argmin()'":
+                                  "Function 'argmax()'"):
+                        *ss=='s'?(ss[1]=='u'?"Function 'sum()'":"Function 'std()'"):
+                        *ss=='k'?"Function 'kth()'":
+                        *ss=='p'?"Function 'prod()'":
+                        *ss=='v'?"Function 'var()'":
+                        ss[1]=='i'?"Function 'min()'":
+                        ss[1]=='a'?"Function 'max()'":
+                        ss[2]=='a'?"Function 'mean()'":"Function 'med()'");
+            pos = scalar();
+            CImg<ulongT>::vector((ulongT)(*ss=='a'?(ss[3]=='('?mp_arg:ss[4]=='i'?mp_argmin:mp_argmax):
+                                        *ss=='s'?(ss[1]=='u'?mp_sum:mp_std):
+                                        *ss=='k'?mp_kth:
+                                        *ss=='p'?mp_prod:
+                                        *ss=='v'?mp_var:
+                                        ss[1]=='i'?mp_min:
+                                        ss[1]=='a'?mp_max:
+                                        ss[2]=='a'?mp_mean:
+                                        mp_med),pos).
+              move_to(_opcode);
+            for (s = std::strchr(ss,'(') + 1; s<se; ++s) {
+              ns = s; while (ns<se && (*ns!=',' || level[ns - expr._data]!=clevel1) &&
+                             (*ns!=')' || level[ns - expr._data]!=clevel)) ++ns;
+              arg2 = compile(s,ns,depth1,0);
+              if (_cimg_mp_is_vector(arg2))
+                CImg<ulongT>::sequence((ulongT)_cimg_mp_vector_size(arg2),arg2 + 1,
+                                      arg2 + (ulongT)_cimg_mp_vector_size(arg2)).
+                  move_to(_opcode);
+              else CImg<ulongT>::vector(arg2).move_to(_opcode);
+              s = ns;
+            }
+            (_opcode>'y').move_to(code);
+            _cimg_mp_return(pos);
+          }
+
+          // No corresponding built-in function -> Look for a user-defined macro.
+          s0 = strchr(ss,'(');
+          if (s0) {
+            variable_name.assign(ss,s0 - ss + 1).back() = 0;
+            cimglist_for(function_def,l) if (!std::strcmp(function_def[l],variable_name)) {
+              p2 = (unsigned int)function_def[l].back(); // Number of required arguments
+              CImg<charT> _expr = function_body[l]; // Expression to be substituted
+              p1 = 1; // Indice of current parsed argument
+              for (s = s0 + 1; s<=se1; ++p1, s = ns + 1) { // Parse function arguments
+                while (*s && *s<=' ') ++s;
+                if (*s==')' && p1==1) break; // Function has no arguments
+                if (p1>p2) { ++p1; break; }
+                ns = s; while (ns<se && (*ns!=',' || level[ns - expr._data]!=clevel1) &&
+                               (*ns!=')' || level[ns - expr._data]!=clevel)) ++ns;
+
+                variable_name.assign(s,ns - s + 1).back() = 0; // Argument to write
+
+                cimg_forX(_expr,k) if (_expr[k]==(char)p1) { // Perform argument substitution
+                  _expr.resize(_expr._width + variable_name._width,1,1,1,0);
+                  _expr[k++] = '(';
+                  std::memmove(_expr._data + k + variable_name._width,_expr._data + k,
+                               _expr._width - variable_name._width - k);
+                  std::memcpy(_expr._data + k,variable_name,variable_name._width - 1);
+                  k+=variable_name._width - 1;
+                  _expr[k++] = ')';
+                }
+                *ns = 0;
+              }
+
+              if (p1!=p2+1) { // Number of specified argument do not fit
+                *se = saved_char; cimg::strellipsize(variable_name,64); cimg::strellipsize(expr,64);
+                throw CImgArgumentException("[_cimg_math_parser] "
+                                            "CImg<%s>::%s: Function '%s()': Number of specified arguments does not "
+                                            "match function declaration (%u argument%s required), "
+                                            "in expression '%s%s%s'.",
+                                            pixel_type(),_cimg_mp_calling_function,variable_name._data,
+                                            p2,p2!=1?"s":"",
+                                            (ss - 4)>expr._data?"...":"",
+                                            (ss - 4)>expr._data?ss - 4:expr._data,
+                                            se<&expr.back()?"...":"");
+              }
+
+              // Recompute 'pexpr' and 'level' for evaluating substituted expression.
+              CImg<charT> _pexpr(_expr._width);
+              ns = _pexpr._data;
+              for (ps = _expr._data, c1 = ' '; *ps; ++ps) {
+                if (*ps!=' ') c1 = *ps;
+                *(ns++) = c1;
+              }
+              *ns = 0;
+
+              CImg<uintT> _level(_expr._width - 1);
+              unsigned int *pd = _level._data;
+              nb = 0;
+              for (ps = _expr._data; *ps && nb>=0; ++ps)
+                *(pd++) = (unsigned int)(*ps=='('||*ps=='['?nb++:*ps==')'||*ps==']'?--nb:nb);
+
+              expr.swap(_expr); pexpr.swap(_pexpr); level.swap(_level);
+              s0 = user_function;
+              user_function = function_def[l];
+              pos = compile(expr._data,expr._data + expr._width - 1,depth1,p_ref);
+              user_function = s0;
+              expr.swap(_expr); pexpr.swap(_pexpr); level.swap(_level);
+              _cimg_mp_return(pos);
+            }
+          }
+        } // if (se1==')')
+
+        // Vector specification using initializer '[ ... ]'.
+        if (*ss=='[' && *se1==']') {
+          _cimg_mp_op("Operator '[]'");
+          arg1 = 0; // Number of specified values.
+          if (*ss1!=']') for (s = ss1; s<se; ++s) {
+              ns = s; while (ns<se && (*ns!=',' || level[ns - expr._data]!=clevel1) &&
+                             (*ns!=']' || level[ns - expr._data]!=clevel)) ++ns;
+              arg2 = compile(s,ns,depth1,0);
+              if (_cimg_mp_is_vector(arg2)) {
+                arg3 = _cimg_mp_vector_size(arg2);
+                CImg<ulongT>::sequence(arg3,arg2 + 1,arg2 + arg3).move_to(_opcode);
+                arg1+=arg3;
+              } else { CImg<ulongT>::vector(arg2).move_to(_opcode); ++arg1; }
+              s = ns;
+            }
+          _cimg_mp_check_vector0(arg1);
+          pos = vector(arg1);
+          _opcode.insert(CImg<ulongT>::vector((ulongT)mp_vector_init,pos,arg1),0);
+          (_opcode>'y').move_to(code);
+          _cimg_mp_return(pos);
+        }
+
+        // Variables related to the input list of images.
+        if (*ss1=='#' && ss2<se) {
+          arg1 = compile(ss2,se,depth1,0);
+          p1 = (unsigned int)(listin._width && _cimg_mp_is_constant(arg1)?cimg::mod((int)mem[arg1],listin.width()):0);
+          switch (*ss) {
+          case 'w' : // w#ind
+            if (!listin) _cimg_mp_return(0);
+            if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(listin[p1]._width);
+            _cimg_mp_scalar1(mp_list_width,arg1);
+          case 'h' : // h#ind
+            if (!listin) _cimg_mp_return(0);
+            if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(listin[p1]._height);
+            _cimg_mp_scalar1(mp_list_height,arg1);
+          case 'd' : // d#ind
+            if (!listin) _cimg_mp_return(0);
+            if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(listin[p1]._depth);
+            _cimg_mp_scalar1(mp_list_depth,arg1);
+          case 'r' : // r#ind
+            if (!listin) _cimg_mp_return(0);
+            if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(listin[p1]._is_shared);
+            _cimg_mp_scalar1(mp_list_is_shared,arg1);
+          case 's' : // s#ind
+            if (!listin) _cimg_mp_return(0);
+            if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(listin[p1]._spectrum);
+            _cimg_mp_scalar1(mp_list_spectrum,arg1);
+          case 'i' : // i#ind
+            if (!listin) _cimg_mp_return(0);
+            _cimg_mp_scalar7(mp_list_ixyzc,arg1,_cimg_mp_x,_cimg_mp_y,_cimg_mp_z,_cimg_mp_c,
+                             reserved_label[29],reserved_label[30]);
+          case 'R' : // R#ind
+            if (!listin) _cimg_mp_return(0);
+            _cimg_mp_scalar7(mp_list_ixyzc,arg1,_cimg_mp_x,_cimg_mp_y,_cimg_mp_z,0,
+                             reserved_label[29],reserved_label[30]);
+          case 'G' : // G#ind
+            if (!listin) _cimg_mp_return(0);
+            _cimg_mp_scalar7(mp_list_ixyzc,arg1,_cimg_mp_x,_cimg_mp_y,_cimg_mp_z,1,
+                             reserved_label[29],reserved_label[30]);
+          case 'B' : // B#ind
+            if (!listin) _cimg_mp_return(0);
+            _cimg_mp_scalar7(mp_list_ixyzc,arg1,_cimg_mp_x,_cimg_mp_y,_cimg_mp_z,2,
+                             reserved_label[29],reserved_label[30]);
+          case 'A' : // A#ind
+            if (!listin) _cimg_mp_return(0);
+            _cimg_mp_scalar7(mp_list_ixyzc,arg1,_cimg_mp_x,_cimg_mp_y,_cimg_mp_z,3,
+                             reserved_label[29],reserved_label[30]);
+          }
+        }
+
+        if (*ss1 && *ss2=='#' && ss3<se) {
+          arg1 = compile(ss3,se,depth1,0);
+          p1 = (unsigned int)(listin._width && _cimg_mp_is_constant(arg1)?cimg::mod((int)mem[arg1],listin.width()):0);
+          if (*ss=='w' && *ss1=='h') { // wh#ind
+            if (!listin) _cimg_mp_return(0);
+            if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(listin[p1]._width*listin[p1]._height);
+            _cimg_mp_scalar1(mp_list_wh,arg1);
+          }
+          arg2 = ~0U;
+
+          if (*ss=='i') {
+            if (*ss1=='c') { // ic#ind
+              if (!listin) _cimg_mp_return(0);
+              if (_cimg_mp_is_constant(arg1)) {
+                if (!list_median) list_median.assign(listin._width);
+                if (!list_median[p1]) CImg<doubleT>::vector(listin[p1].median()).move_to(list_median[p1]);
+                _cimg_mp_constant(*list_median[p1]);
+              }
+              _cimg_mp_scalar1(mp_list_median,arg1);
+            }
+            if (*ss1>='0' && *ss1<='9') { // i0#ind...i9#ind
+              if (!listin) _cimg_mp_return(0);
+              _cimg_mp_scalar7(mp_list_ixyzc,arg1,_cimg_mp_x,_cimg_mp_y,_cimg_mp_z,*ss1 - '0',
+                               reserved_label[29],reserved_label[30]);
+            }
+            switch (*ss1) {
+            case 'm' : arg2 = 0; break; // im#ind
+            case 'M' : arg2 = 1; break; // iM#ind
+            case 'a' : arg2 = 2; break; // ia#ind
+            case 'v' : arg2 = 3; break; // iv#ind
+            case 's' : arg2 = 12; break; // is#ind
+            case 'p' : arg2 = 13; break; // ip#ind
+            }
+          } else if (*ss1=='m') switch (*ss) {
+            case 'x' : arg2 = 4; break; // xm#ind
+            case 'y' : arg2 = 5; break; // ym#ind
+            case 'z' : arg2 = 6; break; // zm#ind
+            case 'c' : arg2 = 7; break; // cm#ind
+            } else if (*ss1=='M') switch (*ss) {
+            case 'x' : arg2 = 8; break; // xM#ind
+            case 'y' : arg2 = 9; break; // yM#ind
+            case 'z' : arg2 = 10; break; // zM#ind
+            case 'c' : arg2 = 11; break; // cM#ind
+            }
+          if (arg2!=~0U) {
+            if (!listin) _cimg_mp_return(0);
+            if (_cimg_mp_is_constant(arg1)) {
+              if (!list_stats) list_stats.assign(listin._width);
+              if (!list_stats[p1]) list_stats[p1].assign(1,14,1,1,0).fill(listin[p1].get_stats(),false);
+              _cimg_mp_constant(list_stats(p1,arg2));
+            }
+            _cimg_mp_scalar2(mp_list_stats,arg1,arg2);
+          }
+        }
+
+        if (*ss=='w' && *ss1=='h' && *ss2=='d' && *ss3=='#' && ss4<se) { // whd#ind
+          arg1 = compile(ss4,se,depth1,0);
+          if (!listin) _cimg_mp_return(0);
+          p1 = (unsigned int)(_cimg_mp_is_constant(arg1)?cimg::mod((int)mem[arg1],listin.width()):0);
+          if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(listin[p1]._width*listin[p1]._height*listin[p1]._depth);
+          _cimg_mp_scalar1(mp_list_whd,arg1);
+        }
+        if (*ss=='w' && *ss1=='h' && *ss2=='d' && *ss3=='s' && *ss4=='#' && ss5<se) { // whds#ind
+          arg1 = compile(ss5,se,depth1,0);
+          if (!listin) _cimg_mp_return(0);
+          p1 = (unsigned int)(_cimg_mp_is_constant(arg1)?cimg::mod((int)mem[arg1],listin.width()):0);
+          if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(listin[p1]._width*listin[p1]._height*listin[p1]._depth*
+                                                            listin[p1]._spectrum);
+          _cimg_mp_scalar1(mp_list_whds,arg1);
+        }
+
+        if (!std::strcmp(ss,"interpolation")) _cimg_mp_return(reserved_label[29]); // interpolation
+        if (!std::strcmp(ss,"boundary")) _cimg_mp_return(reserved_label[30]); // boundary
+
+        // No known item found, assuming this is an already initialized variable.
+        variable_name.assign(ss,(unsigned int)(se + 1 - ss)).back() = 0;
+        if (variable_name[1]) { // Multi-char variable
+          cimglist_for(variable_def,i) if (!std::strcmp(variable_name,variable_def[i]))
+            _cimg_mp_return(variable_pos[i]);
+        } else if (reserved_label[*variable_name]!=~0U) // Single-char variable
+          _cimg_mp_return(reserved_label[*variable_name]);
+
+        // Reached an unknown item -> error.
+        is_sth = true; // is_valid_variable_name
+        if (*variable_name>='0' && *variable_name<='9') is_sth = false;
+        else for (ns = variable_name._data; *ns; ++ns)
+               if (!is_varchar(*ns)) { is_sth = false; break; }
+
+        *se = saved_char; cimg::strellipsize(variable_name,64); cimg::strellipsize(expr,64);
+        if (is_sth)
+          throw CImgArgumentException("[_cimg_math_parser] "
+                                      "CImg<%s>::%s: Undefined variable '%s' in expression '%s%s%s'.",
+                                      pixel_type(),_cimg_mp_calling_function,
+                                      variable_name._data,
+                                      (ss - 4)>expr._data?"...":"",
+                                      (ss - 4)>expr._data?ss - 4:expr._data,
+                                      se<&expr.back()?"...":"");
+        s0 = std::strchr(ss,'(');
+        if (s0 && *se1==')') s_op = "function call"; else s_op = "item";
+        throw CImgArgumentException("[_cimg_math_parser] "
+                                    "CImg<%s>::%s: Unrecognized %s '%s' in expression '%s%s%s'.",
+                                    pixel_type(),_cimg_mp_calling_function,
+                                    s_op,variable_name._data,
+                                    (ss - 4)>expr._data?"...":"",
+                                    (ss - 4)>expr._data?ss - 4:expr._data,
+                                    se<&expr.back()?"...":"");
       }
 
-      static double mp_sqrt(_cimg_math_parser& mp) {
-        return std::sqrt(mp.mem[mp.opcode(2)]);
+      // Evaluation procedure.
+      double operator()(const double x, const double y, const double z, const double c) {
+        mem[_cimg_mp_x] = x; mem[_cimg_mp_y] = y; mem[_cimg_mp_z] = z; mem[_cimg_mp_c] = c;
+        for (p_code = p_code_begin; p_code<p_code_end; ++p_code) {
+          const CImg<ulongT> &op = *p_code;
+          opcode._data = op._data; opcode._height = op._height;
+          const ulongT target = opcode[1];
+          mem[target] = _cimg_mp_defunc(*this);
+        }
+        return *result;
       }
 
-      static double mp_cbrt(_cimg_math_parser& mp) {
-        return std::pow(mp.mem[mp.opcode(2)],1.0/3);
+      // Evaluation procedure (return output values in vector 'output').
+      template<typename t>
+      void operator()(const double x, const double y, const double z, const double c, t *const output) {
+        mem[_cimg_mp_x] = x; mem[_cimg_mp_y] = y; mem[_cimg_mp_z] = z; mem[_cimg_mp_c] = c;
+        for (p_code = p_code_begin; p_code<p_code_end; ++p_code) {
+          const CImg<ulongT> &op = *p_code;
+          opcode._data = op._data; opcode._height = op._height;
+          const ulongT target = opcode[1];
+          mem[target] = _cimg_mp_defunc(*this);
+        }
+        if (result_dim) {
+          const double *ptrs = result + 1;
+          t *ptrd = output;
+          for (unsigned int k = 0; k<result_dim; ++k) *(ptrd++) = (t)*(ptrs++);
+        } else *output = (t)*result;
       }
 
-      static double mp_hypot(_cimg_math_parser& mp) {
-        double
-          x = cimg::abs(mp.mem[mp.opcode(2)]),
-          y = cimg::abs(mp.mem[mp.opcode(3)]),
-          t;
-        if (x<y) { t = x; x = y; } else t = y;
-        if (x>0) { t/=x; return x*std::sqrt(1+t*t); }
-        return 0;
+      // Return type of a memory element as a string.
+      CImg<charT> s_type(const unsigned int arg) const {
+        CImg<charT> res;
+        if (_cimg_mp_is_vector(arg)) { // Vector
+          CImg<charT>::string("vectorXXXXXXXXXXXXXXXX").move_to(res);
+          std::sprintf(res._data + 6,"%u",_cimg_mp_vector_size(arg));
+        } else CImg<charT>::string("scalar").move_to(res);
+        return res;
       }
 
-      static double mp_norm(_cimg_math_parser& mp) {
-        const unsigned int norm_type = (unsigned int)mp.opcode(2);
-        double res = 0;
-        switch (norm_type) {
-        case 0 : // L0-norm.
-          for (unsigned int i = 3; i<mp.opcode._height; ++i)
-            res+=mp.mem[mp.opcode(i)]==0?0:1;
-          break;
-        case 1 : // L1-norm.
-          for (unsigned int i = 3; i<mp.opcode._height; ++i)
-            res+=cimg::abs(mp.mem[mp.opcode(i)]);
-          break;
-        case 2 : // L2-norm.
-          for (unsigned int i = 3; i<mp.opcode._height; ++i) {
-            const double val = mp.mem[mp.opcode(i)];
-            res+=val*val;
-          }
-          res = std::sqrt(res);
-          break;
-        case ~0U : // Linf-norm.
-          for (unsigned int i = 3; i<mp.opcode._height; ++i) {
-            const double val = cimg::abs(mp.mem[mp.opcode(i)]);
-            if (val>res) res = val;
-          }
-          break;
-        default: // Lp-norm.
-          for (unsigned int i = 3; i<mp.opcode._height; ++i)
-            res+=std::pow(cimg::abs(mp.mem[mp.opcode(i)]),(double)norm_type);
-          res = std::pow(res,1.0/norm_type);
+      // Insert constant value in memory.
+      unsigned int constant(const double val) {
+        if (val==(double)(int)val) {
+          if (val>=0 && val<=9) return (unsigned int)val;
+          if (val<0 && val>=-5) return (unsigned int)(10 - val);
         }
-        return res>0?res:0.0;
+        if (val==0.5) return 16;
+        if (cimg::type<double>::is_nan(val)) return 28;
+        if (mempos>=mem._width) { mem.resize(-200,1,1,1,0); memtype.resize(-200,1,1,1,0); }
+        const unsigned int pos = mempos++;
+        mem[pos] = val;
+        memtype[pos] = 1; // Set constant property
+        return pos;
       }
 
-      static double mp_sign(_cimg_math_parser& mp) {
-        return cimg::sign(mp.mem[mp.opcode(2)]);
+      // Insert code instructions for processing scalars.
+      unsigned int scalar() { // Insert new scalar in memory.
+        if (mempos>=mem._width) { mem.resize(-200,1,1,1,0); memtype.resize(mem._width,1,1,1,0); }
+        return mempos++;
       }
 
-      static double mp_time(_cimg_math_parser& mp) {
-        cimg::unused(mp);
-        return (double)cimg::time();
+      unsigned int scalar0(const mp_func op) {
+        const unsigned int pos = scalar();
+        CImg<ulongT>::vector((ulongT)op,pos).move_to(code);
+        return pos;
       }
 
-      static double mp_abs(_cimg_math_parser& mp) {
-        return cimg::abs(mp.mem[mp.opcode(2)]);
+      unsigned int scalar1(const mp_func op, const unsigned int arg1) {
+        const unsigned int pos =
+          arg1>_cimg_mp_c && _cimg_mp_is_temp(arg1)?arg1:scalar();
+        CImg<ulongT>::vector((ulongT)op,pos,arg1).move_to(code);
+        return pos;
       }
 
-      static double mp_atan2(_cimg_math_parser& mp) {
-        return std::atan2(mp.mem[mp.opcode(2)],mp.mem[mp.opcode(3)]);
+      unsigned int scalar2(const mp_func op, const unsigned int arg1, const unsigned int arg2) {
+        const unsigned int pos =
+          arg1>_cimg_mp_c && _cimg_mp_is_temp(arg1)?arg1:
+          arg2>_cimg_mp_c && _cimg_mp_is_temp(arg2)?arg2:scalar();
+        CImg<ulongT>::vector((ulongT)op,pos,arg1,arg2).move_to(code);
+        return pos;
       }
 
-      static double mp_round(_cimg_math_parser& mp) {
-        return cimg::round(mp.mem[mp.opcode(2)],mp.mem[mp.opcode(3)],(int)mp.mem[mp.opcode(4)]);
+      unsigned int scalar3(const mp_func op,
+                           const unsigned int arg1, const unsigned int arg2, const unsigned int arg3) {
+        const unsigned int pos =
+          arg1>_cimg_mp_c && _cimg_mp_is_temp(arg1)?arg1:
+          arg2>_cimg_mp_c && _cimg_mp_is_temp(arg2)?arg2:
+          arg3>_cimg_mp_c && _cimg_mp_is_temp(arg3)?arg3:scalar();
+        CImg<ulongT>::vector((ulongT)op,pos,arg1,arg2,arg3).move_to(code);
+        return pos;
       }
 
-      static double mp_min(_cimg_math_parser& mp) {
-        double val = mp.mem[mp.opcode(2)];
-        for (unsigned int i = 3; i<mp.opcode._height; ++i) val = cimg::min(val,mp.mem[mp.opcode(i)]);
-        return val;
+      unsigned int scalar6(const mp_func op,
+                           const unsigned int arg1, const unsigned int arg2, const unsigned int arg3,
+                           const unsigned int arg4, const unsigned int arg5, const unsigned int arg6) {
+        const unsigned int pos =
+          arg1>_cimg_mp_c && _cimg_mp_is_temp(arg1)?arg1:
+          arg2>_cimg_mp_c && _cimg_mp_is_temp(arg2)?arg2:
+          arg3>_cimg_mp_c && _cimg_mp_is_temp(arg3)?arg3:
+          arg4>_cimg_mp_c && _cimg_mp_is_temp(arg4)?arg4:
+          arg5>_cimg_mp_c && _cimg_mp_is_temp(arg5)?arg5:
+          arg6>_cimg_mp_c && _cimg_mp_is_temp(arg6)?arg6:scalar();
+        CImg<ulongT>::vector((ulongT)op,pos,arg1,arg2,arg3,arg4,arg5,arg6).move_to(code);
+        return pos;
       }
 
-      static double mp_max(_cimg_math_parser& mp) {
-        double val = mp.mem[mp.opcode(2)];
-        for (unsigned int i = 3; i<mp.opcode._height; ++i) val = cimg::max(val,mp.mem[mp.opcode(i)]);
-        return val;
+      unsigned int scalar7(const mp_func op,
+                           const unsigned int arg1, const unsigned int arg2, const unsigned int arg3,
+                           const unsigned int arg4, const unsigned int arg5, const unsigned int arg6,
+                           const unsigned int arg7) {
+        const unsigned int pos =
+          arg1>_cimg_mp_c && _cimg_mp_is_temp(arg1)?arg1:
+          arg2>_cimg_mp_c && _cimg_mp_is_temp(arg2)?arg2:
+          arg3>_cimg_mp_c && _cimg_mp_is_temp(arg3)?arg3:
+          arg4>_cimg_mp_c && _cimg_mp_is_temp(arg4)?arg4:
+          arg5>_cimg_mp_c && _cimg_mp_is_temp(arg5)?arg5:
+          arg6>_cimg_mp_c && _cimg_mp_is_temp(arg6)?arg6:
+          arg7>_cimg_mp_c && _cimg_mp_is_temp(arg7)?arg7:scalar();
+        CImg<ulongT>::vector((ulongT)op,pos,arg1,arg2,arg3,arg4,arg5,arg6,arg7).move_to(code);
+        return pos;
       }
 
-      static double mp_med(_cimg_math_parser& mp) {
-        CImg<doubleT> values(mp.opcode._height - 2);
-        double *p = values.data();
-        for (unsigned int i = 2; i<mp.opcode._height; ++i) *(p++) = mp.mem[mp.opcode(i)];
-        return values.median();
+      // Return a string that defines the calling function + the user-defined function scope.
+      CImg<charT> calling_function_s() const {
+        CImg<charT> res;
+        const unsigned int
+          l1 = calling_function?(unsigned int)std::strlen(calling_function):0U,
+          l2 = user_function?(unsigned int)std::strlen(user_function):0U;
+        if (l2) {
+          res.assign(l1 + l2 + 48);
+          cimg_snprintf(res,res._width,"%s(): When substituting function '%s()'",calling_function,user_function);
+        } else {
+          res.assign(l1 + l2 + 4);
+          cimg_snprintf(res,res._width,"%s()",calling_function);
+        }
+        return res;
       }
 
-      static double mp_kth(_cimg_math_parser& mp) {
-        CImg<doubleT> values(mp.opcode._height - 3);
-        double *p = values.data();
-        for (unsigned int i = 3; i<mp.opcode._height; ++i) *(p++) = mp.mem[mp.opcode(i)];
-        int ind = (int)cimg::round(mp.mem[mp.opcode(2)]);
-        if (ind<0) ind+=values.width() + 1;
-        ind = cimg::max(1,cimg::min(values.width(),ind));
-        return values.kth_smallest(ind - 1);
+      // Return true if specified argument can be a part of an allowed  variable name.
+      bool is_varchar(const char c) const {
+        return (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') || c=='_';
+      }
+
+      // Insert code instructions for processing vectors.
+      bool is_tmp_vector(const unsigned int arg) const {
+        unsigned int siz = _cimg_mp_vector_size(arg);
+        if (siz>8) return false;
+        const int *ptr = memtype.data(arg + 1);
+        bool is_tmp = true;
+        while (siz-->0) if (*(ptr++)) { is_tmp = false; break; }
+        return is_tmp;
+      }
+
+      void set_variable_vector(const unsigned int arg) {
+        unsigned int siz = _cimg_mp_vector_size(arg);
+        int *ptr = memtype.data(arg + 1);
+        while (siz-->0) *(ptr++) = -1;
+      }
+
+      unsigned int vector(const unsigned int siz) { // Insert new vector of specified size in memory
+        if (mempos + siz>=mem._width) {
+          mem.resize(2*mem._width + siz,1,1,1,0);
+          memtype.resize(mem._width,1,1,1,0);
+        }
+        const unsigned int pos = mempos++;
+        mem[pos] = cimg::type<double>::nan();
+        memtype[pos] = siz + 1;
+        mempos+=siz;
+        return pos;
+      }
+
+      unsigned int vector(const unsigned int siz, const double value) { // Insert new initialized vector
+        const unsigned int pos = vector(siz);
+        double *ptr = &mem[pos] + 1;
+        for (unsigned int i = 0; i<siz; ++i) *(ptr++) = value;
+        return pos;
+      }
+
+      unsigned int vector_copy(const unsigned int arg) { // Insert new copy of specified vector in memory
+        const unsigned int
+          siz = _cimg_mp_vector_size(arg),
+          pos = vector(siz);
+        CImg<ulongT>::vector((ulongT)mp_vector_copy,pos,arg,siz).move_to(code);
+        return pos;
+      }
+
+      void self_vector_s(const unsigned int pos, const mp_func op, const unsigned int arg1) {
+        const unsigned int siz = _cimg_mp_vector_size(pos);
+        if (siz>24) CImg<ulongT>::vector((ulongT)mp_self_map_vector_s,pos,siz,(ulongT)op,arg1).move_to(code);
+        else {
+          code.insert(siz);
+          for (unsigned int k = 1; k<=siz; ++k)
+            CImg<ulongT>::vector((ulongT)op,pos + k,arg1).move_to(code[code._width - 1 - siz + k]);
+        }
+      }
+
+      void self_vector_v(const unsigned int pos, const mp_func op, const unsigned int arg1) {
+        const unsigned int siz = _cimg_mp_vector_size(pos);
+        if (siz>24) CImg<ulongT>::vector((ulongT)mp_self_map_vector_v,pos,siz,(ulongT)op,arg1).move_to(code);
+        else {
+          code.insert(siz);
+          for (unsigned int k = 1; k<=siz; ++k)
+            CImg<ulongT>::vector((ulongT)op,pos + k,arg1 + k).move_to(code[code._width - 1 - siz + k]);
+        }
+      }
+
+      unsigned int vector1_v(const mp_func op, const unsigned int arg1) {
+        const unsigned int
+          siz = _cimg_mp_vector_size(arg1),
+          pos = is_tmp_vector(arg1)?arg1:vector(siz);
+        if (siz>24) CImg<ulongT>::vector((ulongT)mp_vector_map_v,pos,siz,(ulongT)op,arg1).move_to(code);
+        else {
+          code.insert(siz);
+          for (unsigned int k = 1; k<=siz; ++k)
+            CImg<ulongT>::vector((ulongT)op,pos + k,arg1 + k).move_to(code[code._width - 1 - siz + k]);
+        }
+        return pos;
+      }
+
+      unsigned int vector2_vv(const mp_func op, const unsigned int arg1, const unsigned int arg2) {
+        const unsigned int
+          siz = _cimg_mp_vector_size(arg1),
+          pos = is_tmp_vector(arg1)?arg1:is_tmp_vector(arg2)?arg2:vector(siz);
+        if (siz>24) CImg<ulongT>::vector((ulongT)mp_vector_map_vv,pos,siz,(ulongT)op,arg1,arg2).move_to(code);
+        else {
+          code.insert(siz);
+          for (unsigned int k = 1; k<=siz; ++k)
+            CImg<ulongT>::vector((ulongT)op,pos + k,arg1 + k,arg2 + k).move_to(code[code._width - 1 - siz + k]);
+        }
+        return pos;
+      }
+
+      unsigned int vector2_vs(const mp_func op, const unsigned int arg1, const unsigned int arg2) {
+        const unsigned int
+          siz = _cimg_mp_vector_size(arg1),
+          pos = is_tmp_vector(arg1)?arg1:vector(siz);
+        if (siz>24) CImg<ulongT>::vector((ulongT)mp_vector_map_vs,pos,siz,(ulongT)op,arg1,arg2).move_to(code);
+        else {
+          code.insert(siz);
+          for (unsigned int k = 1; k<=siz; ++k)
+            CImg<ulongT>::vector((ulongT)op,pos + k,arg1 + k,arg2).move_to(code[code._width - 1 - siz + k]);
+        }
+        return pos;
+      }
+
+      unsigned int vector2_sv(const mp_func op, const unsigned int arg1, const unsigned int arg2) {
+        const unsigned int
+          siz = _cimg_mp_vector_size(arg2),
+          pos = is_tmp_vector(arg2)?arg2:vector(siz);
+        if (siz>24) CImg<ulongT>::vector((ulongT)mp_vector_map_sv,pos,siz,(ulongT)op,arg1,arg2).move_to(code);
+        else {
+          code.insert(siz);
+          for (unsigned int k = 1; k<=siz; ++k)
+            CImg<ulongT>::vector((ulongT)op,pos + k,arg1,arg2 + k).move_to(code[code._width - 1 - siz + k]);
+        }
+        return pos;
+      }
+
+      unsigned int vector3_vss(const mp_func op, const unsigned int arg1, const unsigned int arg2,
+                               const unsigned int arg3) {
+        const unsigned int
+          siz = _cimg_mp_vector_size(arg1),
+          pos = is_tmp_vector(arg1)?arg1:vector(siz);
+        if (siz>24) CImg<ulongT>::vector((ulongT)mp_vector_map_vss,pos,siz,(ulongT)op,arg1,arg2,arg3).move_to(code);
+        else {
+          code.insert(siz);
+          for (unsigned int k = 1; k<=siz; ++k)
+            CImg<ulongT>::vector((ulongT)op,pos + k,arg1 + k,arg2,arg3).move_to(code[code._width - 1 - siz + k]);
+        }
+        return pos;
+      }
+
+      // Check if a memory slot is a positive integer constant scalar value.
+      void check_constant(const unsigned int arg, const unsigned int n_arg,
+                          const bool is_strictly_positive,
+                          const char *const ss, char *const se, const char saved_char) {
+        _cimg_mp_check_type(arg,n_arg,1,0);
+        if (!_cimg_mp_is_constant(arg) || mem[arg]<(is_strictly_positive?1:0) || (double)(int)mem[arg]!=mem[arg]) {
+          const char *s_arg = !n_arg?"":n_arg==1?"First ":n_arg==2?"Second ":n_arg==3?"Third ":
+            n_arg==4?"Fourth ":n_arg==5?"Fifth ":n_arg==6?"Sixth ":n_arg==7?"Seventh ":n_arg==8?"Eighth ":
+            n_arg==9?"Ninth ":"One of the ";
+          *se = saved_char; cimg::strellipsize(expr,64);
+          throw CImgArgumentException("[_cimg_math_parser] "
+                                      "CImg<%s>::%s(): %s%s %s%s (of type '%s') is not a %spositive integer constant, "
+                                      "in expression '%s%s%s'.",
+                                      pixel_type(),_cimg_mp_calling_function,s_op,*s_op?":":"",
+                                      s_arg,*s_arg?"argument":"Argument",s_type(arg)._data,
+                                      is_strictly_positive?"strictly ":"",
+                                      (ss - 4)>expr._data?"...":"",
+                                      (ss - 4)>expr._data?ss - 4:expr._data,
+                                      se<&expr.back()?"...":"");
+        }
+      }
+
+      // Check a matrix is square.
+      void check_matrix_square(const unsigned int arg, const unsigned int n_arg,
+                               const char *const ss, char *const se, const char saved_char) {
+        _cimg_mp_check_type(arg,n_arg,2,0);
+        const unsigned int
+          siz = _cimg_mp_vector_size(arg),
+          n = (unsigned int)std::sqrt((float)siz);
+        if (n*n!=siz) {
+          const char *s_arg;
+          if (*s_op!='F') s_arg = !n_arg?"":n_arg==1?"Left-hand ":"Right-hand ";
+          else s_arg = !n_arg?"":n_arg==1?"First ":n_arg==2?"Second ":n_arg==3?"Third ":"One ";
+          *se = saved_char; cimg::strellipsize(expr,64);
+          throw CImgArgumentException("[_cimg_math_parser] "
+                                      "CImg<%s>::%s(): %s%s %s%s (of type '%s') "
+                                      "cannot be considered as a square matrix, in expression '%s%s%s'.",
+                                      pixel_type(),_cimg_mp_calling_function,s_op,*s_op?":":"",
+                                      s_arg,*s_op=='F'?(*s_arg?"argument":"Argument"):(*s_arg?"operand":"Operand"),
+                                      s_type(arg)._data,
+                                      (ss - 4)>expr._data?"...":"",
+                                      (ss - 4)>expr._data?ss - 4:expr._data,
+                                      se<&expr.back()?"...":"");
+        }
+      }
+
+      // Check type compatibility for one argument.
+      // Bits of 'mode' tells what types are allowed:
+      // { 1 = scalar | 2 = vectorN }.
+      // If 'N' is not zero, it also restricts the vectors to be of size N only.
+      void check_type(const unsigned int arg, const unsigned int n_arg,
+                      const unsigned int mode, const unsigned int N,
+                      const char *const ss, char *const se, const char saved_char) {
+        const bool
+          is_scalar = _cimg_mp_is_scalar(arg),
+          is_vector = _cimg_mp_is_vector(arg) && (!N || _cimg_mp_vector_size(arg)==N);
+        bool cond = false;
+        if (mode&1) cond|=is_scalar;
+        if (mode&2) cond|=is_vector;
+        if (!cond) {
+          const char *s_arg;
+          if (*s_op!='F') s_arg = !n_arg?"":n_arg==1?"Left-hand ":"Right-hand ";
+          else s_arg = !n_arg?"":n_arg==1?"First ":n_arg==2?"Second ":n_arg==3?"Third ":
+                 n_arg==4?"Fourth ":n_arg==5?"Fifth ":n_arg==6?"Sixth ":n_arg==7?"Seventh ":n_arg==8?"Eighth":
+                 n_arg==9?"Ninth":"One of the ";
+          CImg<charT> sb_type(32);
+          if (mode==1) cimg_snprintf(sb_type,sb_type._width,"'scalar'");
+          else if (mode==2) {
+            if (N) cimg_snprintf(sb_type,sb_type._width,"'vector%u'",N);
+            else cimg_snprintf(sb_type,sb_type._width,"'vector'");
+          } else {
+            if (N) cimg_snprintf(sb_type,sb_type._width,"'scalar' or 'vector%u'",N);
+            else cimg_snprintf(sb_type,sb_type._width,"'scalar' or 'vector'");
+          }
+          *se = saved_char; cimg::strellipsize(expr,64);
+          throw CImgArgumentException("[_cimg_math_parser] "
+                                      "CImg<%s>::%s(): %s%s %s%s has invalid type '%s' (should be %s), "
+                                      "in expression '%s%s%s'.",
+                                      pixel_type(),_cimg_mp_calling_function,s_op,*s_op?":":"",
+                                      s_arg,*s_op=='F'?(*s_arg?"argument":"Argument"):(*s_arg?"operand":"Operand"),
+                                      s_type(arg)._data,sb_type._data,
+                                      (ss - 4)>expr._data?"...":"",
+                                      (ss - 4)>expr._data?ss - 4:expr._data,
+                                      se<&expr.back()?"...":"");
+        }
+      }
+
+      // Check is listin is not empty.
+      void check_list(const bool is_out,
+                      const char *const ss, char *const se, const char saved_char) {
+        if ((!is_out && !listin) || (is_out && !listout)) {
+          *se = saved_char; cimg::strellipsize(expr,64);
+          throw CImgArgumentException("[_cimg_math_parser] "
+                                      "CImg<%s>::%s(): %s%s Invalid call with an empty image list, "
+                                      "in expression '%s%s%s'.",
+                                      pixel_type(),_cimg_mp_calling_function,s_op,*s_op?":":"",
+                                      (ss - 4)>expr._data?"...":"",
+                                      (ss - 4)>expr._data?ss - 4:expr._data,
+                                      se<&expr.back()?"...":"");
+        }
+      }
+
+      // Check a vector is not 0-dimensional, or with unknown dimension at compile time.
+      void check_vector0(const unsigned int dim,
+                         const char *const ss, char *const se, const char saved_char) {
+        if (!dim) {
+          *se = saved_char; cimg::strellipsize(expr,64);
+          throw CImgArgumentException("[_cimg_math_parser] "
+                                      "CImg<%s>::%s(): %s%s Invalid construction of a 0-dimensional vector, "
+                                      "in expression '%s%s%s'.",
+                                      pixel_type(),_cimg_mp_calling_function,s_op,*s_op?":":"",
+                                      (ss - 4)>expr._data?"...":"",
+                                      (ss - 4)>expr._data?ss - 4:expr._data,
+                                      se<&expr.back()?"...":"");
+        } else if (dim==~0U) {
+          *se = saved_char; cimg::strellipsize(expr,64);
+          throw CImgArgumentException("[_cimg_math_parser] "
+                                      "CImg<%s>::%s(): %s%s Invalid construction of a vector with dynamic size, "
+                                      "in expression '%s%s%s'.",
+                                      pixel_type(),_cimg_mp_calling_function,s_op,*s_op?":":"",
+                                      (ss - 4)>expr._data?"...":"",
+                                      (ss - 4)>expr._data?ss - 4:expr._data,
+                                      se<&expr.back()?"...":"");
+        }
+      }
+
+      // Evaluation functions, known by the parser.
+      // Defining these functions 'static' ensures that sizeof(mp_func)==sizeof(ulongT),
+      // so we can store pointers to them directly in the opcode vectors.
+#ifdef _mp_arg
+#undef _mp_arg
+#endif
+#define _mp_arg(x) mp.mem[mp.opcode[x]]
+
+      static double mp_abs(_cimg_math_parser& mp) {
+        return cimg::abs(_mp_arg(2));
+      }
+
+      static double mp_add(_cimg_math_parser& mp) {
+        return _mp_arg(2) + _mp_arg(3);
+      }
+
+      static double mp_acos(_cimg_math_parser& mp) {
+        return std::acos(_mp_arg(2));
+      }
+
+      static double mp_arg(_cimg_math_parser& mp) {
+        const int _ind = (int)_mp_arg(2);
+        const unsigned int nb_args = mp.opcode._height - 2, ind = _ind<0?_ind + nb_args:(unsigned int)_ind;
+        if (ind>=nb_args) return 0;
+        return _mp_arg(ind + 2);
       }
 
       static double mp_argmin(_cimg_math_parser& mp) {
-        double val = mp.mem[mp.opcode(2)];
+        double val = _mp_arg(2);
         unsigned int argval = 0;
         for (unsigned int i = 3; i<mp.opcode._height; ++i) {
-          const double _val = mp.mem[mp.opcode(i)];
+          const double _val = _mp_arg(i);
           if (_val<val) { val = _val; argval = i - 2; }
         }
         return (double)argval;
       }
 
       static double mp_argmax(_cimg_math_parser& mp) {
-        double val = mp.mem[mp.opcode(2)];
+        double val = _mp_arg(2);
         unsigned int argval = 0;
         for (unsigned int i = 3; i<mp.opcode._height; ++i) {
-          const double _val = mp.mem[mp.opcode(i)];
+          const double _val = _mp_arg(i);
           if (_val>val) { val = _val; argval = i - 2; }
         }
         return (double)argval;
       }
 
+      static double mp_asin(_cimg_math_parser& mp) {
+        return std::asin(_mp_arg(2));
+      }
+
+      static double mp_atan(_cimg_math_parser& mp) {
+        return std::atan(_mp_arg(2));
+      }
+
+      static double mp_atan2(_cimg_math_parser& mp) {
+        return std::atan2(_mp_arg(2),_mp_arg(3));
+      }
+
+      static double mp_bitwise_and(_cimg_math_parser& mp) {
+        return (double)((ulongT)_mp_arg(2) & (ulongT)_mp_arg(3));
+      }
+
+      static double mp_bitwise_left_shift(_cimg_math_parser& mp) {
+        return (double)((longT)_mp_arg(2)<<(unsigned int)_mp_arg(3));
+      }
+
+      static double mp_bitwise_not(_cimg_math_parser& mp) {
+        return (double)~(ulongT)_mp_arg(2);
+      }
+
+      static double mp_bitwise_or(_cimg_math_parser& mp) {
+        return (double)((ulongT)_mp_arg(2) | (ulongT)_mp_arg(3));
+      }
+
+      static double mp_bitwise_right_shift(_cimg_math_parser& mp) {
+        return (double)((longT)_mp_arg(2)>>(unsigned int)_mp_arg(3));
+      }
+
+      static double mp_cbrt(_cimg_math_parser& mp) {
+        return std::pow(_mp_arg(2),1.0/3);
+      }
+
+      static double mp_complex_conj(_cimg_math_parser& mp) {
+        const double *ptrs = &_mp_arg(2) + 1;
+        double *ptrd = &_mp_arg(1) + 1;
+        *(ptrd++) = *(ptrs++);
+        *ptrd = -*(ptrs);
+        return cimg::type<double>::nan();
+      }
+
+      static double mp_complex_div_sv(_cimg_math_parser& mp) {
+        const double
+          *ptr2 = &_mp_arg(3) + 1,
+          r1 = _mp_arg(2),
+          r2 = *(ptr2++), i2 = *ptr2;
+        double *ptrd = &_mp_arg(1) + 1;
+        const double denom = r2*r2 + i2*i2;
+        *(ptrd++) = r1*r2/denom;
+        *ptrd =  -r1*i2/denom;
+        return cimg::type<double>::nan();
+      }
+
+      static double mp_complex_div_vv(_cimg_math_parser& mp) {
+        const double
+          *ptr1 = &_mp_arg(2) + 1, *ptr2 = &_mp_arg(3) + 1,
+          r1 = *(ptr1++), i1 = *ptr1,
+          r2 = *(ptr2++), i2 = *ptr2;
+        double *ptrd = &_mp_arg(1) + 1;
+        const double denom = r2*r2 + i2*i2;
+        *(ptrd++) = (r1*r2 + i1*i2)/denom;
+        *ptrd = (r2*i1 - r1*i2)/denom;
+        return cimg::type<double>::nan();
+      }
+
+      static double mp_complex_exp(_cimg_math_parser& mp) {
+        double *ptrd = &_mp_arg(1) + 1;
+        const double *ptrs = &_mp_arg(2) + 1, r = *(ptrs++), i = *(ptrs), er = std::exp(r);
+        *(ptrd++) = er*std::cos(i);
+        *(ptrd++) = er*std::sin(i);
+        return cimg::type<double>::nan();
+      }
+
+      static double mp_complex_log(_cimg_math_parser& mp) {
+        double *ptrd = &_mp_arg(1) + 1;
+        const double *ptrs = &_mp_arg(2) + 1, r = *(ptrs++), i = *(ptrs);
+        *(ptrd++) = std::log(std::sqrt(r*r + i*i));
+        *(ptrd++) = std::atan2(i,r);
+        return cimg::type<double>::nan();
+      }
+
+      static double mp_complex_mul(_cimg_math_parser& mp) {
+        const double
+          *ptr1 = &_mp_arg(2) + 1, *ptr2 = &_mp_arg(3) + 1,
+          r1 = *(ptr1++), i1 = *ptr1,
+          r2 = *(ptr2++), i2 = *ptr2;
+        double *ptrd = &_mp_arg(1) + 1;
+        *(ptrd++) = r1*r2 - i1*i2;
+        *(ptrd++) = r1*i2 + r2*i1;
+        return cimg::type<double>::nan();
+      }
+
+      static void _mp_complex_pow(const double r1, const double i1,
+                                  const double r2, const double i2,
+                                  double *ptrd) {
+        double ro, io;
+        if (cimg::abs(i2)<1e-15) { // Exponent is real
+          if (cimg::abs(r1)<1e-15 && cimg::abs(i1)<1e-15) {
+            if (cimg::abs(r2)<1e-15) { ro = 1; io = 0; }
+            else ro = io = 0;
+          } else {
+            const double
+              mod1_2 = r1*r1 + i1*i1,
+              phi1 = std::atan2(i1,r1),
+              modo = std::pow(mod1_2,0.5*r2),
+              phio = r2*phi1;
+            ro = modo*std::cos(phio);
+            io = modo*std::sin(phio);
+          }
+        } else { // Exponent is complex
+          if (cimg::abs(r1)<1e-15 && cimg::abs(i1)<1e-15) ro = io = 0;
+          const double
+            mod1_2 = r1*r1 + i1*i1,
+            phi1 = std::atan2(i1,r1),
+            modo = std::pow(mod1_2,0.5*r2)*std::exp(-i2*phi1),
+            phio = r2*phi1 + 0.5*i2*std::log(mod1_2);
+          ro = modo*std::cos(phio);
+          io = modo*std::sin(phio);
+        }
+        *(ptrd++) = ro;
+        *ptrd = io;
+      }
+
+      static double mp_complex_pow_sv(_cimg_math_parser& mp) {
+        const double val1 = _mp_arg(2), *ptr2 = &_mp_arg(3) + 1;
+        double *ptrd = &_mp_arg(1) + 1;
+        _mp_complex_pow(val1,0,ptr2[0],ptr2[1],ptrd);
+        return cimg::type<double>::nan();
+      }
+
+      static double mp_complex_pow_vs(_cimg_math_parser& mp) {
+        const double *ptr1 = &_mp_arg(2) + 1, val2 = _mp_arg(3);
+        double *ptrd = &_mp_arg(1) + 1;
+        _mp_complex_pow(ptr1[0],ptr1[1],val2,0,ptrd);
+        return cimg::type<double>::nan();
+      }
+
+      static double mp_complex_pow_vv(_cimg_math_parser& mp) {
+        const double *ptr1 = &_mp_arg(2) + 1, *ptr2 = &_mp_arg(3) + 1;
+        double *ptrd = &_mp_arg(1) + 1;
+        _mp_complex_pow(ptr1[0],ptr1[1],ptr2[0],ptr2[1],ptrd);
+        return cimg::type<double>::nan();
+      }
+
+      static double mp_cos(_cimg_math_parser& mp) {
+        return std::cos(_mp_arg(2));
+      }
+
+      static double mp_cosh(_cimg_math_parser& mp) {
+        return std::cosh(_mp_arg(2));
+      }
+
+      static double mp_crop(_cimg_math_parser& mp) {
+        double *ptrd = &_mp_arg(1) + 1;
+        const int x = (int)_mp_arg(3), y = (int)_mp_arg(4), z = (int)_mp_arg(5), c = (int)_mp_arg(6);
+        const unsigned int
+          dx = (unsigned int)mp.opcode[7],
+          dy = (unsigned int)mp.opcode[8],
+          dz = (unsigned int)mp.opcode[9],
+          dc = (unsigned int)mp.opcode[10];
+        const bool boundary_conditions = (bool)_mp_arg(11);
+        unsigned int ind = (unsigned int)mp.opcode[2];
+        if (ind!=~0U) ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width());
+        const CImg<T> &img = ind==~0U?mp.imgin:mp.listin[ind];
+        if (!img) std::memset(ptrd,0,dx*dy*dz*dc*sizeof(double));
+        else CImg<double>(ptrd,dx,dy,dz,dc,true) = img.get_crop(x,y,z,c,
+                                                                x + dx - 1,y + dy - 1,
+                                                                z + dz - 1,c + dc - 1,
+                                                                boundary_conditions);
+        return cimg::type<double>::nan();
+      }
+
+      static double mp_cross(_cimg_math_parser& mp) {
+        CImg<doubleT>
+          vout(&_mp_arg(1) + 1,1,3,1,1,true),
+          v1(&_mp_arg(2) + 1,1,3,1,1,true),
+          v2(&_mp_arg(3) + 1,1,3,1,1,true);
+        (vout = v1).cross(v2);
+        return cimg::type<double>::nan();
+      }
+
+      static double mp_cut(_cimg_math_parser& mp) {
+        double val = _mp_arg(2), cmin = _mp_arg(3), cmax = _mp_arg(4);
+        return val<cmin?cmin:val>cmax?cmax:val;
+      }
+
+      static double mp_debug(_cimg_math_parser& mp) {
+        CImg<charT> expr(mp.opcode._height - 3);
+        const ulongT *ptrs = mp.opcode._data + 3;
+        cimg_for(expr,ptrd,char) *ptrd = (char)*(ptrs++);
+        cimg::strellipsize(expr);
+        const ulongT g_target = mp.opcode[1];
+
+#ifndef cimg_use_openmp
+        const unsigned int n_thread = 0;
+#else
+        const unsigned int n_thread = omp_get_thread_num();
+#pragma omp critical
+#endif
+        {
+          std::fprintf(cimg::output(),
+                       "\n[_cimg_math_parser] %p[thread #%u]:%*c"
+                       "Start debugging expression '%s', code length %u -> mem[%u] (memsize: %u)",
+                       (void*)&mp,n_thread,mp.debug_indent,' ',
+                       expr._data,(unsigned int)mp.opcode[2],(unsigned int)g_target,mp.mem._width);
+          std::fflush(cimg::output());
+          const CImg<ulongT> *const p_end = (++mp.p_code) + mp.opcode[2];
+          CImg<ulongT> _op;
+          mp.debug_indent+=3;
+          for ( ; mp.p_code<p_end; ++mp.p_code) {
+            const CImg<ulongT> &op = *mp.p_code;
+            mp.opcode._data = op._data; mp.opcode._height = op._height;
+
+            _op.assign(1,op._height - 1);
+            const ulongT *ptrs = op._data + 1;
+            for (ulongT *ptrd = _op._data, *const ptrde = _op._data + _op._height; ptrd<ptrde; ++ptrd)
+              *ptrd = *(ptrs++);
+
+            const ulongT target = mp.opcode[1];
+            mp.mem[target] = _cimg_mp_defunc(mp);
+            std::fprintf(cimg::output(),
+                         "\n[_cimg_math_parser] %p[thread #%u]:%*c"
+                         "Opcode %p = [ %p,%s ] -> mem[%u] = %g",
+                         (void*)&mp,n_thread,mp.debug_indent,' ',
+                         (void*)mp.opcode._data,(void*)*mp.opcode,_op.value_string().data(),
+                         (unsigned int)target,mp.mem[target]);
+            std::fflush(cimg::output());
+          }
+          mp.debug_indent-=3;
+          std::fprintf(cimg::output(),
+                       "\n[_cimg_math_parser] %p[thread #%u]:%*c"
+                       "End debugging expression '%s' -> mem[%u] = %g (memsize: %u)",
+                       (void*)&mp,n_thread,mp.debug_indent,' ',
+                       expr._data,(unsigned int)g_target,mp.mem[g_target],mp.mem._width);
+          std::fflush(cimg::output());
+          --mp.p_code;
+        }
+        return mp.mem[g_target];
+      }
+
+      static double mp_decrement(_cimg_math_parser& mp) {
+        return _mp_arg(2) - 1;
+      }
+
+      static double mp_det(_cimg_math_parser& mp) {
+        const double *ptrs = &_mp_arg(2) + 1;
+        const unsigned int k = (unsigned int)mp.opcode(3);
+        return CImg<double>(ptrs,k,k,1,1,true).det();
+      }
+
+      static double mp_diag(_cimg_math_parser& mp) {
+        double *ptrd = &_mp_arg(1) + 1;
+        const double *ptrs = &_mp_arg(2) + 1;
+        const unsigned int k = (unsigned int)mp.opcode(3);
+        CImg<double>(ptrd,k,k,1,1,true) = CImg<double>(ptrs,1,k,1,1,true).get_diagonal();
+        return cimg::type<double>::nan();
+      }
+
+      static double mp_div(_cimg_math_parser& mp) {
+        return _mp_arg(2)/_mp_arg(3);
+      }
+
+      static double mp_dot(_cimg_math_parser& mp) {
+        const unsigned int siz = (unsigned int)mp.opcode[4];
+        return CImg<doubleT>(&_mp_arg(2) + 1,1,siz,1,1,true).
+          dot(CImg<doubleT>(&_mp_arg(3) + 1,1,siz,1,1,true));
+      }
+
+      static double mp_dowhile(_cimg_math_parser& mp) {
+        const ulongT
+          mem_proc = mp.opcode[1],
+          mem_cond = mp.opcode[2];
+        const CImg<ulongT>
+          *const p_proc = ++mp.p_code,
+          *const p_end = p_proc + mp.opcode[3];
+        do {
+          for (mp.p_code = p_proc; mp.p_code<p_end; ++mp.p_code) { // Evaluate loop iteration + condition
+            const CImg<ulongT> &op = *mp.p_code;
+            mp.opcode._data = op._data; mp.opcode._height = op._height;
+            const ulongT target = mp.opcode[1];
+            mp.mem[target] = _cimg_mp_defunc(mp);
+          }
+        } while (mp.mem[mem_cond]);
+        --mp.p_code;
+        return mp.mem[mem_proc];
+      }
+
+      static double mp_draw(_cimg_math_parser& mp) {
+        const int x = (int)_mp_arg(3), y = (int)_mp_arg(4), z = (int)_mp_arg(5), c = (int)_mp_arg(6);
+        const unsigned int
+          dx = (unsigned int)mp.opcode[7],
+          dy = (unsigned int)mp.opcode[8],
+          dz = (unsigned int)mp.opcode[9],
+          dc = (unsigned int)mp.opcode[10];
+        const CImg<double> S(&_mp_arg(1) + 1,dx,dy,dz,dc,true);
+        const float opacity = (float)_mp_arg(11);
+        unsigned int ind = (unsigned int)mp.opcode[2];
+        if (ind!=~0U) ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width());
+        CImg<T> &img = ind==~0U?mp.imgout:mp.listout[ind];
+        if (img) {
+          if (mp.opcode[12]!=(ulongT)-1) {
+            const CImg<double> M(&_mp_arg(12) + 1,dx,dy,dz,(unsigned int)mp.opcode[13],true);
+            img.draw_image(x,y,z,c,S,M,opacity,(float)_mp_arg(14));
+          } else img.draw_image(x,y,z,c,S,opacity);
+        }
+        return cimg::type<double>::nan();
+      }
+
+      static double mp_eig(_cimg_math_parser& mp) {
+        double *ptrd = &_mp_arg(1) + 1;
+        const double *ptr1 = &_mp_arg(2) + 1;
+        const unsigned int k = (unsigned int)mp.opcode(3);
+        CImg<double> val, vec;
+        CImg<double>(ptr1,k,k,1,1,true).symmetric_eigen(val,vec);
+        CImg<double>(ptrd,k,1,1,1,true) = val.unroll('x');
+        CImg<double>(ptrd + k,k,k,1,1,true) = vec.get_transpose();
+        return cimg::type<double>::nan();
+      }
+
+      static double mp_eq(_cimg_math_parser& mp) {
+        return (double)(_mp_arg(2)==_mp_arg(3));
+      }
+
+      static double mp_exp(_cimg_math_parser& mp) {
+        return std::exp(_mp_arg(2));
+      }
+
+      static double mp_eye(_cimg_math_parser& mp) {
+        double *ptrd = &_mp_arg(1) + 1;
+        const unsigned int k = (unsigned int)mp.opcode(2);
+        CImg<double>(ptrd,k,k,1,1,true).identity_matrix();
+        return cimg::type<double>::nan();
+      }
+
+      static double mp_g(_cimg_math_parser& mp) {
+        cimg::unused(mp);
+        return cimg::grand();
+      }
+
+      static double mp_gauss(_cimg_math_parser& mp) {
+        const double x = _mp_arg(2), s = _mp_arg(3);
+        return std::exp(-x*x/(2*s*s))/std::sqrt(2*s*s*cimg::PI);
+      }
+
+      static double mp_gt(_cimg_math_parser& mp) {
+        return (double)(_mp_arg(2)>_mp_arg(3));
+      }
+
+      static double mp_gte(_cimg_math_parser& mp) {
+        return (double)(_mp_arg(2)>=_mp_arg(3));
+      }
+
+      static double mp_hypot(_cimg_math_parser& mp) {
+        return cimg::hypot(_mp_arg(2),_mp_arg(3));
+      }
+
+      static double mp_i(_cimg_math_parser& mp) {
+        return (double)mp.imgin.atXYZC((int)mp.mem[_cimg_mp_x],(int)mp.mem[_cimg_mp_y],
+                                       (int)mp.mem[_cimg_mp_z],(int)mp.mem[_cimg_mp_c],0);
+      }
+
+      static double mp_if(_cimg_math_parser& mp) {
+        const bool is_cond = (bool)_mp_arg(2);
+        const ulongT
+          mem_left = mp.opcode[3],
+          mem_right = mp.opcode[4];
+        const CImg<ulongT>
+          *const p_right = ++mp.p_code + mp.opcode[5],
+          *const p_end = p_right + mp.opcode[6];
+        const unsigned int vtarget = mp.opcode[1], vsiz = mp.opcode[7];
+        if (is_cond) {
+          for ( ; mp.p_code<p_right; ++mp.p_code) {
+            const CImg<ulongT> &op = *mp.p_code;
+            mp.opcode._data = op._data; mp.opcode._height = op._height;
+            const ulongT target = mp.opcode[1];
+            mp.mem[target] = _cimg_mp_defunc(mp);
+          }
+          mp.p_code = p_end - 1;
+          if (vsiz) std::memcpy(&mp.mem[vtarget] + 1,&mp.mem[mem_left] + 1,sizeof(double)*vsiz);
+          return mp.mem[mem_left];
+        }
+        for (mp.p_code = p_right; mp.p_code<p_end; ++mp.p_code) {
+          const CImg<ulongT> &op = *mp.p_code;
+          mp.opcode._data = op._data; mp.opcode._height = op._height;
+          const ulongT target = mp.opcode[1];
+          mp.mem[target] = _cimg_mp_defunc(mp);
+        }
+        --mp.p_code;
+        if (vsiz) std::memcpy(&mp.mem[vtarget] + 1,&mp.mem[mem_right] + 1,sizeof(double)*vsiz);
+        return mp.mem[mem_right];
+      }
+
+      static double mp_increment(_cimg_math_parser& mp) {
+        return _mp_arg(2) + 1;
+      }
+
+      static double mp_int(_cimg_math_parser& mp) {
+        return (double)(longT)_mp_arg(2);
+      }
+
+      static double mp_inv(_cimg_math_parser& mp) {
+        double *ptrd = &_mp_arg(1) + 1;
+        const double *ptr1 = &_mp_arg(2) + 1;
+        const unsigned int k = (unsigned int)mp.opcode(3);
+        CImg<double>(ptrd,k,k,1,1,true) = CImg<double>(ptr1,k,k,1,1,true).get_invert();
+        return cimg::type<double>::nan();
+      }
+
+      static double mp_ioff(_cimg_math_parser& mp) {
+        const unsigned int
+          boundary_conditions = (unsigned int)_mp_arg(3);
+        const CImg<T> &img = mp.imgin;
+        const longT
+          off = (longT)_mp_arg(2),
+          whds = (longT)img.size();
+        if (off<0 || off>=whds)
+          switch (boundary_conditions) {
+          case 2 : // Periodic boundary
+            if (img) return (double)img[cimg::mod(off,whds)];
+            return 0;
+          case 1 : // Neumann boundary
+            if (img) return (double)(off<0?*img:img.back());
+            return 0;
+          default : // Dirichet boundary
+            return 0;
+          }
+        return (double)img[off];
+      }
+
+      static double mp_isbool(_cimg_math_parser& mp) {
+        const double val = _mp_arg(2);
+        return (double)(val==0.0 || val==1.0);
+      }
+
       static double mp_isin(_cimg_math_parser& mp) {
-        double value = mp.mem[mp.opcode(2)];
+        const double val = _mp_arg(2);
         for (unsigned int i = 3; i<mp.opcode._height; ++i)
-          if (value==mp.mem[mp.opcode(i)]) return 1.0;
+          if (val==_mp_arg(i)) return 1.0;
         return 0.0;
       }
 
+      static double mp_isinf(_cimg_math_parser& mp) {
+        return (double)cimg::type<double>::is_inf(_mp_arg(2));
+      }
+
+      static double mp_isint(_cimg_math_parser& mp) {
+        return (double)(cimg::mod(_mp_arg(2),1.0)==0);
+      }
+
       static double mp_isnan(_cimg_math_parser& mp) {
-        const double val = mp.mem[mp.opcode(2)];
-        return cimg::type<double>::is_nan(val);
+        return (double)cimg::type<double>::is_nan(_mp_arg(2));
       }
 
-      static double mp_isinf(_cimg_math_parser& mp) {
-        const double val = mp.mem[mp.opcode(2)];
-        return cimg::type<double>::is_inf(val);
+      static double mp_ixyzc(_cimg_math_parser& mp) {
+        const unsigned int
+          interpolation = (unsigned int)_mp_arg(6),
+          boundary_conditions = (unsigned int)_mp_arg(7);
+        const CImg<T> &img = mp.imgin;
+        const double
+          x = _mp_arg(2), y = _mp_arg(3),
+          z = _mp_arg(4), c = _mp_arg(5);
+        if (interpolation==0) { // Nearest neighbor interpolation
+          if (boundary_conditions==2)
+            return (double)img.atXYZC(cimg::mod((int)x,img.width()),
+                                      cimg::mod((int)y,img.height()),
+                                      cimg::mod((int)z,img.depth()),
+                                      cimg::mod((int)c,img.spectrum()));
+          if (boundary_conditions==1)
+            return (double)img.atXYZC((int)x,(int)y,(int)z,(int)c);
+          return (double)img.atXYZC((int)x,(int)y,(int)z,(int)c,0);
+        } else { // Linear interpolation
+          if (boundary_conditions==2)
+            return (double)img.linear_atXYZC(cimg::mod((float)x,(float)img.width()),
+                                             cimg::mod((float)y,(float)img.height()),
+                                             cimg::mod((float)z,(float)img.depth()),
+                                             cimg::mod((float)c,(float)img.spectrum()));
+          if (boundary_conditions==1)
+            return (double)img.linear_atXYZC((float)x,(float)y,(float)z,(float)c);
+          return (double)img.linear_atXYZC((float)x,(float)y,(float)z,(float)c,0);
+        }
       }
 
-      static double mp_isint(_cimg_math_parser& mp) {
-        const double val = mp.mem[mp.opcode(2)];
-        return (double)(cimg::mod(val,1.0)==0);
+      static double mp_joff(_cimg_math_parser& mp) {
+        const unsigned int
+          boundary_conditions = (unsigned int)_mp_arg(3);
+        const int
+          ox = (int)mp.mem[_cimg_mp_x], oy = (int)mp.mem[_cimg_mp_y],
+          oz = (int)mp.mem[_cimg_mp_z], oc = (int)mp.mem[_cimg_mp_c];
+        const CImg<T> &img = mp.imgin;
+        const longT
+          off = img.offset(ox,oy,oz,oc) + (longT)_mp_arg(2),
+          whds = (longT)img.size();
+        if (off<0 || off>=whds)
+          switch (boundary_conditions) {
+          case 2 : // Periodic boundary
+            if (img) return (double)img[cimg::mod(off,whds)];
+            return 0;
+          case 1 : // Neumann boundary
+            if (img) return (double)(off<0?*img:img.back());
+            return 0;
+          default : // Dirichet boundary
+            return 0;
+          }
+        return (double)img[off];
       }
 
-      static double mp_isbool(_cimg_math_parser& mp) {
-        const double val = mp.mem[mp.opcode(2)];
-        return (val==0.0 || val==1.0);
+      static double mp_jxyzc(_cimg_math_parser& mp) {
+        const unsigned int
+          interpolation = (unsigned int)_mp_arg(6),
+          boundary_conditions = (unsigned int)_mp_arg(7);
+        const CImg<T> &img = mp.imgin;
+        const double
+          ox = mp.mem[_cimg_mp_x], oy = mp.mem[_cimg_mp_y],
+          oz = mp.mem[_cimg_mp_z], oc = mp.mem[_cimg_mp_c],
+          x = ox + _mp_arg(2), y = oy + _mp_arg(3),
+          z = oz + _mp_arg(4), c = oc + _mp_arg(5);
+        if (interpolation==0) { // Nearest neighbor interpolation
+          if (boundary_conditions==2)
+            return (double)img.atXYZC(cimg::mod((int)x,img.width()),
+                                      cimg::mod((int)y,img.height()),
+                                      cimg::mod((int)z,img.depth()),
+                                      cimg::mod((int)c,img.spectrum()));
+          if (boundary_conditions==1)
+            return (double)img.atXYZC((int)x,(int)y,(int)z,(int)c);
+          return (double)img.atXYZC((int)x,(int)y,(int)z,(int)c,0);
+        } else { // Linear interpolation
+          if (boundary_conditions==2)
+            return (double)img.linear_atXYZC(cimg::mod((float)x,(float)img.width()),
+                                             cimg::mod((float)y,(float)img.height()),
+                                             cimg::mod((float)z,(float)img.depth()),
+                                             cimg::mod((float)c,(float)img.spectrum()));
+          if (boundary_conditions==1)
+            return (double)img.linear_atXYZC((float)x,(float)y,(float)z,(float)c);
+          return (double)img.linear_atXYZC((float)x,(float)y,(float)z,(float)c,0);
+        }
+      }
+
+      static double mp_kth(_cimg_math_parser& mp) {
+        CImg<doubleT> vals(mp.opcode._height - 3);
+        double *p = vals.data();
+        for (unsigned int i = 3; i<mp.opcode._height; ++i) *(p++) = _mp_arg(i);
+        int ind = (int)cimg::round(_mp_arg(2));
+        if (ind<0) ind+=vals.width() + 1;
+        ind = cimg::max(1,cimg::min(vals.width(),ind));
+        return vals.kth_smallest(ind - 1);
+      }
+
+      static double mp_list_depth(_cimg_math_parser& mp) {
+        const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width());
+        return (double)mp.listin[ind]._depth;
+      }
+
+      static double mp_list_height(_cimg_math_parser& mp) {
+        const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width());
+        return (double)mp.listin[ind]._height;
+      }
+
+      static double mp_list_ioff(_cimg_math_parser& mp) {
+        const unsigned int
+          ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()),
+          boundary_conditions = (unsigned int)_mp_arg(4);
+        const CImg<T> &img = mp.listin[ind];
+        const longT
+          off = (longT)_mp_arg(3),
+          whds = (longT)img.size();
+        if (off<0 || off>=whds)
+          switch (boundary_conditions) {
+          case 2 : // Periodic boundary
+            if (img) return (double)img[cimg::mod(off,whds)];
+            return 0;
+          case 1 : // Neumann boundary
+            if (img) return (double)(off<0?*img:img.back());
+            return 0;
+          default : // Dirichet boundary
+            return 0;
+          }
+        return (double)img[off];
+      }
+
+      static double mp_list_is_shared(_cimg_math_parser& mp) {
+        const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width());
+        return (double)mp.listin[ind]._is_shared;
+      }
+
+      static double mp_list_ixyzc(_cimg_math_parser& mp) {
+        const unsigned int
+          ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()),
+          interpolation = (unsigned int)_mp_arg(7),
+          boundary_conditions = (unsigned int)_mp_arg(8);
+        const CImg<T> &img = mp.listin[ind];
+        const double
+          x = _mp_arg(3), y = _mp_arg(4),
+          z = _mp_arg(5), c = _mp_arg(6);
+        if (interpolation==0) { // Nearest neighbor interpolation
+          if (boundary_conditions==2)
+            return (double)img.atXYZC(cimg::mod((int)x,img.width()),
+                                      cimg::mod((int)y,img.height()),
+                                      cimg::mod((int)z,img.depth()),
+                                      cimg::mod((int)c,img.spectrum()));
+          if (boundary_conditions==1)
+            return (double)img.atXYZC((int)x,(int)y,(int)z,(int)c);
+          return (double)img.atXYZC((int)x,(int)y,(int)z,(int)c,0);
+        } else { // Linear interpolation
+          if (boundary_conditions==2)
+            return (double)img.linear_atXYZC(cimg::mod((float)x,(float)img.width()),
+                                             cimg::mod((float)y,(float)img.height()),
+                                             cimg::mod((float)z,(float)img.depth()),
+                                             cimg::mod((float)c,(float)img.spectrum()));
+          if (boundary_conditions==1)
+            return (double)img.linear_atXYZC((float)x,(float)y,(float)z,(float)c);
+          return (double)img.linear_atXYZC((float)x,(float)y,(float)z,(float)c,0);
+        }
+      }
+
+      static double mp_list_joff(_cimg_math_parser& mp) {
+        const unsigned int
+          ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()),
+          boundary_conditions = (unsigned int)_mp_arg(4);
+        const int
+          ox = (int)mp.mem[_cimg_mp_x], oy = (int)mp.mem[_cimg_mp_y],
+          oz = (int)mp.mem[_cimg_mp_z], oc = (int)mp.mem[_cimg_mp_c];
+        const CImg<T> &img = mp.listin[ind];
+        const longT
+          off = img.offset(ox,oy,oz,oc) + (longT)_mp_arg(3),
+          whds = (longT)img.size();
+        if (off<0 || off>=whds)
+          switch (boundary_conditions) {
+          case 2 : // Periodic boundary
+            if (img) return (double)img(ind,cimg::mod(off,whds));
+            return 0;
+          case 1 : // Neumann boundary
+            if (img) return (double)(off<0?*img:img.back());
+            return 0;
+          default : // Dirichet boundary
+            return 0;
+          }
+        return (double)img[off];
+      }
+
+      static double mp_list_jxyzc(_cimg_math_parser& mp) {
+        const unsigned int
+          ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()),
+          interpolation = (unsigned int)_mp_arg(7),
+          boundary_conditions = (unsigned int)_mp_arg(8);
+        const CImg<T> &img = mp.listin[ind];
+        const double
+          ox = mp.mem[_cimg_mp_x], oy = mp.mem[_cimg_mp_y],
+          oz = mp.mem[_cimg_mp_z], oc = mp.mem[_cimg_mp_c],
+          x = ox + _mp_arg(3), y = oy + _mp_arg(4),
+          z = oz + _mp_arg(5), c = oc + _mp_arg(6);
+        if (interpolation==0) { // Nearest neighbor interpolation
+          if (boundary_conditions==2)
+            return (double)img.atXYZC(cimg::mod((int)x,img.width()),
+                                      cimg::mod((int)y,img.height()),
+                                      cimg::mod((int)z,img.depth()),
+                                      cimg::mod((int)c,img.spectrum()));
+          if (boundary_conditions==1)
+            return (double)img.atXYZC((int)x,(int)y,(int)z,(int)c);
+          return (double)img.atXYZC((int)x,(int)y,(int)z,(int)c,0);
+        } else { // Linear interpolation
+          if (boundary_conditions==2)
+            return (double)img.linear_atXYZC(cimg::mod((float)x,(float)img.width()),
+                                             cimg::mod((float)y,(float)img.height()),
+                                             cimg::mod((float)z,(float)img.depth()),
+                                             cimg::mod((float)c,(float)img.spectrum()));
+          if (boundary_conditions==1)
+            return (double)img.linear_atXYZC((float)x,(float)y,(float)z,(float)c);
+          return (double)img.linear_atXYZC((float)x,(float)y,(float)z,(float)c,0);
+        }
+      }
+
+      static double mp_list_median(_cimg_math_parser& mp) {
+        const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width());
+        if (!mp.list_median) mp.list_median.assign(mp.listin._width);
+        if (!mp.list_median[ind]) CImg<doubleT>::vector(mp.listin[ind].median()).move_to(mp.list_median[ind]);
+        return *mp.list_median[ind];
+      }
+
+      static double mp_list_set_ioff(_cimg_math_parser& mp) {
+        const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width());
+        CImg<T> &img = mp.listout[ind];
+        const longT
+          off = (longT)_mp_arg(3),
+          whds = (longT)img.size();
+        const double val = _mp_arg(1);
+        if (off>=0 && off<whds) img[off] = (T)val;
+        return val;
+      }
+
+      static double mp_list_set_ixyzc(_cimg_math_parser& mp) {
+        const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width());
+        CImg<T> &img = mp.listout[ind];
+        const int
+          x = (int)_mp_arg(3), y = (int)_mp_arg(4),
+          z = (int)_mp_arg(5), c = (int)_mp_arg(6);
+        const double val = _mp_arg(1);
+        if (x>=0 && x<img.width() && y>=0 && y<img.height() &&
+            z>=0 && z<img.depth() && c>=0 && c<img.spectrum())
+          img(x,y,z,c) = (T)val;
+        return val;
+      }
+
+      static double mp_list_set_joff(_cimg_math_parser& mp) {
+        const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width());
+        CImg<T> &img = mp.listout[ind];
+        const int
+          ox = (int)mp.mem[_cimg_mp_x], oy = (int)mp.mem[_cimg_mp_y],
+          oz = (int)mp.mem[_cimg_mp_z], oc = (int)mp.mem[_cimg_mp_c];
+        const longT
+          off = img.offset(ox,oy,oz,oc) + (longT)_mp_arg(3),
+          whds = (longT)img.size();
+        const double val = _mp_arg(1);
+        if (off>=0 && off<whds) img[off] = (T)val;
+        return val;
+      }
+
+      static double mp_list_set_jxyzc(_cimg_math_parser& mp) {
+        const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width());
+        CImg<T> &img = mp.listout[ind];
+        const double
+          ox = mp.mem[_cimg_mp_x], oy = mp.mem[_cimg_mp_y],
+          oz = mp.mem[_cimg_mp_z], oc = mp.mem[_cimg_mp_c];
+        const int
+          x = (int)(ox + _mp_arg(3)), y = (int)(oy + _mp_arg(4)),
+          z = (int)(oz + _mp_arg(5)), c = (int)(oc + _mp_arg(6));
+        const double val = _mp_arg(1);
+        if (x>=0 && x<img.width() && y>=0 && y<img.height() &&
+            z>=0 && z<img.depth() && c>=0 && c<img.spectrum())
+          img(x,y,z,c) = (T)val;
+        return val;
+      }
+
+      static double mp_list_set_Ioff_s(_cimg_math_parser& mp) {
+        const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width());
+        CImg<T> &img = mp.listout[ind];
+        const longT
+          off = (longT)_mp_arg(3),
+          whd = (longT)img.width()*img.height()*img.depth();
+        const T val = (T)_mp_arg(1);
+        if (off>=0 && off<whd) {
+          T *ptrd = &img[off];
+          cimg_forC(img,c) { *ptrd = val; ptrd+=whd; }
+        }
+        return _mp_arg(1);
+      }
+
+      static double mp_list_set_Ioff_v(_cimg_math_parser& mp) {
+        const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width());
+        CImg<T> &img = mp.listout[ind];
+        const longT
+          off = (longT)_mp_arg(3),
+          whd = (longT)img.width()*img.height()*img.depth();
+        const double *ptrs = &_mp_arg(1) + 1;
+        if (off>=0 && off<whd) {
+          T *ptrd = &img[off];
+          cimg_forC(img,c) { *ptrd = (T)*(ptrs++); ptrd+=whd; }
+        }
+        return cimg::type<double>::nan();
+      }
+
+      static double mp_list_set_Ixyz_s(_cimg_math_parser& mp) {
+        const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width());
+        CImg<T> &img = mp.listout[ind];
+        const int x = (int)_mp_arg(3), y = (int)_mp_arg(4), z = (int)_mp_arg(5);
+        const T val = (T)_mp_arg(1);
+        if (x>=0 && x<img.width() && y>=0 && y<img.height() && z>=0 && z<img.depth()) {
+          T *ptrd = &img(x,y,z);
+          const ulongT whd = (ulongT)img._width*img._height*img._depth;
+          cimg_forC(img,c) { *ptrd = val; ptrd+=whd; }
+        }
+        return _mp_arg(1);
+      }
+
+      static double mp_list_set_Ixyz_v(_cimg_math_parser& mp) {
+        const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width());
+        CImg<T> &img = mp.listout[ind];
+        const int x = (int)_mp_arg(3), y = (int)_mp_arg(4), z = (int)_mp_arg(5);
+        const double *ptrs = &_mp_arg(1) + 1;
+        if (x>=0 && x<img.width() && y>=0 && y<img.height() && z>=0 && z<img.depth()) {
+          T *ptrd = &img(x,y,z);
+          const ulongT whd = (ulongT)img._width*img._height*img._depth;
+          cimg_forC(img,c) { *ptrd = (T)*(ptrs++); ptrd+=whd; }
+        }
+        return cimg::type<double>::nan();
+      }
+
+      static double mp_list_set_Joff_s(_cimg_math_parser& mp) {
+        const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width());
+        CImg<T> &img = mp.listout[ind];
+        const int
+          ox = (int)mp.mem[_cimg_mp_x], oy = (int)mp.mem[_cimg_mp_y],
+          oz = (int)mp.mem[_cimg_mp_z], oc = (int)mp.mem[_cimg_mp_c];
+        const longT
+          off = img.offset(ox,oy,oz,oc) + (longT)_mp_arg(3),
+          whd = (longT)img.width()*img.height()*img.depth();
+        const T val = (T)_mp_arg(1);
+        if (off>=0 && off<whd) {
+          T *ptrd = &img[off];
+          cimg_forC(img,c) { *ptrd = val; ptrd+=whd; }
+        }
+        return _mp_arg(1);
+      }
+
+      static double mp_list_set_Joff_v(_cimg_math_parser& mp) {
+        const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width());
+        CImg<T> &img = mp.listout[ind];
+        const int
+          ox = (int)mp.mem[_cimg_mp_x], oy = (int)mp.mem[_cimg_mp_y],
+          oz = (int)mp.mem[_cimg_mp_z], oc = (int)mp.mem[_cimg_mp_c];
+        const longT
+          off = img.offset(ox,oy,oz,oc) + (longT)_mp_arg(3),
+          whd = (longT)img.width()*img.height()*img.depth();
+        const double *ptrs = &_mp_arg(1) + 1;
+        if (off>=0 && off<whd) {
+          T *ptrd = &img[off];
+          cimg_forC(img,c) { *ptrd = (T)*(ptrs++); ptrd+=whd; }
+        }
+        return cimg::type<double>::nan();
+      }
+
+      static double mp_list_set_Jxyz_s(_cimg_math_parser& mp) {
+        const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width());
+        CImg<T> &img = mp.listout[ind];
+        const double ox = mp.mem[_cimg_mp_x], oy = mp.mem[_cimg_mp_y], oz = mp.mem[_cimg_mp_z];
+        const int x = (int)(ox + _mp_arg(3)), y = (int)(oy + _mp_arg(4)), z = (int)(oz + _mp_arg(5));
+        const T val = (T)_mp_arg(1);
+        if (x>=0 && x<img.width() && y>=0 && y<img.height() && z>=0 && z<img.depth()) {
+          T *ptrd = &img(x,y,z);
+          const ulongT whd = (ulongT)img._width*img._height*img._depth;
+          cimg_forC(img,c) { *ptrd = val; ptrd+=whd; }
+        }
+        return _mp_arg(1);
+      }
+
+      static double mp_list_set_Jxyz_v(_cimg_math_parser& mp) {
+        const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width());
+        CImg<T> &img = mp.listout[ind];
+        const double ox = mp.mem[_cimg_mp_x], oy = mp.mem[_cimg_mp_y], oz = mp.mem[_cimg_mp_z];
+        const int x = (int)(ox + _mp_arg(3)), y = (int)(oy + _mp_arg(4)), z = (int)(oz + _mp_arg(5));
+        const double *ptrs = &_mp_arg(1) + 1;
+        if (x>=0 && x<img.width() && y>=0 && y<img.height() && z>=0 && z<img.depth()) {
+          T *ptrd = &img(x,y,z);
+          const ulongT whd = (ulongT)img._width*img._height*img._depth;
+          cimg_forC(img,c) { *ptrd = (T)*(ptrs++); ptrd+=whd; }
+        }
+        return cimg::type<double>::nan();
+      }
+
+      static double mp_list_spectrum(_cimg_math_parser& mp) {
+        const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width());
+        return (double)mp.listin[ind]._spectrum;
+      }
+
+      static double mp_list_stats(_cimg_math_parser& mp) {
+        const unsigned int
+          ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()),
+          k = (unsigned int)_mp_arg(3);
+        if (!mp.list_stats) mp.list_stats.assign(mp.listin._width);
+        if (!mp.list_stats[ind]) mp.list_stats[ind].assign(1,14,1,1,0).fill(mp.listin[ind].get_stats(),false);
+        return mp.list_stats(ind,k);
+      }
+
+      static double mp_list_wh(_cimg_math_parser& mp) {
+        const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width());
+        return (double)mp.listin[ind]._width*mp.listin[ind]._height;
+      }
+
+      static double mp_list_whd(_cimg_math_parser& mp) {
+        const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width());
+        return (double)mp.listin[ind]._width*mp.listin[ind]._height*mp.listin[ind]._depth;
+      }
+
+      static double mp_list_whds(_cimg_math_parser& mp) {
+        const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width());
+        return (double)mp.listin[ind]._width*mp.listin[ind]._height*mp.listin[ind]._depth*mp.listin[ind]._spectrum;
+      }
+
+      static double mp_list_width(_cimg_math_parser& mp) {
+        const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width());
+        return (double)mp.listin[ind]._width;
+      }
+
+      static double mp_list_Ioff(_cimg_math_parser& mp) {
+        double *ptrd = &_mp_arg(1) + 1;
+        const unsigned int
+          ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()),
+          boundary_conditions = (unsigned int)_mp_arg(4);
+        const CImg<T> &img = mp.listin[ind];
+        const longT
+          off = (longT)_mp_arg(3),
+          whd = (longT)img.width()*img.height()*img.depth();
+        const T *ptrs;
+        if (off<0 || off>=whd)
+          switch (boundary_conditions) {
+          case 2 : // Periodic boundary
+            if (!img) {
+              ptrs = &img[cimg::mod(off,whd)];
+              cimg_forC(img,c) { *(ptrd++) = *ptrs; ptrs+=whd; }
+            } else std::memset(ptrd,0,img._spectrum*sizeof(double));
+            return cimg::type<double>::nan();
+          case 1 : // Neumann boundary
+            if (img) {
+              ptrs = off<0?img._data:&img.back();
+              cimg_forC(img,c) { *(ptrd++) = *ptrs; ptrs+=whd; }
+            } else std::memset(ptrd,0,img._spectrum*sizeof(double));
+            return cimg::type<double>::nan();
+          default : // Dirichet boundary
+            std::memset(ptrd,0,img._spectrum*sizeof(double));
+            return cimg::type<double>::nan();
+          }
+        ptrs = &img[off];
+        cimg_forC(img,c) { *(ptrd++) = *ptrs; ptrs+=whd; }
+        return cimg::type<double>::nan();
+      }
+
+      static double mp_list_Ixyz(_cimg_math_parser& mp) {
+        double *ptrd = &_mp_arg(1) + 1;
+        const unsigned int
+          ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()),
+          interpolation = (unsigned int)_mp_arg(6),
+          boundary_conditions = (unsigned int)_mp_arg(7);
+        const CImg<T> &img = mp.listin[ind];
+        const double x = _mp_arg(3), y = _mp_arg(4), z = _mp_arg(5);
+        if (interpolation==0) { // Nearest neighbor interpolation
+          if (boundary_conditions==2)
+            cimg_forC(img,c)
+              *(ptrd++) = (double)img.atXYZ(cimg::mod((int)x,img.width()),
+                                            cimg::mod((int)y,img.height()),
+                                            cimg::mod((int)z,img.depth()),
+                                            c);
+          else if (boundary_conditions==1)
+            cimg_forC(img,c)
+              *(ptrd++) = (double)img.atXYZ((int)x,(int)y,(int)z,c);
+          else
+            cimg_forC(img,c)
+              *(ptrd++) = (double)img.atXYZ((int)x,(int)y,(int)z,c,0);
+        } else { // Linear interpolation
+          if (boundary_conditions==2)
+            cimg_forC(img,c)
+              *(ptrd++) = (double)img.linear_atXYZ(cimg::mod((float)x,(float)img.width()),
+                                                   cimg::mod((float)y,(float)img.height()),
+                                                   cimg::mod((float)z,(float)img.depth()),c);
+          else if (boundary_conditions==1)
+            cimg_forC(img,c)
+              *(ptrd++) = (double)img.linear_atXYZ((float)x,(float)y,(float)z,c);
+          else
+            cimg_forC(img,c)
+              *(ptrd++) = (double)img.linear_atXYZ((float)x,(float)y,(float)z,c,0);
+        }
+        return cimg::type<double>::nan();
+      }
+
+      static double mp_list_Joff(_cimg_math_parser& mp) {
+        double *ptrd = &_mp_arg(1) + 1;
+        const unsigned int
+          ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()),
+          boundary_conditions = (unsigned int)_mp_arg(4);
+        const int
+          ox = (int)mp.mem[_cimg_mp_x], oy = (int)mp.mem[_cimg_mp_y], oz = (int)mp.mem[_cimg_mp_z];
+        const CImg<T> &img = mp.listin[ind];
+        const longT
+          off = img.offset(ox,oy,oz) + (longT)_mp_arg(3),
+          whd = (longT)img.width()*img.height()*img.depth();
+        const T *ptrs;
+        if (off<0 || off>=whd)
+          switch (boundary_conditions) {
+          case 2 : // Periodic boundary
+            if (!img) {
+              ptrs = &img[cimg::mod(off,whd)];
+              cimg_forC(img,c) { *(ptrd++) = *ptrs; ptrs+=whd; }
+            } else std::memset(ptrd,0,img._spectrum*sizeof(double));
+            return cimg::type<double>::nan();
+          case 1 : // Neumann boundary
+            if (img) {
+              ptrs = off<0?img._data:&img.back();
+              cimg_forC(img,c) { *(ptrd++) = *ptrs; ptrs+=whd; }
+            } else std::memset(ptrd,0,img._spectrum*sizeof(double));
+            return cimg::type<double>::nan();
+          default : // Dirichet boundary
+            std::memset(ptrd,0,img._spectrum*sizeof(double));
+            return cimg::type<double>::nan();
+          }
+        ptrs = &img[off];
+        cimg_forC(img,c) { *(ptrd++) = *ptrs; ptrs+=whd; }
+        return cimg::type<double>::nan();
+      }
+
+      static double mp_list_Jxyz(_cimg_math_parser& mp) {
+        double *ptrd = &_mp_arg(1) + 1;
+        const unsigned int
+          ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()),
+          interpolation = (unsigned int)_mp_arg(6),
+          boundary_conditions = (unsigned int)_mp_arg(7);
+        const CImg<T> &img = mp.listin[ind];
+        const double
+          ox = mp.mem[_cimg_mp_x], oy = mp.mem[_cimg_mp_y], oz = mp.mem[_cimg_mp_z],
+          x = ox + _mp_arg(3), y = oy + _mp_arg(4), z = oz + _mp_arg(5);
+        if (interpolation==0) { // Nearest neighbor interpolation
+          if (boundary_conditions==2)
+            cimg_forC(img,c)
+              *(ptrd++) = (double)img.atXYZ(cimg::mod((int)x,img.width()),
+                                            cimg::mod((int)y,img.height()),
+                                            cimg::mod((int)z,img.depth()),
+                                            c);
+          else if (boundary_conditions==1)
+            cimg_forC(img,c)
+              *(ptrd++) = (double)img.atXYZ((int)x,(int)y,(int)z,c);
+          else
+            cimg_forC(img,c)
+              *(ptrd++) = (double)img.atXYZ((int)x,(int)y,(int)z,c,0);
+        } else { // Linear interpolation
+          if (boundary_conditions==2)
+            cimg_forC(img,c)
+              *(ptrd++) = (double)img.linear_atXYZ(cimg::mod((float)x,(float)img.width()),
+                                                   cimg::mod((float)y,(float)img.height()),
+                                                   cimg::mod((float)z,(float)img.depth()),c);
+          else if (boundary_conditions==1)
+            cimg_forC(img,c)
+              *(ptrd++) = (double)img.linear_atXYZ((float)x,(float)y,(float)z,c);
+          else
+            cimg_forC(img,c)
+              *(ptrd++) = (double)img.linear_atXYZ((float)x,(float)y,(float)z,c,0);
+        }
+        return cimg::type<double>::nan();
+      }
+
+      static double mp_log(_cimg_math_parser& mp) {
+        return std::log(_mp_arg(2));
+      }
+
+      static double mp_log10(_cimg_math_parser& mp) {
+        return std::log10(_mp_arg(2));
+      }
+
+      static double mp_log2(_cimg_math_parser& mp) {
+        return cimg::log2(_mp_arg(2));
+      }
+
+      static double mp_logical_and(_cimg_math_parser& mp) {
+        const bool val_left = (bool)_mp_arg(2);
+        const CImg<ulongT> *const p_end = ++mp.p_code + mp.opcode[4];
+        if (!val_left) { mp.p_code = p_end - 1; return 0; }
+        const ulongT mem_right = mp.opcode[3];
+        for ( ; mp.p_code<p_end; ++mp.p_code) {
+          const CImg<ulongT> &op = *mp.p_code;
+          mp.opcode._data = op._data; mp.opcode._height = op._height;
+          const ulongT target = mp.opcode[1];
+          mp.mem[target] = _cimg_mp_defunc(mp);
+        }
+        --mp.p_code;
+        return (double)(bool)mp.mem[mem_right];
+      }
+
+      static double mp_logical_not(_cimg_math_parser& mp) {
+        return (double)!_mp_arg(2);
+      }
+
+      static double mp_logical_or(_cimg_math_parser& mp) {
+        const bool val_left = (bool)_mp_arg(2);
+        const CImg<ulongT> *const p_end = ++mp.p_code + mp.opcode[4];
+        if (val_left) { mp.p_code = p_end - 1; return 1; }
+        const ulongT mem_right = mp.opcode[3];
+        for ( ; mp.p_code<p_end; ++mp.p_code) {
+          const CImg<ulongT> &op = *mp.p_code;
+          mp.opcode._data = op._data; mp.opcode._height = op._height;
+          const ulongT target = mp.opcode[1];
+          mp.mem[target] = _cimg_mp_defunc(mp);
+        }
+        --mp.p_code;
+        return (double)(bool)mp.mem[mem_right];
+      }
+
+
+      static double mp_lt(_cimg_math_parser& mp) {
+        return (double)(_mp_arg(2)<_mp_arg(3));
+      }
+
+      static double mp_lte(_cimg_math_parser& mp) {
+        return (double)(_mp_arg(2)<=_mp_arg(3));
+      }
+
+      static double mp_matrix_mul(_cimg_math_parser& mp) {
+        double *ptrd = &_mp_arg(1) + 1;
+        const double
+          *ptr1 = &_mp_arg(2) + 1,
+          *ptr2 = &_mp_arg(3) + 1;
+        const unsigned int
+          k = (unsigned int)mp.opcode(4),
+          l = (unsigned int)mp.opcode(5),
+          m = (unsigned int)mp.opcode(6);
+        CImg<double>(ptrd,m,k,1,1,true) = CImg<double>(ptr1,l,k,1,1,true)*CImg<double>(ptr2,m,l,1,1,true);
+        return cimg::type<double>::nan();
+      }
+
+      static double mp_max(_cimg_math_parser& mp) {
+        double val = _mp_arg(2);
+        for (unsigned int i = 3; i<mp.opcode._height; ++i) val = cimg::max(val,_mp_arg(i));
+        return val;
+      }
+
+      static double* _mp_memcopy_double(_cimg_math_parser& mp, const unsigned int ind, const ulongT *const p_ref,
+                                        const longT siz, const long inc) {
+        const longT
+          off = *p_ref?p_ref[1] + (longT)mp.mem[(longT)p_ref[2]] + 1:ind,
+          eoff = off + (siz - 1)*inc;
+        if (off<0 || eoff>=mp.mem.width())
+          throw CImgArgumentException("[_cimg_math_parser] CImg<%s>: 'copy()': "
+                                      "Out-of-bounds variable pointer "
+                                      "(length: %ld, increment: %ld, offset start: %ld, "
+                                      "offset end: %ld, offset max: %u).",
+                                      mp.imgin.pixel_type(),siz,inc,off,eoff,mp.mem._width - 1);
+        return &mp.mem[off];
+      }
+
+      static float* _mp_memcopy_float(_cimg_math_parser& mp, const ulongT *const p_ref,
+                                      const longT siz, const long inc) {
+        const unsigned ind = p_ref[1];
+        const CImg<T> &img = ind==~0U?mp.imgin:mp.listin[cimg::mod((int)mp.mem[ind],mp.listin.width())];
+        const bool is_relative = (bool)p_ref[2];
+        int ox, oy, oz, oc;
+        longT off = 0;
+        if (is_relative) {
+          ox = (int)mp.mem[_cimg_mp_x];
+          oy = (int)mp.mem[_cimg_mp_y];
+          oz = (int)mp.mem[_cimg_mp_z];
+          oc = (int)mp.mem[_cimg_mp_c];
+          off = img.offset(ox,oy,oz,oc);
+        }
+        if ((*p_ref)%2) {
+          const int
+            x = (int)mp.mem[p_ref[3]],
+            y = (int)mp.mem[p_ref[4]],
+            z = (int)mp.mem[p_ref[5]],
+            c = *p_ref==5?0:(int)mp.mem[p_ref[6]];
+          off+=img.offset(x,y,z,c);
+        } else off+=(longT)mp.mem[p_ref[3]];
+        const longT eoff = off + (siz - 1)*inc;
+        if (off<0 || eoff>=(longT)img.size())
+          throw CImgArgumentException("[_cimg_math_parser] CImg<%s>: Function 'copy()': "
+                                      "Out-of-bounds image pointer "
+                                      "(length: %ld, increment: %ld, offset start: %ld, "
+                                      "offset end: %ld, offset max: %lu).",
+                                      mp.imgin.pixel_type(),siz,inc,off,eoff,img.size() - 1);
+        return (float*)&img[off];
+      }
+
+      static double mp_memcopy(_cimg_math_parser& mp) {
+        longT siz = (longT)_mp_arg(4);
+        const longT inc_d = (longT)_mp_arg(5), inc_s = (longT)_mp_arg(6);
+        if (siz>0) {
+          const bool
+            is_doubled = mp.opcode[7]<=1,
+            is_doubles = mp.opcode[14]<=1;
+          if (is_doubled && is_doubles) { // (double*) <- (double*)
+            double *ptrd = _mp_memcopy_double(mp,mp.opcode[2],&mp.opcode[7],siz,inc_d);
+            const double *ptrs = _mp_memcopy_double(mp,mp.opcode[3],&mp.opcode[14],siz,inc_s);
+            if (inc_d==1 && inc_s==1) {
+              if (ptrs + siz - 1<ptrd || ptrs>ptrd + siz - 1) std::memcpy(ptrd,ptrs,siz*sizeof(double));
+              else std::memmove(ptrd,ptrs,siz*sizeof(double));
+            } else {
+              if (ptrs + (siz - 1)*inc_s<ptrd || ptrs>ptrd + (siz - 1)*inc_d)
+                while (siz-->0) { *ptrd = (double)*ptrs; ptrd+=inc_d; ptrs+=inc_s; }
+              else { // Overlapping buffers
+                CImg<double> buf(siz);
+                cimg_for(buf,ptr,double) { *ptr = *ptrs; ptrs+=inc_s; }
+                ptrs = buf;
+                while (siz-->0) { *ptrd = *(ptrs++); ptrd+=inc_d; }
+              }
+            }
+          } else if (is_doubled && !is_doubles) { // (double*) <- (float*)
+            double *ptrd = _mp_memcopy_double(mp,mp.opcode[2],&mp.opcode[7],siz,inc_d);
+            const float *ptrs = _mp_memcopy_float(mp,&mp.opcode[14],siz,inc_s);
+            while (siz-->0) { *ptrd = (double)*ptrs; ptrd+=inc_d; ptrs+=inc_s; }
+          } else if (!is_doubled && is_doubles) { // (float*) <- (double*)
+            float *ptrd = _mp_memcopy_float(mp,&mp.opcode[7],siz,inc_d);
+            const double *ptrs = _mp_memcopy_double(mp,mp.opcode[3],&mp.opcode[14],siz,inc_s);
+            while (siz-->0) { *ptrd = (float)*ptrs; ptrd+=inc_d; ptrs+=inc_s; }
+          } else { // (float*) <- (float*)
+            float *ptrd = _mp_memcopy_float(mp,&mp.opcode[7],siz,inc_d);
+            const float *ptrs = _mp_memcopy_float(mp,&mp.opcode[14],siz,inc_s);
+            if (inc_d==1 && inc_s==1) {
+              if (ptrs + siz - 1<ptrd || ptrs>ptrd + siz - 1) std::memcpy(ptrd,ptrs,siz*sizeof(float));
+              else std::memmove(ptrd,ptrs,siz*sizeof(float));
+            } else {
+              if (ptrs + (siz - 1)*inc_s<ptrd || ptrs>ptrd + (siz - 1)*inc_d)
+                while (siz-->0) { *ptrd = (float)*ptrs; ptrd+=inc_d; ptrs+=inc_s; }
+              else { // Overlapping buffers
+                CImg<float> buf(siz);
+                cimg_for(buf,ptr,float) { *ptr = *ptrs; ptrs+=inc_s; }
+                ptrs = buf;
+                while (siz-->0) { *ptrd = *(ptrs++); ptrd+=inc_d; }
+              }
+            }
+          }
+        }
+        return _mp_arg(1);
+      }
+
+      static double mp_min(_cimg_math_parser& mp) {
+        double val = _mp_arg(2);
+        for (unsigned int i = 3; i<mp.opcode._height; ++i) val = cimg::min(val,_mp_arg(i));
+        return val;
+      }
+
+      static double mp_minus(_cimg_math_parser& mp) {
+        return -_mp_arg(2);
+      }
+
+      static double mp_mean(_cimg_math_parser& mp) {
+        double val = _mp_arg(2);
+        for (unsigned int i = 3; i<mp.opcode._height; ++i) val+=_mp_arg(i);
+        return val/(mp.opcode._height - 2);
+      }
+
+      static double mp_med(_cimg_math_parser& mp) {
+        CImg<doubleT> vals(mp.opcode._height - 2);
+        double *p = vals.data();
+        for (unsigned int i = 2; i<mp.opcode._height; ++i) *(p++) = _mp_arg(i);
+        return vals.median();
+      }
+
+      static double mp_modulo(_cimg_math_parser& mp) {
+        return cimg::mod(_mp_arg(2),_mp_arg(3));
+      }
+
+      static double mp_mul(_cimg_math_parser& mp) {
+        return _mp_arg(2)*_mp_arg(3);
+      }
+
+      static double mp_neq(_cimg_math_parser& mp) {
+        return (double)(_mp_arg(2)!=_mp_arg(3));
+      }
+
+      static double mp_norm0(_cimg_math_parser& mp) {
+        double res = 0;
+        for (unsigned int i = 2; i<mp.opcode._height; ++i)
+          res+=_mp_arg(i)==0?0:1;
+        return res;
+      }
+
+      static double mp_norm1(_cimg_math_parser& mp) {
+        double res = 0;
+        for (unsigned int i = 2; i<mp.opcode._height; ++i)
+          res+=cimg::abs(_mp_arg(i));
+        return res;
+      }
+
+      static double mp_norm2(_cimg_math_parser& mp) {
+        double res = 0;
+        for (unsigned int i = 2; i<mp.opcode._height; ++i)
+          res+=cimg::sqr(_mp_arg(i));
+        return std::sqrt(res);
+      }
+
+      static double mp_norminf(_cimg_math_parser& mp) {
+        double res = 0;
+        for (unsigned int i = 2; i<mp.opcode._height; ++i) {
+          const double val = cimg::abs(_mp_arg(i));
+          if (val>res) res = val;
+        }
+        return res;
+      }
+
+      static double mp_normp(_cimg_math_parser& mp) {
+        const double p = (double)mp.opcode[2];
+        double res = 0;
+        for (unsigned int i = 3; i<mp.opcode._height; ++i)
+          res+=std::pow(cimg::abs(_mp_arg(i)),p);
+        res = std::pow(res,1/p);
+        return res>0?res:0.0;
+      }
+
+      static double mp_pow(_cimg_math_parser& mp) {
+        const double v = _mp_arg(2), p = _mp_arg(3);
+        return std::pow(v,p);
+      }
+
+      static double mp_pow3(_cimg_math_parser& mp) {
+        const double val = _mp_arg(2);
+        return val*val*val;
+      }
+
+      static double mp_pow4(_cimg_math_parser& mp) {
+        const double val = _mp_arg(2);
+        return val*val*val*val;
+      }
+
+      static double mp_print(_cimg_math_parser& mp) {
+          const double val = _mp_arg(1);
+#ifdef cimg_use_openmp
+#pragma omp critical
+#endif
+        {
+          CImg<charT> expr(mp.opcode._height - 2);
+          const ulongT *ptrs = mp.opcode._data + 2;
+          cimg_for(expr,ptrd,char) *ptrd = (char)*(ptrs++);
+          cimg::strellipsize(expr);
+          cimg::mutex(6);
+          std::fprintf(cimg::output(),"\n[_cimg_math_parser] %s = %g",expr._data,val);
+          std::fflush(cimg::output());
+          cimg::mutex(6,0);
+        }
+        return val;
+      }
+
+      static double mp_prod(_cimg_math_parser& mp) {
+        double val = _mp_arg(2);
+        for (unsigned int i = 3; i<mp.opcode._height; ++i) val*=_mp_arg(i);
+        return val;
+      }
+
+      static double mp_copy(_cimg_math_parser& mp) {
+        return _mp_arg(2);
       }
 
       static double mp_rol(_cimg_math_parser& mp) {
-        return cimg::rol(mp.mem[mp.opcode(2)],(unsigned int)mp.mem[mp.opcode(3)]);
+        return cimg::rol(_mp_arg(2),(unsigned int)_mp_arg(3));
       }
 
       static double mp_ror(_cimg_math_parser& mp) {
-        return cimg::ror(mp.mem[mp.opcode(2)],(unsigned int)mp.mem[mp.opcode(3)]);
+        return cimg::ror(_mp_arg(2),(unsigned int)_mp_arg(3));
       }
 
-      static double mp_lsl(_cimg_math_parser& mp) {
-        return (long)mp.mem[mp.opcode(2)]<<(unsigned int)mp.mem[mp.opcode(3)];
+      static double mp_rot2d(_cimg_math_parser& mp) {
+        double *ptrd = &_mp_arg(1) + 1;
+        const float
+          theta = (float)_mp_arg(2),
+          ca = std::cos(theta),
+          sa = std::sin(theta);
+        *(ptrd++) = ca;
+        *(ptrd++) = -sa;
+        *(ptrd++) = sa;
+        *ptrd = ca;
+        return cimg::type<double>::nan();
       }
 
-      static double mp_lsr(_cimg_math_parser& mp) {
-        return (long)mp.mem[mp.opcode(2)]>>(unsigned int)mp.mem[mp.opcode(3)];
+      static double mp_rot3d(_cimg_math_parser& mp) {
+        double *ptrd = &_mp_arg(1) + 1;
+        const float x = (float)_mp_arg(2), y = (float)_mp_arg(3), z = (float)_mp_arg(4), theta = (float)_mp_arg(5);
+        CImg<double>(ptrd,3,3,1,1,true) = CImg<double>::rotation_matrix(x,y,z,theta);
+        return cimg::type<double>::nan();
       }
 
-      static double mp_sinc(_cimg_math_parser& mp) {
-        return cimg::sinc(mp.mem[mp.opcode(2)]);
+      static double mp_round(_cimg_math_parser& mp) {
+        return cimg::round(_mp_arg(2),_mp_arg(3),(int)_mp_arg(4));
+      }
+
+      static double mp_self_add(_cimg_math_parser& mp) {
+        return _mp_arg(1)+=_mp_arg(2);
+      }
+
+      static double mp_self_bitwise_and(_cimg_math_parser& mp) {
+        double &val = _mp_arg(1);
+        return val = (double)((ulongT)val & (ulongT)_mp_arg(2));
+      }
+
+      static double mp_self_bitwise_left_shift(_cimg_math_parser& mp) {
+        double &val = _mp_arg(1);
+        return val = (double)((longT)val<<(unsigned int)_mp_arg(2));
       }
 
-      static double mp_im(_cimg_math_parser& mp) {
-        return mp.input_stats?mp.input_stats[0]:0;
+      static double mp_self_bitwise_or(_cimg_math_parser& mp) {
+        double &val = _mp_arg(1);
+        return val = (double)((ulongT)val | (ulongT)_mp_arg(2));
       }
 
-      static double mp_iM(_cimg_math_parser& mp) {
-        return mp.input_stats?mp.input_stats[1]:0;
+      static double mp_self_bitwise_right_shift(_cimg_math_parser& mp) {
+        double &val = _mp_arg(1);
+        return val = (double)((longT)val>>(unsigned int)_mp_arg(2));
       }
 
-      static double mp_ia(_cimg_math_parser& mp) {
-        return mp.input_stats?mp.input_stats[2]:0;
+      static double mp_self_decrement(_cimg_math_parser& mp) {
+        return --_mp_arg(1);
       }
 
-      static double mp_iv(_cimg_math_parser& mp) {
-        return mp.input_stats?mp.input_stats[3]:0;
+      static double mp_self_increment(_cimg_math_parser& mp) {
+        return ++_mp_arg(1);
       }
 
-      static double mp_is(_cimg_math_parser& mp) {
-        return mp.input_stats?mp.input_stats[12]:0;
+      static double mp_self_map_vector_s(_cimg_math_parser& mp) { // Vector += scalar
+        unsigned int
+          ptrd = (unsigned int)mp.opcode[1] + 1,
+          siz = (unsigned int)mp.opcode[2];
+        mp_func op = (mp_func)mp.opcode[3];
+        CImg<ulongT> l_opcode(1,3);
+        l_opcode[2] = mp.opcode[4]; // Scalar argument.
+        l_opcode.swap(mp.opcode);
+        ulongT &target = mp.opcode[1];
+        while (siz-->0) { target = ptrd++; (*op)(mp); }
+        l_opcode.swap(mp.opcode);
+        return cimg::type<double>::nan();
       }
 
-      static double mp_ip(_cimg_math_parser& mp) {
-        return mp.input_stats?mp.input_stats[13]:0;
+      static double mp_self_map_vector_v(_cimg_math_parser& mp) { // Vector += vector
+        unsigned int
+          ptrd = (unsigned int)mp.opcode[1] + 1,
+          siz = (unsigned int)mp.opcode[2],
+          ptrs = (unsigned int)mp.opcode[4] + 1;
+        mp_func op = (mp_func)mp.opcode[3];
+        CImg<ulongT> l_opcode(1,4);
+        l_opcode.swap(mp.opcode);
+        ulongT &target = mp.opcode[1], &argument = mp.opcode[2];
+        while (siz-->0)  { target = ptrd++; argument = ptrs++; (*op)(mp); }
+        l_opcode.swap(mp.opcode);
+        return cimg::type<double>::nan();
       }
 
-      static double mp_ic(_cimg_math_parser& mp) {
-        return mp.is_median_value?mp.median_value:0;
+      static double mp_self_mul(_cimg_math_parser& mp) {
+        return _mp_arg(1)*=_mp_arg(2);
       }
 
-      static double mp_xm(_cimg_math_parser& mp) {
-        return mp.input_stats?mp.input_stats[4]:0;
+      static double mp_self_div(_cimg_math_parser& mp) {
+        return _mp_arg(1)/=_mp_arg(2);
       }
 
-      static double mp_ym(_cimg_math_parser& mp) {
-        return mp.input_stats?mp.input_stats[5]:0;
+      static double mp_self_modulo(_cimg_math_parser& mp) {
+        double &val = _mp_arg(1);
+        return val = cimg::mod(val,_mp_arg(2));
       }
 
-      static double mp_zm(_cimg_math_parser& mp) {
-        return mp.input_stats?mp.input_stats[6]:0;
+      static double mp_self_pow(_cimg_math_parser& mp) {
+        double &val = _mp_arg(1);
+        return val = std::pow(val,_mp_arg(2));
       }
 
-      static double mp_cm(_cimg_math_parser& mp) {
-        return mp.input_stats?mp.input_stats[7]:0;
+      static double mp_self_sub(_cimg_math_parser& mp) {
+        return _mp_arg(1)-=_mp_arg(2);
       }
 
-      static double mp_xM(_cimg_math_parser& mp) {
-        return mp.input_stats?mp.input_stats[8]:0;
+      static double mp_set_ioff(_cimg_math_parser& mp) {
+        CImg<T> &img = mp.imgout;
+        const longT
+          off = (longT)_mp_arg(2),
+          whds = (longT)img.size();
+        const double val = _mp_arg(1);
+        if (off>=0 && off<whds) img[off] = (T)val;
+        return val;
       }
 
-      static double mp_yM(_cimg_math_parser& mp) {
-        return mp.input_stats?mp.input_stats[9]:0;
+      static double mp_set_ixyzc(_cimg_math_parser& mp) {
+        CImg<T> &img = mp.imgout;
+        const int
+          x = (int)_mp_arg(2), y = (int)_mp_arg(3),
+          z = (int)_mp_arg(4), c = (int)_mp_arg(5);
+        const double val = _mp_arg(1);
+        if (x>=0 && x<img.width() && y>=0 && y<img.height() &&
+            z>=0 && z<img.depth() && c>=0 && c<img.spectrum())
+          img(x,y,z,c) = (T)val;
+        return val;
       }
 
-      static double mp_zM(_cimg_math_parser& mp) {
-        return mp.input_stats?mp.input_stats[10]:0;
+      static double mp_set_joff(_cimg_math_parser& mp) {
+        CImg<T> &img = mp.imgout;
+        const int
+          ox = (int)mp.mem[_cimg_mp_x], oy = (int)mp.mem[_cimg_mp_y],
+          oz = (int)mp.mem[_cimg_mp_z], oc = (int)mp.mem[_cimg_mp_c];
+        const longT
+          off = img.offset(ox,oy,oz,oc) + (longT)_mp_arg(2),
+          whds = (longT)img.size();
+        const double val = _mp_arg(1);
+        if (off>=0 && off<whds) img[off] = (T)val;
+        return val;
       }
 
-      static double mp_cM(_cimg_math_parser& mp) {
-        return mp.input_stats?mp.input_stats[11]:0;
+      static double mp_set_jxyzc(_cimg_math_parser& mp) {
+        CImg<T> &img = mp.imgout;
+        const double
+          ox = mp.mem[_cimg_mp_x], oy = mp.mem[_cimg_mp_y],
+          oz = mp.mem[_cimg_mp_z], oc = mp.mem[_cimg_mp_c];
+        const int
+          x = (int)(ox + _mp_arg(2)), y = (int)(oy + _mp_arg(3)),
+          z = (int)(oz + _mp_arg(4)), c = (int)(oc + _mp_arg(5));
+        const double val = _mp_arg(1);
+        if (x>=0 && x<img.width() && y>=0 && y<img.height() &&
+            z>=0 && z<img.depth() && c>=0 && c<img.spectrum())
+          img(x,y,z,c) = (T)val;
+        return val;
       }
 
-      static double mp_arg(_cimg_math_parser& mp) {
-        const int _ind = (int)mp.mem[mp.opcode(2)];
-        const unsigned int nb_args = mp.opcode._height - 2, ind = _ind<0?_ind + nb_args:(unsigned int)_ind;
-        if (ind>=nb_args) return 0;
-        return mp.mem[mp.opcode(ind + 2)];
+      static double mp_set_Ioff_s(_cimg_math_parser& mp) {
+        CImg<T> &img = mp.imgout;
+        const longT
+          off = (longT)_mp_arg(2),
+          whd = (longT)img.width()*img.height()*img.depth();
+        const T val = (T)_mp_arg(1);
+        if (off>=0 && off<whd) {
+          T *ptrd = &img[off];
+          cimg_forC(img,c) { *ptrd = val; ptrd+=whd; }
+        }
+        return _mp_arg(1);
       }
 
-      static double mp_int(_cimg_math_parser& mp) {
-        return (double)(long)mp.mem[mp.opcode(2)];
+      static double mp_set_Ioff_v(_cimg_math_parser& mp) {
+        CImg<T> &img = mp.imgout;
+        const longT
+          off = (longT)_mp_arg(2),
+          whd = (longT)img.width()*img.height()*img.depth();
+        const double *ptrs = &_mp_arg(1) + 1;
+        if (off>=0 && off<whd) {
+          T *ptrd = &img[off];
+          cimg_forC(img,c) { *ptrd = (T)*(ptrs++); ptrd+=whd; }
+        }
+        return cimg::type<double>::nan();
       }
 
-      static double mp_replace(_cimg_math_parser& mp) {
-        return mp.mem[mp.opcode(2)];
+      static double mp_set_Ixyz_s(_cimg_math_parser& mp) {
+        CImg<T> &img = mp.imgout;
+        const int x = (int)_mp_arg(2), y = (int)_mp_arg(3), z = (int)_mp_arg(4);
+        const T val = (T)_mp_arg(1);
+        if (x>=0 && x<img.width() && y>=0 && y<img.height() && z>=0 && z<img.depth()) {
+          T *ptrd = &img(x,y,z);
+          const ulongT whd = (ulongT)img._width*img._height*img._depth;
+          cimg_forC(img,c) { *ptrd = val; ptrd+=whd; }
+        }
+        return _mp_arg(1);
       }
 
-      static double mp_ioff(_cimg_math_parser& mp) {
-        const long off = (long)mp.mem[mp.opcode(2)];
-        if (off<0 || off>=(long)mp.input.size()) return 0;
-        return (double)mp.input[off];
+      static double mp_set_Ixyz_v(_cimg_math_parser& mp) {
+        CImg<T> &img = mp.imgout;
+        const int x = (int)_mp_arg(2), y = (int)_mp_arg(3), z = (int)_mp_arg(4);
+        const double *ptrs = &_mp_arg(1) + 1;
+        if (x>=0 && x<img.width() && y>=0 && y<img.height() && z>=0 && z<img.depth()) {
+          T *ptrd = &img(x,y,z);
+          const ulongT whd = (ulongT)img._width*img._height*img._depth;
+          cimg_forC(img,c) { *ptrd = (T)*(ptrs++); ptrd+=whd; }
+        }
+        return cimg::type<double>::nan();
       }
 
-      static double mp_joff(_cimg_math_parser& mp) {
-        const int x = (int)mp.mem[16], y = (int)mp.mem[17], z = (int)mp.mem[18], c = (int)mp.mem[19];
-        const long off = mp.input.offset(x,y,z,c) + (long)(mp.mem[mp.opcode(2)]);
-        if (off<0 || off>=(long)mp.input.size()) return 0;
-        return (double)mp.input[off];
+      static double mp_set_Joff_s(_cimg_math_parser& mp) {
+        CImg<T> &img = mp.imgout;
+        const int
+          ox = (int)mp.mem[_cimg_mp_x], oy = (int)mp.mem[_cimg_mp_y],
+          oz = (int)mp.mem[_cimg_mp_z], oc = (int)mp.mem[_cimg_mp_c];
+        const longT
+          off = img.offset(ox,oy,oz,oc) + (longT)_mp_arg(2),
+          whd = (longT)img.width()*img.height()*img.depth();
+        const T val = (T)_mp_arg(1);
+        if (off>=0 && off<whd) {
+          T *ptrd = &img[off];
+          cimg_forC(img,c) { *ptrd = val; ptrd+=whd; }
+        }
+        return _mp_arg(1);
       }
 
-      static double mp_ixyzc(_cimg_math_parser& mp) {
-        const double
-          x = mp.mem[mp.opcode(2)], y = mp.mem[mp.opcode(3)], z = mp.mem[mp.opcode(4)], c = mp.mem[mp.opcode(5)];
-        const int i = (int)mp.mem[mp.opcode(6)], b = (int)mp.mem[mp.opcode(7)];
-        if (i==0) { // Nearest neighbor interpolation.
-          if (b==2) return (double)mp.input.atXYZC(cimg::mod((int)x,mp.input.width()),
-                                                   cimg::mod((int)y,mp.input.height()),
-                                                   cimg::mod((int)z,mp.input.depth()),
-                                                   cimg::mod((int)c,mp.input.spectrum()));
-          if (b==1) return (double)mp.input.atXYZC((int)x,(int)y,(int)z,(int)c);
-          return (double)mp.input.atXYZC((int)x,(int)y,(int)z,(int)c,0);
-        } else { // Linear interpolation.
-          if (b==2) return (double)mp.input.linear_atXYZC(cimg::mod((float)x,(float)mp.input.width()),
-                                                          cimg::mod((float)y,(float)mp.input.height()),
-                                                          cimg::mod((float)z,(float)mp.input.depth()),
-                                                          cimg::mod((float)c,(float)mp.input.spectrum()));
-          if (b==1) return (double)mp.input.linear_atXYZC((float)x,(float)y,(float)z,(float)c);
-          return (double)mp.input.linear_atXYZC((float)x,(float)y,(float)z,(float)c,0);
+      static double mp_set_Joff_v(_cimg_math_parser& mp) {
+        CImg<T> &img = mp.imgout;
+        const int
+          ox = (int)mp.mem[_cimg_mp_x], oy = (int)mp.mem[_cimg_mp_y],
+          oz = (int)mp.mem[_cimg_mp_z], oc = (int)mp.mem[_cimg_mp_c];
+        const longT
+          off = img.offset(ox,oy,oz,oc) + (longT)_mp_arg(2),
+          whd = (longT)img.width()*img.height()*img.depth();
+        const double *ptrs = &_mp_arg(1) + 1;
+        if (off>=0 && off<whd) {
+          T *ptrd = &img[off];
+          cimg_forC(img,c) { *ptrd = (T)*(ptrs++); ptrd+=whd; }
         }
+        return cimg::type<double>::nan();
       }
 
-      static double mp_jxyzc(_cimg_math_parser& mp) {
-        const double x = mp.mem[16], y = mp.mem[17], z = mp.mem[18], c = mp.mem[19];
-        const double
-          dx = mp.mem[mp.opcode(2)], dy = mp.mem[mp.opcode(3)], dz = mp.mem[mp.opcode(4)], dc = mp.mem[mp.opcode(5)];
-        const int i = (int)mp.mem[mp.opcode(6)], b = (int)mp.mem[mp.opcode(7)];
-        if (i==0) { // Nearest neighbor interpolation.
-          if (b==2) return (double)mp.input.atXYZC(cimg::mod((int)(x + dx),mp.input.width()),
-                                                   cimg::mod((int)(y + dy),mp.input.height()),
-                                                   cimg::mod((int)(z + dz),mp.input.depth()),
-                                                   cimg::mod((int)(c + dc),mp.input.spectrum()));
-          if (b==1) return (double)mp.input.atXYZC((int)(x + dx),(int)(y + dy),(int)(z + dz),(int)(c + dc));
-          return (double)mp.input.atXYZC((int)(x + dx),(int)(y + dy),(int)(z + dz),(int)(c + dc),0);
-        } else { // Linear interpolation.
-          if (b==2)
-            return (double)mp.input.linear_atXYZC(cimg::mod((float)(x + dx),(float)mp.input.width()),
-                                                  cimg::mod((float)(y + dy),(float)mp.input.height()),
-                                                  cimg::mod((float)(z + dz),(float)mp.input.depth()),
-                                                  cimg::mod((float)(c + dc),(float)mp.input.spectrum()));
-          if (b==1) return (double)mp.input.linear_atXYZC((float)(x + dx),(float)(y + dy),
-                                                          (float)(z + dz),(float)(c + dc));
-          return (double)mp.input.linear_atXYZC((float)(x + dx),(float)(y + dy),(float)(z + dz),(float)(c + dc),0);
+      static double mp_set_Jxyz_s(_cimg_math_parser& mp) {
+        CImg<T> &img = mp.imgout;
+        const double ox = mp.mem[_cimg_mp_x], oy = mp.mem[_cimg_mp_y], oz = mp.mem[_cimg_mp_z];
+        const int x = (int)(ox + _mp_arg(2)), y = (int)(oy + _mp_arg(3)), z = (int)(oz + _mp_arg(4));
+        const T val = (T)_mp_arg(1);
+        if (x>=0 && x<img.width() && y>=0 && y<img.height() && z>=0 && z<img.depth()) {
+          T *ptrd = &img(x,y,z);
+          const ulongT whd = (ulongT)img._width*img._height*img._depth;
+          cimg_forC(img,c) { *ptrd = val; ptrd+=whd; }
         }
+        return _mp_arg(1);
       }
 
-      static double mp_set_ioff(_cimg_math_parser& mp) {
-        const long off = (long)mp.mem[mp.opcode(2)];
-        const double value = mp.mem[mp.opcode(3)];
-        if (off>=0 && off<(long)mp.output.size()) mp.output._data[off] = (T)value;
-        return value;
+      static double mp_set_Jxyz_v(_cimg_math_parser& mp) {
+        CImg<T> &img = mp.imgout;
+        const double ox = mp.mem[_cimg_mp_x], oy = mp.mem[_cimg_mp_y], oz = mp.mem[_cimg_mp_z];
+        const int x = (int)(ox + _mp_arg(2)), y = (int)(oy + _mp_arg(3)), z = (int)(oz + _mp_arg(4));
+        const double *ptrs = &_mp_arg(1) + 1;
+        if (x>=0 && x<img.width() && y>=0 && y<img.height() && z>=0 && z<img.depth()) {
+          T *ptrd = &img(x,y,z);
+          const ulongT whd = (ulongT)img._width*img._height*img._depth;
+          cimg_forC(img,c) { *ptrd = (T)*(ptrs++); ptrd+=whd; }
+        }
+        return cimg::type<double>::nan();
       }
 
-      static double mp_set_joff(_cimg_math_parser& mp) {
-        const int x = (int)mp.mem[16], y = (int)mp.mem[17], z = (int)mp.mem[18], c = (int)mp.mem[19];
-        const long off = mp.output.offset(x,y,z,c) + (long)(mp.mem[mp.opcode(2)]);
-        const double value = mp.mem[mp.opcode(3)];
-        if (off>=0 && off<(long)mp.output.size()) mp.output._data[off] = (T)value;
-        return value;
+      static double mp_sign(_cimg_math_parser& mp) {
+        return cimg::sign(_mp_arg(2));
       }
 
-      static double mp_set_ixyzc(_cimg_math_parser& mp) {
-        const int
-          x = (int)mp.mem[mp.opcode(2)], y = (int)mp.mem[mp.opcode(3)],
-          z = (int)mp.mem[mp.opcode(4)], c = (int)mp.mem[mp.opcode(5)];
-        const double value = mp.mem[mp.opcode(6)];
-        if (x>=0 && x<mp.output.width() && y>=0 && y<mp.output.height() &&
-            z>=0 && z<mp.output.depth() && c>=0 && c<mp.output.spectrum()) {
-          mp.output(x,y,z,c) = (T)value;
-        }
-        return value;
+      static double mp_sin(_cimg_math_parser& mp) {
+        return std::sin(_mp_arg(2));
       }
 
-      static double mp_set_jxyzc(_cimg_math_parser& mp) {
-        const double
-          dx = mp.mem[mp.opcode(2)], dy = mp.mem[mp.opcode(3)],
-          dz = mp.mem[mp.opcode(4)], dc = mp.mem[mp.opcode(5)];
-        const int
-          x = (int)(dx + mp.mem[16]), y = (int)(dy + mp.mem[17]),
-          z = (int)(dz + mp.mem[18]), c = (int)(dc + mp.mem[19]);
-        const double value = mp.mem[mp.opcode(6)];
-        if (x>=0 && x<mp.output.width() && y>=0 && y<mp.output.height() &&
-            z>=0 && z<mp.output.depth() && c>=0 && c<mp.output.spectrum()) {
-          mp.output(x,y,z,c) = (T)value;
-        }
-        return value;
+      static double mp_sinc(_cimg_math_parser& mp) {
+        return cimg::sinc(_mp_arg(2));
       }
 
-      static double mp_if(_cimg_math_parser& mp) {
-        const bool is_cond = (bool)mp.mem[mp.opcode(2)];
-        const unsigned int
-          mem_left = (unsigned int)mp.opcode(3),
-          mem_right = (unsigned int)mp.opcode(4);
-        const CImg<longT>
-          *const p_right = ++mp.p_code + mp.opcode(5),
-          *const p_end = p_right + mp.opcode(6);
-        if (is_cond) {
-          for ( ; mp.p_code<p_right; ++mp.p_code) {
-            cimg_test_abort();
-            const CImg<longT> &op = *mp.p_code;
+      static double mp_single(_cimg_math_parser& mp) {
+        const double res = _mp_arg(1);
+#ifdef cimg_use_openmp
+#pragma omp critical
+#endif
+        {
+          for (const CImg<ulongT> *const p_end = ++mp.p_code + mp.opcode[2];
+            mp.p_code<p_end; ++mp.p_code) { // Evaluate loop iteration + condition
+            const CImg<ulongT> &op = *mp.p_code;
             mp.opcode._data = op._data; mp.opcode._height = op._height;
-            const unsigned int target = (unsigned int)mp.opcode[1];
+            const ulongT target = mp.opcode[1];
             mp.mem[target] = _cimg_mp_defunc(mp);
           }
-          mp.p_code = p_end - 1;
-          return mp.mem[mem_left];
-        }
-        for (mp.p_code = p_right; mp.p_code<p_end; ++mp.p_code) {
-          cimg_test_abort();
-          const CImg<longT> &op = *mp.p_code;
-          mp.opcode._data = op._data; mp.opcode._height = op._height;
-          const unsigned int target = (unsigned int)mp.opcode[1];
-          mp.mem[target] = _cimg_mp_defunc(mp);
         }
         --mp.p_code;
-        return mp.mem[mem_right];
+        return res;
       }
 
-      static double mp_dowhile(_cimg_math_parser& mp) {
+      static double mp_sinh(_cimg_math_parser& mp) {
+        return std::sinh(_mp_arg(2));
+      }
+
+      static double mp_solve(_cimg_math_parser& mp) {
+        double *ptrd = &_mp_arg(1) + 1;
+        const double
+          *ptr1 = &_mp_arg(2) + 1,
+          *ptr2 = &_mp_arg(3) + 1;
         const unsigned int
-          mem_proc = (unsigned int)mp.opcode(1),
-          mem_cond = (unsigned int)mp.opcode(2);
-        const CImg<longT>
-          *const p_proc = ++mp.p_code,
-          *const p_end = p_proc + mp.opcode(3);
-        do {
-          cimg_test_abort();
-          for (mp.p_code = p_proc; mp.p_code<p_end; ++mp.p_code) { // Evaluate loop iteration + condition.
-            cimg_test_abort();
-            const CImg<longT> &op = *mp.p_code;
-            mp.opcode._data = op._data; mp.opcode._height = op._height;
-            const unsigned int target = (unsigned int)mp.opcode[1];
-            mp.mem[target] = _cimg_mp_defunc(mp);
-          }
-        } while (mp.mem[mem_cond]);
-        --mp.p_code;
-        return mp.mem[mem_proc];
+          k = (unsigned int)mp.opcode(4),
+          l = (unsigned int)mp.opcode(5),
+          m = (unsigned int)mp.opcode(6);
+        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));
+        return cimg::type<double>::nan();
+      }
+
+      static double mp_sort(_cimg_math_parser& mp) {
+        double *const ptrd = &_mp_arg(1) + 1;
+        const double *const ptrs = &_mp_arg(2) + 1;
+        const unsigned int
+          siz = mp.opcode[3],
+          chunk_siz = mp.opcode[5];
+        const bool is_increasing = (bool)_mp_arg(4);
+        CImg<doubleT>(ptrd,chunk_siz,siz/chunk_siz,1,1,true) = CImg<doubleT>(ptrs,chunk_siz,siz/chunk_siz,1,1,true).
+          get_sort(is_increasing,chunk_siz>1?'y':0);
+        return cimg::type<double>::nan();
+      }
+
+      static double mp_sqr(_cimg_math_parser& mp) {
+        return cimg::sqr(_mp_arg(2));
+      }
+
+      static double mp_sqrt(_cimg_math_parser& mp) {
+        return std::sqrt(_mp_arg(2));
+      }
+
+      static double mp_std(_cimg_math_parser& mp) {
+        CImg<doubleT> vals(mp.opcode._height - 2);
+        double *p = vals.data();
+        for (unsigned int i = 2; i<mp.opcode._height; ++i) *(p++) = _mp_arg(i);
+        return std::sqrt(vals.variance());
+      }
+
+      static double mp_sub(_cimg_math_parser& mp) {
+        return _mp_arg(2) - _mp_arg(3);
+      }
+
+      static double mp_sum(_cimg_math_parser& mp) {
+        double val = _mp_arg(2);
+        for (unsigned int i = 3; i<mp.opcode._height; ++i) val+=_mp_arg(i);
+        return val;
+      }
+
+      static double mp_tan(_cimg_math_parser& mp) {
+        return std::tan(_mp_arg(2));
+      }
+
+      static double mp_tanh(_cimg_math_parser& mp) {
+        return std::tanh(_mp_arg(2));
+      }
+
+      static double mp_trace(_cimg_math_parser& mp) {
+        const double *ptrs = &_mp_arg(2) + 1;
+        const unsigned int k = (unsigned int)mp.opcode(3);
+        return CImg<double>(ptrs,k,k,1,1,true).trace();
+      }
+
+      static double mp_transp(_cimg_math_parser& mp) {
+        double *ptrd = &_mp_arg(1) + 1;
+        const double *ptr1 = &_mp_arg(2) + 1;
+        const unsigned int
+          k = (unsigned int)mp.opcode(3),
+          l = (unsigned int)mp.opcode(4);
+        CImg<double>(ptrd,l,k,1,1,true) = CImg<double>(ptr1,k,l,1,1,true).get_transpose();
+        return cimg::type<double>::nan();
+      }
+
+      static double mp_u(_cimg_math_parser& mp) {
+        return cimg::rand(_mp_arg(2),_mp_arg(3));
+      }
+
+      static double mp_var(_cimg_math_parser& mp) {
+        CImg<doubleT> vals(mp.opcode._height - 2);
+        double *p = vals.data();
+        for (unsigned int i = 2; i<mp.opcode._height; ++i) *(p++) = _mp_arg(i);
+        return vals.variance();
+      }
+
+      static double mp_vector_copy(_cimg_math_parser& mp) {
+        std::memcpy(&_mp_arg(1) + 1,&_mp_arg(2) + 1,sizeof(double)*mp.opcode[3]);
+        return cimg::type<double>::nan();
+      }
+
+      static double mp_vector_crop(_cimg_math_parser& mp) {
+        double *const ptrd = &_mp_arg(1) + 1;
+        const double *const ptrs = &_mp_arg(2) + 1;
+        const unsigned int p1 = mp.opcode[3], p2 = mp.opcode[4];
+        std::memcpy(ptrd,ptrs + p1,p2*sizeof(double));
+        return cimg::type<double>::nan();
+      }
+
+      static double mp_vector_init(_cimg_math_parser& mp) {
+        unsigned int
+          ptrs = 3U,
+          ptrd = (unsigned int)mp.opcode[1] + 1,
+          siz = (unsigned int)mp.opcode[2];
+        switch (mp.opcode._height) {
+        case 3 : std::memset(mp.mem._data + ptrd,0,siz*sizeof(double)); break; // 0 values given
+        case 4 : { const double val = _mp_arg(ptrs); while (siz-->0) mp.mem[ptrd++] = val; } break;
+        default : while (siz-->0) { mp.mem[ptrd++] = _mp_arg(ptrs++); if (ptrs>=mp.opcode._height) ptrs = 3U; }
+        }
+        return cimg::type<double>::nan();
+      }
+
+      static double mp_vector_map_sv(_cimg_math_parser& mp) { // Operator(scalar,vector)
+        unsigned int
+          siz = (unsigned int)mp.opcode[2],
+          ptrs = (unsigned int)mp.opcode[5] + 1;
+        double *ptrd = &_mp_arg(1) + 1;
+        mp_func op = (mp_func)mp.opcode[3];
+        CImg<ulongT> l_opcode(4);
+        l_opcode[2] = mp.opcode[4]; // Scalar argument1
+        l_opcode.swap(mp.opcode);
+        ulongT &argument2 = mp.opcode[3];
+        while (siz-->0) { argument2 = ptrs++; *(ptrd++) = (*op)(mp); }
+        l_opcode.swap(mp.opcode);
+        return cimg::type<double>::nan();
+      }
+
+      static double mp_vector_map_v(_cimg_math_parser& mp) { // Operator(vector)
+        unsigned int
+          siz = (unsigned int)mp.opcode[2],
+          ptrs = (unsigned int)mp.opcode[4] + 1;
+        double *ptrd = &_mp_arg(1) + 1;
+        mp_func op = (mp_func)mp.opcode[3];
+        CImg<ulongT> l_opcode(1,3);
+        l_opcode.swap(mp.opcode);
+        ulongT &argument = mp.opcode[2];
+        while (siz-->0) { argument = ptrs++; *(ptrd++) = (*op)(mp); }
+        l_opcode.swap(mp.opcode);
+        return cimg::type<double>::nan();
+      }
+
+      static double mp_vector_map_vs(_cimg_math_parser& mp) { // Operator(vector,scalar)
+        unsigned int
+          siz = (unsigned int)mp.opcode[2],
+          ptrs = (unsigned int)mp.opcode[4] + 1;
+        double *ptrd = &_mp_arg(1) + 1;
+        mp_func op = (mp_func)mp.opcode[3];
+        CImg<ulongT> l_opcode(1,4);
+        l_opcode[3] = mp.opcode[5]; // Scalar argument2
+        l_opcode.swap(mp.opcode);
+        ulongT &argument1 = mp.opcode[2];
+        while (siz-->0) { argument1 = ptrs++; *(ptrd++) = (*op)(mp); }
+        l_opcode.swap(mp.opcode);
+        return cimg::type<double>::nan();
+      }
+
+      static double mp_vector_map_vss(_cimg_math_parser& mp) { // Operator(vector,scalar,scalar)
+        unsigned int
+          siz = (unsigned int)mp.opcode[2],
+          ptrs = (unsigned int)mp.opcode[4] + 1;
+        double *ptrd = &_mp_arg(1) + 1;
+        mp_func op = (mp_func)mp.opcode[3];
+        CImg<ulongT> l_opcode(1,5);
+        l_opcode[3] = mp.opcode[5]; // Scalar argument2
+        l_opcode[4] = mp.opcode[6]; // Scalar argument3
+        l_opcode.swap(mp.opcode);
+        ulongT &argument1 = mp.opcode[2];
+        while (siz-->0) { argument1 = ptrs++; *(ptrd++) = (*op)(mp); }
+        l_opcode.swap(mp.opcode);
+        return cimg::type<double>::nan();
+      }
+
+      static double mp_vector_map_vv(_cimg_math_parser& mp) { // Operator(vector,vector)
+        unsigned int
+          siz = (unsigned int)mp.opcode[2],
+          ptrs1 = (unsigned int)mp.opcode[4] + 1,
+          ptrs2 = (unsigned int)mp.opcode[5] + 1;
+        double *ptrd = &_mp_arg(1) + 1;
+        mp_func op = (mp_func)mp.opcode[3];
+        CImg<ulongT> l_opcode(1,4);
+        l_opcode.swap(mp.opcode);
+        ulongT &argument1 = mp.opcode[2], &argument2 = mp.opcode[3];
+        while (siz-->0) { argument1 = ptrs1++; argument2 = ptrs2++; *(ptrd++) = (*op)(mp); }
+        l_opcode.swap(mp.opcode);
+        return cimg::type<double>::nan();
+      }
+
+      static double mp_vector_off(_cimg_math_parser& mp) {
+        const unsigned int
+          ptr = mp.opcode[2] + 1,
+          siz = (int)mp.opcode[3];
+        const int off = (int)_mp_arg(4);
+        return off>=0 && off<(int)siz?mp.mem[ptr + off]:cimg::type<double>::nan();
       }
 
-      static double mp_whiledo(_cimg_math_parser& mp) { // Used also by 'for()'.
+      static double mp_vector_set_off(_cimg_math_parser& mp) {
         const unsigned int
-          mem_cond = (unsigned int)mp.opcode(2),
-          mem_proc = (unsigned int)mp.opcode(1);
-        const CImg<longT>
+          ptr = mp.opcode[2] + 1,
+          siz = mp.opcode[3];
+        const int off = (int)_mp_arg(4);
+        if (off>=0 && off<(int)siz) mp.mem[ptr + off] = _mp_arg(5);
+        return _mp_arg(5);
+      }
+
+      static double mp_vector_print(_cimg_math_parser& mp) {
+#ifdef cimg_use_openmp
+#pragma omp critical
+#endif
+        {
+          CImg<charT> expr(mp.opcode._height - 3);
+          const ulongT *ptrs = mp.opcode._data + 3;
+          cimg_for(expr,ptrd,char) *ptrd = (char)*(ptrs++);
+          cimg::strellipsize(expr);
+          unsigned int
+            ptr = mp.opcode[1] + 1,
+            siz = mp.opcode[2];
+          cimg::mutex(6);
+          std::fprintf(cimg::output(),"\n[_cimg_math_parser] %s = [",expr._data);
+          while (siz-->0) std::fprintf(cimg::output(),"%g%s",mp.mem[ptr++],siz?",":"");
+          std::fputc(']',cimg::output());
+          std::fflush(cimg::output());
+          cimg::mutex(6,0);
+        }
+        return cimg::type<double>::nan();
+      }
+
+      static double mp_whiledo(_cimg_math_parser& mp) { // Used also by 'for()'
+        const ulongT
+          mem_proc = mp.opcode[1],
+          mem_cond = mp.opcode[2];
+        const CImg<ulongT>
           *const p_cond = ++mp.p_code,
-          *const p_proc = p_cond + mp.opcode(3),
-          *const p_end = p_proc + mp.opcode(4);
+          *const p_proc = p_cond + mp.opcode[3],
+          *const p_end = p_proc + mp.opcode[4];
+        const unsigned int vsiz = mp.opcode[5];
         bool is_first_iter = true, is_cond = false;
         do {
-          cimg_test_abort();
-          for (mp.p_code = p_cond; mp.p_code<p_proc; ++mp.p_code) { // Evaluate loop condition.
-            cimg_test_abort();
-            const CImg<longT> &op = *mp.p_code;
+          for (mp.p_code = p_cond; mp.p_code<p_proc; ++mp.p_code) { // Evaluate loop condition
+            const CImg<ulongT> &op = *mp.p_code;
             mp.opcode._data = op._data; mp.opcode._height = op._height;
-            const unsigned target = (unsigned int)mp.opcode[1];
+            const ulongT target = mp.opcode[1];
             mp.mem[target] = _cimg_mp_defunc(mp);
           }
           is_cond = (bool)mp.mem[mem_cond];
-          if (is_cond) { // Evaluate loop iteration.
+          if (is_cond) { // Evaluate loop iteration
             for ( ; mp.p_code<p_end; ++mp.p_code) {
-              cimg_test_abort();
-              const CImg<longT> &op = *mp.p_code;
+              const CImg<ulongT> &op = *mp.p_code;
               mp.opcode._data = op._data; mp.opcode._height = op._height;
-              const unsigned int target = (unsigned int)mp.opcode[1];
+              const ulongT target = mp.opcode[1];
               mp.mem[target] = _cimg_mp_defunc(mp);
             }
             is_first_iter = false;
           }
         } while (is_cond);
         mp.p_code = p_end - 1;
+        if (vsiz && is_first_iter) std::memset(&mp.mem[mem_proc] + 1,0,vsiz*sizeof(double));
         return is_first_iter?0:mp.mem[mem_proc];
       }
 
-      static double mp_print(_cimg_math_parser& mp) {
-        const CImg<char> label(mp.opcode);
-        const double val = mp.mem[mp.opcode(1)];
-        std::fprintf(cimg::output(),"\n[_cimg_math_parser] %s = %g",label.data()+2,val);
-        return val;
+      static double mp_Ioff(_cimg_math_parser& mp) {
+        double *ptrd = &_mp_arg(1) + 1;
+        const unsigned int
+          boundary_conditions = (unsigned int)_mp_arg(3);
+        const CImg<T> &img = mp.imgin;
+        const longT
+          off = (longT)_mp_arg(2),
+          whd = (longT)img.width()*img.height()*img.depth();
+        const T *ptrs;
+        if (off<0 || off>=whd)
+          switch (boundary_conditions) {
+          case 2 : // Periodic boundary
+            if (!img) {
+              ptrs = &img[cimg::mod(off,whd)];
+              cimg_forC(img,c) { *(ptrd++) = *ptrs; ptrs+=whd; }
+            } else std::memset(ptrd,0,img._spectrum*sizeof(double));
+            return cimg::type<double>::nan();
+          case 1 : // Neumann boundary
+            if (img) {
+              ptrs = off<0?img._data:&img.back();
+              cimg_forC(img,c) { *(ptrd++) = *ptrs; ptrs+=whd; }
+            } else std::memset(ptrd,0,img._spectrum*sizeof(double));
+            return cimg::type<double>::nan();
+          default : // Dirichet boundary
+            std::memset(ptrd,0,img._spectrum*sizeof(double));
+            return cimg::type<double>::nan();
+          }
+        ptrs = &img[off];
+        cimg_forC(img,c) { *(ptrd++) = *ptrs; ptrs+=whd; }
+        return cimg::type<double>::nan();
+      }
+
+      static double mp_Ixyz(_cimg_math_parser& mp) {
+        double *ptrd = &_mp_arg(1) + 1;
+        const unsigned int
+          interpolation = (unsigned int)_mp_arg(5),
+          boundary_conditions = (unsigned int)_mp_arg(6);
+        const CImg<T> &img = mp.imgin;
+        const double x = _mp_arg(2), y = _mp_arg(3), z = _mp_arg(4);
+        if (interpolation==0) { // Nearest neighbor interpolation
+          if (boundary_conditions==2)
+            cimg_forC(img,c)
+              *(ptrd++) = (double)img.atXYZ(cimg::mod((int)x,img.width()),
+                                            cimg::mod((int)y,img.height()),
+                                            cimg::mod((int)z,img.depth()),
+                                            c);
+          else if (boundary_conditions==1)
+            cimg_forC(img,c)
+              *(ptrd++) = (double)img.atXYZ((int)x,(int)y,(int)z,c);
+          else
+            cimg_forC(img,c)
+              *(ptrd++) = (double)img.atXYZ((int)x,(int)y,(int)z,c,0);
+        } else { // Linear interpolation
+          if (boundary_conditions==2)
+            cimg_forC(img,c)
+              *(ptrd++) = (double)img.linear_atXYZ(cimg::mod((float)x,(float)img.width()),
+                                                   cimg::mod((float)y,(float)img.height()),
+                                                   cimg::mod((float)z,(float)img.depth()),c);
+          else if (boundary_conditions==1)
+            cimg_forC(img,c)
+              *(ptrd++) = (double)img.linear_atXYZ((float)x,(float)y,(float)z,c);
+          else
+            cimg_forC(img,c)
+              *(ptrd++) = (double)img.linear_atXYZ((float)x,(float)y,(float)z,c,0);
+        }
+        return cimg::type<double>::nan();
       }
 
-      // Evaluation procedure, with image data.
-      double operator()(const double x, const double y, const double z, const double c) {
-        if (!mem) return 0;
-        mem[16] = x; mem[17] = y; mem[18] = z; mem[19] = c;
-        opcode._is_shared = true; opcode._width = opcode._depth = opcode._spectrum = 1;
-        for (p_code = code._data; p_code<code.end(); ++p_code) {
-          cimg_test_abort();
-          const CImg<longT> &op = *p_code;
-          // Allows to avoid parameter passing to evaluation functions.
-          opcode._data = op._data; opcode._height = op._height;
-          const unsigned int target = (unsigned int)opcode[1];
-          mem[target] = _cimg_mp_defunc(*this);
+      static double mp_Joff(_cimg_math_parser& mp) {
+        double *ptrd = &_mp_arg(1) + 1;
+        const unsigned int
+          boundary_conditions = (unsigned int)_mp_arg(3);
+        const CImg<T> &img = mp.imgin;
+        const int ox = (int)mp.mem[_cimg_mp_x], oy = (int)mp.mem[_cimg_mp_y], oz = (int)mp.mem[_cimg_mp_z];
+        const longT
+          off = img.offset(ox,oy,oz) + (longT)_mp_arg(2),
+          whd = (longT)img.width()*img.height()*img.depth();
+        const T *ptrs;
+        if (off<0 || off>=whd)
+          switch (boundary_conditions) {
+          case 2 : // Periodic boundary
+            if (!img) {
+              ptrs = &img[cimg::mod(off,whd)];
+              cimg_forC(img,c) { *(ptrd++) = *ptrs; ptrs+=whd; }
+            } else std::memset(ptrd,0,img._spectrum*sizeof(double));
+            return cimg::type<double>::nan();
+          case 1 : // Neumann boundary
+            if (img) {
+              ptrs = off<0?img._data:&img.back();
+              cimg_forC(img,c) { *(ptrd++) = *ptrs; ptrs+=whd; }
+            } else std::memset(ptrd,0,img._spectrum*sizeof(double));
+            return cimg::type<double>::nan();
+          default : // Dirichet boundary
+            std::memset(ptrd,0,img._spectrum*sizeof(double));
+            return cimg::type<double>::nan();
+          }
+        ptrs = &img[off];
+        cimg_forC(img,c) { *(ptrd++) = *ptrs; ptrs+=whd; }
+        return cimg::type<double>::nan();
+      }
+
+      static double mp_Jxyz(_cimg_math_parser& mp) {
+        double *ptrd = &_mp_arg(1) + 1;
+        const unsigned int
+          interpolation = (unsigned int)_mp_arg(5),
+          boundary_conditions = (unsigned int)_mp_arg(6);
+        const CImg<T> &img = mp.imgin;
+        const double
+          ox = mp.mem[_cimg_mp_x], oy = mp.mem[_cimg_mp_y], oz = mp.mem[_cimg_mp_z],
+          x = ox + _mp_arg(2), y = oy + _mp_arg(3), z = oz + _mp_arg(4);
+        if (interpolation==0) { // Nearest neighbor interpolation
+          if (boundary_conditions==2)
+            cimg_forC(img,c)
+              *(ptrd++) = (double)img.atXYZ(cimg::mod((int)x,img.width()),
+                                            cimg::mod((int)y,img.height()),
+                                            cimg::mod((int)z,img.depth()),
+                                            c);
+          else if (boundary_conditions==1)
+            cimg_forC(img,c)
+              *(ptrd++) = (double)img.atXYZ((int)x,(int)y,(int)z,c);
+          else
+            cimg_forC(img,c)
+              *(ptrd++) = (double)img.atXYZ((int)x,(int)y,(int)z,c,0);
+        } else { // Linear interpolation
+          if (boundary_conditions==2)
+            cimg_forC(img,c)
+              *(ptrd++) = (double)img.linear_atXYZ(cimg::mod((float)x,(float)img.width()),
+                                                   cimg::mod((float)y,(float)img.height()),
+                                                   cimg::mod((float)z,(float)img.depth()),c);
+          else if (boundary_conditions==1)
+            cimg_forC(img,c)
+              *(ptrd++) = (double)img.linear_atXYZ((float)x,(float)y,(float)z,c);
+          else
+            cimg_forC(img,c)
+              *(ptrd++) = (double)img.linear_atXYZ((float)x,(float)y,(float)z,c,0);
         }
-        return mem[result];
+        return cimg::type<double>::nan();
       }
-    };
+
+#undef _mp_arg
+
+    }; // struct _cimg_math_parser {}
 
     //! Compute the square value of each pixel value.
     /**
@@ -15326,7 +19687,7 @@ namespace cimg_library_suffixed {
     CImg<T>& sqr() {
       if (is_empty()) return *this;
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (size()>=524288)
+#pragma omp parallel for cimg_openmp_if(size()>=524288)
 #endif
       cimg_rof(*this,ptrd,T) { const T val = *ptrd; *ptrd = (T)(val*val); };
       return *this;
@@ -15353,7 +19714,7 @@ namespace cimg_library_suffixed {
     CImg<T>& sqrt() {
       if (is_empty()) return *this;
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (size()>=8192)
+#pragma omp parallel for cimg_openmp_if(size()>=8192)
 #endif
       cimg_rof(*this,ptrd,T) *ptrd = (T)std::sqrt((double)*ptrd);
       return *this;
@@ -15374,7 +19735,7 @@ namespace cimg_library_suffixed {
     CImg<T>& exp() {
       if (is_empty()) return *this;
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (size()>=4096)
+#pragma omp parallel for cimg_openmp_if(size()>=4096)
 #endif
       cimg_rof(*this,ptrd,T) *ptrd = (T)std::exp((double)*ptrd);
       return *this;
@@ -15396,7 +19757,7 @@ namespace cimg_library_suffixed {
     CImg<T>& log() {
       if (is_empty()) return *this;
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (size()>=262144)
+#pragma omp parallel for cimg_openmp_if(size()>=262144)
 #endif
       cimg_rof(*this,ptrd,T) *ptrd = (T)std::log((double)*ptrd);
       return *this;
@@ -15418,7 +19779,7 @@ namespace cimg_library_suffixed {
     CImg<T>& log2() {
       if (is_empty()) return *this;
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (size()>=4096)
+#pragma omp parallel for cimg_openmp_if(size()>=4096)
 #endif
       cimg_rof(*this,ptrd,T) *ptrd = (T)cimg::log2((double)*ptrd);
       return *this;
@@ -15440,7 +19801,7 @@ namespace cimg_library_suffixed {
     CImg<T>& log10() {
       if (is_empty()) return *this;
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (size()>=4096)
+#pragma omp parallel for cimg_openmp_if(size()>=4096)
 #endif
       cimg_rof(*this,ptrd,T) *ptrd = (T)std::log10((double)*ptrd);
       return *this;
@@ -15461,7 +19822,7 @@ namespace cimg_library_suffixed {
     CImg<T>& abs() {
       if (is_empty()) return *this;
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (size()>=524288)
+#pragma omp parallel for cimg_openmp_if(size()>=524288)
 #endif
       cimg_rof(*this,ptrd,T) *ptrd = cimg::abs(*ptrd);
       return *this;
@@ -15487,7 +19848,7 @@ namespace cimg_library_suffixed {
     CImg<T>& sign() {
       if (is_empty()) return *this;
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (size()>=32768)
+#pragma omp parallel for cimg_openmp_if(size()>=32768)
 #endif
       cimg_rof(*this,ptrd,T) *ptrd = cimg::sign(*ptrd);
       return *this;
@@ -15509,7 +19870,7 @@ namespace cimg_library_suffixed {
     CImg<T>& cos() {
       if (is_empty()) return *this;
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (size()>=8192)
+#pragma omp parallel for cimg_openmp_if(size()>=8192)
 #endif
       cimg_rof(*this,ptrd,T) *ptrd = (T)std::cos((double)*ptrd);
       return *this;
@@ -15531,7 +19892,7 @@ namespace cimg_library_suffixed {
     CImg<T>& sin() {
       if (is_empty()) return *this;
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (size()>=8192)
+#pragma omp parallel for cimg_openmp_if(size()>=8192)
 #endif
       cimg_rof(*this,ptrd,T) *ptrd = (T)std::sin((double)*ptrd);
       return *this;
@@ -15554,7 +19915,7 @@ namespace cimg_library_suffixed {
     CImg<T>& sinc() {
       if (is_empty()) return *this;
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (size()>=2048)
+#pragma omp parallel for cimg_openmp_if(size()>=2048)
 #endif
       cimg_rof(*this,ptrd,T) *ptrd = (T)cimg::sinc((double)*ptrd);
       return *this;
@@ -15576,7 +19937,7 @@ namespace cimg_library_suffixed {
     CImg<T>& tan() {
       if (is_empty()) return *this;
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (size()>=2048)
+#pragma omp parallel for cimg_openmp_if(size()>=2048)
 #endif
       cimg_rof(*this,ptrd,T) *ptrd = (T)std::tan((double)*ptrd);
       return *this;
@@ -15598,7 +19959,7 @@ namespace cimg_library_suffixed {
     CImg<T>& cosh() {
       if (is_empty()) return *this;
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (size()>=2048)
+#pragma omp parallel for cimg_openmp_if(size()>=2048)
 #endif
       cimg_rof(*this,ptrd,T) *ptrd = (T)std::cosh((double)*ptrd);
       return *this;
@@ -15620,7 +19981,7 @@ namespace cimg_library_suffixed {
     CImg<T>& sinh() {
       if (is_empty()) return *this;
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (size()>=2048)
+#pragma omp parallel for cimg_openmp_if(size()>=2048)
 #endif
       cimg_rof(*this,ptrd,T) *ptrd = (T)std::sinh((double)*ptrd);
       return *this;
@@ -15642,7 +20003,7 @@ namespace cimg_library_suffixed {
     CImg<T>& tanh() {
       if (is_empty()) return *this;
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (size()>=2048)
+#pragma omp parallel for cimg_openmp_if(size()>=2048)
 #endif
       cimg_rof(*this,ptrd,T) *ptrd = (T)std::tanh((double)*ptrd);
       return *this;
@@ -15664,7 +20025,7 @@ namespace cimg_library_suffixed {
     CImg<T>& acos() {
       if (is_empty()) return *this;
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (size()>=8192)
+#pragma omp parallel for cimg_openmp_if(size()>=8192)
 #endif
       cimg_rof(*this,ptrd,T) *ptrd = (T)std::acos((double)*ptrd);
       return *this;
@@ -15686,7 +20047,7 @@ namespace cimg_library_suffixed {
     CImg<T>& asin() {
       if (is_empty()) return *this;
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (size()>=8192)
+#pragma omp parallel for cimg_openmp_if(size()>=8192)
 #endif
       cimg_rof(*this,ptrd,T) *ptrd = (T)std::asin((double)*ptrd);
       return *this;
@@ -15708,7 +20069,7 @@ namespace cimg_library_suffixed {
     CImg<T>& atan() {
       if (is_empty()) return *this;
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (size()>=8192)
+#pragma omp parallel for cimg_openmp_if(size()>=8192)
 #endif
       cimg_rof(*this,ptrd,T) *ptrd = (T)std::atan((double)*ptrd);
       return *this;
@@ -15738,11 +20099,11 @@ namespace cimg_library_suffixed {
     **/
     template<typename t>
     CImg<T>& atan2(const CImg<t>& img) {
-      const unsigned long siz = size(), isiz = img.size();
+      const ulongT siz = size(), isiz = img.size();
       if (siz && isiz) {
         if (is_overlapped(img)) return atan2(+img);
         T *ptrd = _data, *const ptre = _data + siz;
-        if (siz>isiz) for (unsigned long n = siz/isiz; n; --n)
+        if (siz>isiz) for (ulongT n = siz/isiz; n; --n)
           for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs<ptrs_end; ++ptrd)
             *ptrd = (T)std::atan2((double)*ptrd,(double)*(ptrs++));
         for (const t *ptrs = img._data; ptrd<ptre; ++ptrd) *ptrd = (T)std::atan2((double)*ptrd,(double)*(ptrs++));
@@ -15775,11 +20136,11 @@ namespace cimg_library_suffixed {
     **/
     template<typename t>
     CImg<T>& mul(const CImg<t>& img) {
-      const unsigned long siz = size(), isiz = img.size();
+      const ulongT siz = size(), isiz = img.size();
       if (siz && isiz) {
         if (is_overlapped(img)) return mul(+img);
         T *ptrd = _data, *const ptre = _data + siz;
-        if (siz>isiz) for (unsigned long n = siz/isiz; n; --n)
+        if (siz>isiz) for (ulongT n = siz/isiz; n; --n)
           for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs<ptrs_end; ++ptrd)
             *ptrd = (T)(*ptrd * *(ptrs++));
         for (const t *ptrs = img._data; ptrd<ptre; ++ptrd) *ptrd = (T)(*ptrd * *(ptrs++));
@@ -15799,11 +20160,11 @@ namespace cimg_library_suffixed {
     **/
     template<typename t>
     CImg<T>& div(const CImg<t>& img) {
-      const unsigned long siz = size(), isiz = img.size();
+      const ulongT siz = size(), isiz = img.size();
       if (siz && isiz) {
         if (is_overlapped(img)) return div(+img);
         T *ptrd = _data, *const ptre = _data + siz;
-        if (siz>isiz) for (unsigned long n = siz/isiz; n; --n)
+        if (siz>isiz) for (ulongT n = siz/isiz; n; --n)
           for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs<ptrs_end; ++ptrd)
             *ptrd = (T)(*ptrd / *(ptrs++));
         for (const t *ptrs = img._data; ptrd<ptre; ++ptrd) *ptrd = (T)(*ptrd / *(ptrs++));
@@ -15837,35 +20198,35 @@ namespace cimg_library_suffixed {
       if (is_empty()) return *this;
       if (p==-4) {
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (size()>=32768)
+#pragma omp parallel for cimg_openmp_if(size()>=32768)
 #endif
         cimg_rof(*this,ptrd,T) { const T val = *ptrd; *ptrd = (T)(1.0/(val*val*val*val)); }
         return *this;
       }
       if (p==-3) {
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (size()>=32768)
+#pragma omp parallel for cimg_openmp_if(size()>=32768)
 #endif
         cimg_rof(*this,ptrd,T) { const T val = *ptrd; *ptrd = (T)(1.0/(val*val*val)); }
         return *this;
       }
       if (p==-2) {
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (size()>=32768)
+#pragma omp parallel for cimg_openmp_if(size()>=32768)
 #endif
         cimg_rof(*this,ptrd,T) { const T val = *ptrd; *ptrd = (T)(1.0/(val*val)); }
         return *this;
       }
       if (p==-1) {
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (size()>=32768)
+#pragma omp parallel for cimg_openmp_if(size()>=32768)
 #endif
         cimg_rof(*this,ptrd,T) { const T val = *ptrd; *ptrd = (T)(1.0/val); }
         return *this;
       }
       if (p==-0.5) {
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (size()>=8192)
+#pragma omp parallel for cimg_openmp_if(size()>=8192)
 #endif
         cimg_rof(*this,ptrd,T) { const T val = *ptrd; *ptrd = (T)(1/std::sqrt((double)val)); }
         return *this;
@@ -15876,20 +20237,20 @@ namespace cimg_library_suffixed {
       if (p==2) return sqr();
       if (p==3) {
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (size()>=262144)
+#pragma omp parallel for cimg_openmp_if(size()>=262144)
 #endif
         cimg_rof(*this,ptrd,T) { const T val = *ptrd; *ptrd = val*val*val; }
         return *this;
       }
       if (p==4) {
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (size()>=131072)
+#pragma omp parallel for cimg_openmp_if(size()>=131072)
 #endif
         cimg_rof(*this,ptrd,T) { const T val = *ptrd; *ptrd = val*val*val*val; }
         return *this;
       }
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (size()>=1024)
+#pragma omp parallel for cimg_openmp_if(size()>=1024)
 #endif
       cimg_rof(*this,ptrd,T) *ptrd = (T)std::pow((double)*ptrd,p);
       return *this;
@@ -15905,44 +20266,7 @@ namespace cimg_library_suffixed {
        Similar to operator+=(const char*), except it performs a pointwise exponentiation instead of an addition.
     **/
     CImg<T>& pow(const char *const expression) {
-      if (is_empty()) return *this;
-      const unsigned int omode = cimg::exception_mode();
-      cimg::exception_mode(0);
-      try {
-        const CImg<T> _base = cimg::_is_self_expr(expression)?+*this:CImg<T>(), &base = _base?_base:*this;
-        _cimg_math_parser mp(base,this,expression + (*expression=='>' || *expression=='<'?1:0),"pow");
-        T *ptrd = *expression=='<'?end() - 1:_data;
-        if (*expression=='<') cimg_rofXYZC(*this,x,y,z,c) { *ptrd = (T)std::pow((double)*ptrd,mp(x,y,z,c)); --ptrd; }
-        else if (*expression=='>')
-          cimg_forXYZC(*this,x,y,z,c) { *ptrd = (T)std::pow((double)*ptrd,mp(x,y,z,c)); ++ptrd; }
-        else {
-#ifdef cimg_use_openmp
-          if (_width>=512 && _height*_depth*_spectrum>=2 && std::strlen(expression)>=6)
-#pragma omp parallel
-          {
-            _cimg_math_parser _mp = omp_get_thread_num()?mp:_cimg_math_parser(), &lmp = omp_get_thread_num()?_mp:mp;
-#pragma omp for collapse(3)
-            cimg_forYZC(*this,y,z,c) {
-              T *ptrd = data(0,y,z,c);
-              cimg_forX(*this,x) { *ptrd = (T)std::pow((double)*ptrd,lmp(x,y,z,c)); ++ptrd; }
-            }
-          }
-          else
-#endif
-            cimg_forXYZC(*this,x,y,z,c) { *ptrd = (T)std::pow((double)*ptrd,mp(x,y,z,c)); ++ptrd; }
-        }
-      } catch (CImgException&) {
-        CImg<Tfloat> values(_width,_height,_depth,_spectrum);
-        try {
-          values.fill(expression,true);
-        } catch (CImgException&) {
-          cimg::exception_mode(omode);
-          values.load(expression);
-        }
-        pow(values);
-      }
-      cimg::exception_mode(omode);
-      return *this;
+      return pow((+*this)._fill(expression,true,true,0,0,"pow",this));
     }
 
     //! Raise each pixel value to a power, specified from an expression \newinstance.
@@ -15956,11 +20280,11 @@ namespace cimg_library_suffixed {
     **/
     template<typename t>
     CImg<T>& pow(const CImg<t>& img) {
-      const unsigned long siz = size(), isiz = img.size();
+      const ulongT siz = size(), isiz = img.size();
       if (siz && isiz) {
         if (is_overlapped(img)) return pow(+img);
         T *ptrd = _data, *const ptre = _data + siz;
-        if (siz>isiz) for (unsigned long n = siz/isiz; n; --n)
+        if (siz>isiz) for (ulongT n = siz/isiz; n; --n)
           for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs<ptrs_end; ++ptrd)
             *ptrd = (T)std::pow((double)*ptrd,(double)(*(ptrs++)));
         for (const t *ptrs = img._data; ptrd<ptre; ++ptrd) *ptrd = (T)std::pow((double)*ptrd,(double)(*(ptrs++)));
@@ -15981,7 +20305,7 @@ namespace cimg_library_suffixed {
     CImg<T>& rol(const unsigned int n=1) {
       if (is_empty()) return *this;
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (size()>=32768)
+#pragma omp parallel for cimg_openmp_if(size()>=32768)
 #endif
       cimg_rof(*this,ptrd,T) *ptrd = (T)cimg::rol(*ptrd,n);
       return *this;
@@ -15997,45 +20321,7 @@ namespace cimg_library_suffixed {
        Similar to operator<<=(const char*), except that it performs a left rotation instead of a left shift.
     **/
     CImg<T>& rol(const char *const expression) {
-      if (is_empty()) return *this;
-      const unsigned int omode = cimg::exception_mode();
-      cimg::exception_mode(0);
-      try {
-        const CImg<T> _base = cimg::_is_self_expr(expression)?+*this:CImg<T>(), &base = _base?_base:*this;
-        _cimg_math_parser mp(base,this,expression + (*expression=='>' || *expression=='<'?1:0),"rol");
-        T *ptrd = *expression=='<'?end() - 1:_data;
-        if (*expression=='<')
-          cimg_rofXYZC(*this,x,y,z,c) { *ptrd = (T)cimg::rol(*ptrd,(unsigned int)mp(x,y,z,c)); --ptrd; }
-        else if (*expression=='>')
-          cimg_forXYZC(*this,x,y,z,c) { *ptrd = (T)cimg::rol(*ptrd,(unsigned int)mp(x,y,z,c)); ++ptrd; }
-        else {
-#ifdef cimg_use_openmp
-          if (_width>=512 && _height*_depth*_spectrum>=2 && std::strlen(expression)>=6)
-#pragma omp parallel
-          {
-            _cimg_math_parser _mp = omp_get_thread_num()?mp:_cimg_math_parser(), &lmp = omp_get_thread_num()?_mp:mp;
-#pragma omp for collapse(3)
-            cimg_forYZC(*this,y,z,c) {
-              T *ptrd = data(0,y,z,c);
-              cimg_forX(*this,x) { *ptrd = (T)cimg::rol(*ptrd,(unsigned int)lmp(x,y,z,c)); ++ptrd; }
-            }
-          }
-          else
-#endif
-            cimg_forXYZC(*this,x,y,z,c) { *ptrd = (T)cimg::rol(*ptrd,(unsigned int)mp(x,y,z,c)); ++ptrd; }
-        }
-      } catch (CImgException&) {
-        CImg<Tfloat> values(_width,_height,_depth,_spectrum);
-        try {
-          values.fill(expression,true);
-        } catch (CImgException&) {
-          cimg::exception_mode(omode);
-          values.load(expression);
-        }
-        rol(values);
-      }
-      cimg::exception_mode(omode);
-      return *this;
+      return rol((+*this)._fill(expression,true,true,0,0,"rol",this));
     }
 
     //! Compute the bitwise left rotation of each pixel value \newinstance.
@@ -16049,11 +20335,11 @@ namespace cimg_library_suffixed {
     **/
     template<typename t>
     CImg<T>& rol(const CImg<t>& img) {
-      const unsigned long siz = size(), isiz = img.size();
+      const ulongT siz = size(), isiz = img.size();
       if (siz && isiz) {
         if (is_overlapped(img)) return rol(+img);
         T *ptrd = _data, *const ptre = _data + siz;
-        if (siz>isiz) for (unsigned long n = siz/isiz; n; --n)
+        if (siz>isiz) for (ulongT n = siz/isiz; n; --n)
           for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs<ptrs_end; ++ptrd)
             *ptrd = (T)cimg::rol(*ptrd,(unsigned int)(*(ptrs++)));
         for (const t *ptrs = img._data; ptrd<ptre; ++ptrd) *ptrd = (T)cimg::rol(*ptrd,(unsigned int)(*(ptrs++)));
@@ -16074,7 +20360,7 @@ namespace cimg_library_suffixed {
     CImg<T>& ror(const unsigned int n=1) {
       if (is_empty()) return *this;
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (size()>=32768)
+#pragma omp parallel for cimg_openmp_if(size()>=32768)
 #endif
       cimg_rof(*this,ptrd,T) *ptrd = (T)cimg::ror(*ptrd,n);
       return *this;
@@ -16090,45 +20376,7 @@ namespace cimg_library_suffixed {
        Similar to operator>>=(const char*), except that it performs a right rotation instead of a right shift.
     **/
     CImg<T>& ror(const char *const expression) {
-      if (is_empty()) return *this;
-      const unsigned int omode = cimg::exception_mode();
-      cimg::exception_mode(0);
-      try {
-        const CImg<T> _base = cimg::_is_self_expr(expression)?+*this:CImg<T>(), &base = _base?_base:*this;
-        _cimg_math_parser mp(base,this,expression + (*expression=='>' || *expression=='<'?1:0),"ror");
-        T *ptrd = *expression=='<'?end() - 1:_data;
-        if (*expression=='<')
-          cimg_rofXYZC(*this,x,y,z,c) { *ptrd = (T)cimg::ror(*ptrd,(unsigned int)mp(x,y,z,c)); --ptrd; }
-        else if (*expression=='>')
-          cimg_forXYZC(*this,x,y,z,c) { *ptrd = (T)cimg::ror(*ptrd,(unsigned int)mp(x,y,z,c)); ++ptrd; }
-        else {
-#ifdef cimg_use_openmp
-          if (_width>=512 && _height*_depth*_spectrum>=2 && std::strlen(expression)>=6)
-#pragma omp parallel
-          {
-            _cimg_math_parser _mp = omp_get_thread_num()?mp:_cimg_math_parser(), &lmp = omp_get_thread_num()?_mp:mp;
-#pragma omp for collapse(3)
-            cimg_forYZC(*this,y,z,c) {
-              T *ptrd = data(0,y,z,c);
-              cimg_forX(*this,x) { *ptrd = (T)cimg::ror(*ptrd,(unsigned int)lmp(x,y,z,c)); ++ptrd; }
-            }
-          }
-          else
-#endif
-            cimg_forXYZC(*this,x,y,z,c) { *ptrd = (T)cimg::ror(*ptrd,(unsigned int)mp(x,y,z,c)); ++ptrd; }
-        }
-      } catch (CImgException&) {
-        CImg<Tfloat> values(_width,_height,_depth,_spectrum);
-        try {
-          values.fill(expression,true);
-        } catch (CImgException&) {
-          cimg::exception_mode(omode);
-          values.load(expression);
-        }
-        ror(values);
-      }
-      cimg::exception_mode(omode);
-      return *this;
+      return ror((+*this)._fill(expression,true,true,0,0,"ror",this));
     }
 
     //! Compute the bitwise right rotation of each pixel value \newinstance.
@@ -16142,11 +20390,11 @@ namespace cimg_library_suffixed {
     **/
     template<typename t>
     CImg<T>& ror(const CImg<t>& img) {
-      const unsigned long siz = size(), isiz = img.size();
+      const ulongT siz = size(), isiz = img.size();
       if (siz && isiz) {
         if (is_overlapped(img)) return ror(+img);
         T *ptrd = _data, *const ptre = _data + siz;
-        if (siz>isiz) for (unsigned long n = siz/isiz; n; --n)
+        if (siz>isiz) for (ulongT n = siz/isiz; n; --n)
           for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs<ptrs_end; ++ptrd)
             *ptrd = (T)cimg::ror(*ptrd,(unsigned int)(*(ptrs++)));
         for (const t *ptrs = img._data; ptrd<ptre; ++ptrd) *ptrd = (T)cimg::ror(*ptrd,(unsigned int)(*(ptrs++)));
@@ -16169,7 +20417,7 @@ namespace cimg_library_suffixed {
     CImg<T>& min(const T& val) {
       if (is_empty()) return *this;
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (size()>=65536)
+#pragma omp parallel for cimg_openmp_if(size()>=65536)
 #endif
       cimg_rof(*this,ptrd,T) *ptrd = cimg::min(*ptrd,val);
       return *this;
@@ -16188,11 +20436,11 @@ namespace cimg_library_suffixed {
      **/
     template<typename t>
     CImg<T>& min(const CImg<t>& img) {
-      const unsigned long siz = size(), isiz = img.size();
+      const ulongT siz = size(), isiz = img.size();
       if (siz && isiz) {
         if (is_overlapped(img)) return min(+img);
         T *ptrd = _data, *const ptre = _data + siz;
-        if (siz>isiz) for (unsigned long n = siz/isiz; n; --n)
+        if (siz>isiz) for (ulongT n = siz/isiz; n; --n)
           for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs<ptrs_end; ++ptrd)
             *ptrd = cimg::min((T)*(ptrs++),*ptrd);
         for (const t *ptrs = img._data; ptrd<ptre; ++ptrd) *ptrd = cimg::min((T)*(ptrs++),*ptrd);
@@ -16213,43 +20461,7 @@ namespace cimg_library_suffixed {
        \f$\mathrm{min}(I_{(x,y,z,c)},\mathrm{expr}_{(x,y,z,c)})\f$.
     **/
     CImg<T>& min(const char *const expression) {
-      if (is_empty()) return *this;
-      const unsigned int omode = cimg::exception_mode();
-      cimg::exception_mode(0);
-      try {
-        const CImg<T> _base = cimg::_is_self_expr(expression)?+*this:CImg<T>(), &base = _base?_base:*this;
-        _cimg_math_parser mp(base,this,expression + (*expression=='>' || *expression=='<'?1:0),"min");
-        T *ptrd = *expression=='<'?end() - 1:_data;
-        if (*expression=='<') cimg_rofXYZC(*this,x,y,z,c) { *ptrd = (T)cimg::min(*ptrd,(T)mp(x,y,z,c)); --ptrd; }
-        else if (*expression=='>') cimg_forXYZC(*this,x,y,z,c) { *ptrd = (T)cimg::min(*ptrd,(T)mp(x,y,z,c)); ++ptrd; }
-        else {
-#ifdef cimg_use_openmp
-          if (_width>=512 && _height*_depth*_spectrum>=2 && std::strlen(expression)>=6)
-#pragma omp parallel
-          {
-            _cimg_math_parser _mp = omp_get_thread_num()?mp:_cimg_math_parser(), &lmp = omp_get_thread_num()?_mp:mp;
-#pragma omp for collapse(3)
-            cimg_forYZC(*this,y,z,c) {
-              T *ptrd = data(0,y,z,c);
-              cimg_forX(*this,x) { *ptrd = (T)cimg::min(*ptrd,(T)lmp(x,y,z,c)); ++ptrd; }
-            }
-          }
-          else
-#endif
-            cimg_forXYZC(*this,x,y,z,c) { *ptrd = (T)cimg::min(*ptrd,(T)mp(x,y,z,c)); ++ptrd; }
-        }
-      } catch (CImgException&) {
-        CImg<T> values(_width,_height,_depth,_spectrum);
-        try {
-          values.fill(expression,true);
-        } catch (CImgException&) {
-          cimg::exception_mode(omode);
-          values.load(expression);
-        }
-        min(values);
-      }
-      cimg::exception_mode(omode);
-      return *this;
+      return min((+*this)._fill(expression,true,true,0,0,"min",this));
     }
 
     //! Pointwise min operator between an image and an expression \newinstance.
@@ -16266,7 +20478,7 @@ namespace cimg_library_suffixed {
     CImg<T>& max(const T& val) {
       if (is_empty()) return *this;
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (size()>=65536)
+#pragma omp parallel for cimg_openmp_if(size()>=65536)
 #endif
       cimg_rof(*this,ptrd,T) *ptrd = cimg::max(*ptrd,val);
       return *this;
@@ -16285,11 +20497,11 @@ namespace cimg_library_suffixed {
      **/
     template<typename t>
     CImg<T>& max(const CImg<t>& img) {
-      const unsigned long siz = size(), isiz = img.size();
+      const ulongT siz = size(), isiz = img.size();
       if (siz && isiz) {
         if (is_overlapped(img)) return max(+img);
         T *ptrd = _data, *const ptre = _data + siz;
-        if (siz>isiz) for (unsigned long n = siz/isiz; n; --n)
+        if (siz>isiz) for (ulongT n = siz/isiz; n; --n)
           for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs<ptrs_end; ++ptrd)
             *ptrd = cimg::max((T)*(ptrs++),*ptrd);
         for (const t *ptrs = img._data; ptrd<ptre; ++ptrd) *ptrd = cimg::max((T)*(ptrs++),*ptrd);
@@ -16310,43 +20522,7 @@ namespace cimg_library_suffixed {
        \f$\mathrm{max}(I_{(x,y,z,c)},\mathrm{expr}_{(x,y,z,c)})\f$.
     **/
     CImg<T>& max(const char *const expression) {
-      if (is_empty()) return *this;
-      const unsigned int omode = cimg::exception_mode();
-      cimg::exception_mode(0);
-      try {
-        const CImg<T> _base = cimg::_is_self_expr(expression)?+*this:CImg<T>(), &base = _base?_base:*this;
-        _cimg_math_parser mp(base,this,expression + (*expression=='>' || *expression=='<'?1:0),"max");
-        T *ptrd = *expression=='<'?end() - 1:_data;
-        if (*expression=='<') cimg_rofXYZC(*this,x,y,z,c) { *ptrd = (T)cimg::max(*ptrd,(T)mp(x,y,z,c)); --ptrd; }
-        else if (*expression=='>') cimg_forXYZC(*this,x,y,z,c) { *ptrd = (T)cimg::max(*ptrd,(T)mp(x,y,z,c)); ++ptrd; }
-        else {
-#ifdef cimg_use_openmp
-          if (_width>=512 && _height*_depth*_spectrum>=2 && std::strlen(expression)>=6)
-#pragma omp parallel
-          {
-            _cimg_math_parser _mp = omp_get_thread_num()?mp:_cimg_math_parser(), &lmp = omp_get_thread_num()?_mp:mp;
-#pragma omp for collapse(3)
-            cimg_forYZC(*this,y,z,c) {
-              T *ptrd = data(0,y,z,c);
-              cimg_forX(*this,x) { *ptrd = (T)cimg::max(*ptrd,(T)lmp(x,y,z,c)); ++ptrd; }
-            }
-          }
-          else
-#endif
-            cimg_forXYZC(*this,x,y,z,c) { *ptrd = (T)cimg::max(*ptrd,(T)mp(x,y,z,c)); ++ptrd; }
-        }
-      } catch (CImgException&) {
-        CImg<T> values(_width,_height,_depth,_spectrum);
-        try {
-          values.fill(expression,true);
-        } catch (CImgException&) {
-          cimg::exception_mode(omode);
-          values.load(expression);
-        }
-        max(values);
-      }
-      cimg::exception_mode(omode);
-      return *this;
+      return max((+*this)._fill(expression,true,true,0,0,"max",this));
     }
 
     //! Pointwise max operator between an image and an expression \newinstance.
@@ -16591,7 +20767,7 @@ namespace cimg_library_suffixed {
                                     cimg_instance);
 
       double variance = 0, average = 0;
-      const unsigned long siz = size();
+      const ulongT siz = size();
       switch (variance_method) {
       case 0 : { // Least mean square (standard definition)
         double S = 0, S2 = 0;
@@ -16608,7 +20784,7 @@ namespace cimg_library_suffixed {
       case 2 : { // Least Median of Squares (MAD)
         CImg<Tfloat> buf(*this,false);
         buf.sort();
-        const unsigned long siz2 = siz>>1;
+        const ulongT siz2 = siz>>1;
         const double med_i = (double)buf[siz2];
         cimg_for(buf,ptrs,Tfloat) {
           const double val = (double)*ptrs; *ptrs = (Tfloat)cimg::abs(val - med_i); average+=val;
@@ -16619,14 +20795,14 @@ namespace cimg_library_suffixed {
       } break;
       default : { // Least trimmed of Squares
         CImg<Tfloat> buf(*this,false);
-        const unsigned long siz2 = siz>>1;
+        const ulongT siz2 = siz>>1;
         cimg_for(buf,ptrs,Tfloat) {
           const double val = (double)*ptrs; (*ptrs)=(Tfloat)((*ptrs)*val); average+=val;
         }
         buf.sort();
         double a = 0;
         const Tfloat *ptrs = buf._data;
-        for (unsigned long j = 0; j<siz2; ++j) a+=(double)*(ptrs++);
+        for (ulongT j = 0; j<siz2; ++j) a+=(double)*(ptrs++);
         const double sig = (double)(2.6477*std::sqrt(a/siz2));
         variance = sig*sig;
       }
@@ -16650,14 +20826,14 @@ namespace cimg_library_suffixed {
                                     "variance_noise(): Empty instance.",
                                     cimg_instance);
 
-      const unsigned long siz = size();
+      const ulongT siz = size();
       if (!siz || !_data) return 0;
       if (variance_method>1) { // Compute a scaled version of the Laplacian.
         CImg<Tdouble> tmp(*this);
         if (_depth==1) {
           const double cste = 1.0/std::sqrt(20.0); // Depends on how the Laplacian is computed.
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (_width*_height>=262144 && _spectrum>=2)
+#pragma omp parallel for cimg_openmp_if(_width*_height>=262144 && _spectrum>=2)
 #endif
           cimg_forC(*this,c) {
             CImg_3x3(I,T);
@@ -16669,7 +20845,7 @@ namespace cimg_library_suffixed {
         } else {
           const double cste = 1.0/std::sqrt(42.0); // Depends on how the Laplacian is computed.
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (_width*_height*_depth>=262144 && _spectrum>=2)
+#pragma omp parallel for cimg_openmp_if(_width*_height*_depth>=262144 && _spectrum>=2)
 #endif
           cimg_forC(*this,c) {
             CImg_3x3x3(I,T);
@@ -16726,7 +20902,7 @@ namespace cimg_library_suffixed {
         const double diff = (double)*ptr1 - (double)*(ptr2++);
         vMSE+=diff*diff;
       }
-      const unsigned long siz = img.size();
+      const ulongT siz = img.size();
       if (siz) vMSE/=siz;
       return vMSE;
     }
@@ -16749,20 +20925,25 @@ namespace cimg_library_suffixed {
        \param y Value of the pre-defined variable \c y.
        \param z Value of the pre-defined variable \c z.
        \param c Value of the pre-defined variable \c c.
+       \param list_inputs A list of input images attached to the specified math formula.
+       \param list_outputs A pointer to a list of output images attached to the specified math formula.
     **/
     double eval(const char *const expression,
-                const double x=0, const double y=0, const double z=0, const double c=0) {
-      return _eval(this,expression,x,y,z,c);
+                const double x=0, const double y=0, const double z=0, const double c=0,
+                const CImgList<T> *const list_inputs=0, CImgList<T> *const list_outputs=0) {
+      return _eval(this,expression,x,y,z,c,list_inputs,list_outputs);
     }
 
     //! Evaluate math formula \const.
     double eval(const char *const expression,
-                const double x=0, const double y=0, const double z=0, const double c=0) const {
-      return _eval(0,expression,x,y,z,c);
+                const double x=0, const double y=0, const double z=0, const double c=0,
+                const CImgList<T> *const list_inputs=0, CImgList<T> *const list_outputs=0) const {
+      return _eval(0,expression,x,y,z,c,list_inputs,list_outputs);
     }
 
-    double _eval(CImg<T> *const output, const char *const expression,
-                 const double x=0, const double y=0, const double z=0, const double c=0) const {
+    double _eval(CImg<T> *const img_output, const char *const expression,
+                 const double x, const double y, const double z, const double c,
+                 const CImgList<T> *const list_inputs, CImgList<T> *const list_outputs) const {
       if (!expression) return 0;
       if (!expression[1]) switch (*expression) { // Single-char optimization.
         case 'w' : return (double)_width;
@@ -16771,9 +20952,57 @@ namespace cimg_library_suffixed {
         case 's' : return (double)_spectrum;
         case 'r' : return (double)_is_shared;
         }
-      return _cimg_math_parser(*this,output,expression,"eval")(x,y,z,c);
+      _cimg_math_parser mp(expression + (*expression=='>' || *expression=='<' ||
+                                         *expression=='*' || *expression==':'?1:0),"eval",
+                           *this,img_output,list_inputs,list_outputs);
+      return mp(x,y,z,c);
+    }
+
+    //! Evaluate math formula.
+    /**
+       \param[out] output Contains values of output vector returned by the evaluated expression
+         (or is empty if the returned type is scalar).
+       \param expression Math formula, as a C-string.
+       \param x Value of the pre-defined variable \c x.
+       \param y Value of the pre-defined variable \c y.
+       \param z Value of the pre-defined variable \c z.
+       \param c Value of the pre-defined variable \c c.
+       \param list_inputs A list of input images attached to the specified math formula.
+       \param list_outputs A pointer to a list of output images attached to the specified math formula.
+    **/
+    template<typename t>
+    void eval(CImg<t> &output, const char *const expression,
+              const double x=0, const double y=0, const double z=0, const double c=0,
+              const CImgList<T> *const list_inputs=0, CImgList<T> *const list_outputs=0) {
+      _eval(output,this,expression,x,y,z,c,list_inputs,list_outputs);
+    }
+
+    //! Evaluate math formula \const.
+    template<typename t>
+    void eval(CImg<t>& output, const char *const expression,
+              const double x=0, const double y=0, const double z=0, const double c=0,
+              const CImgList<T> *const list_inputs=0, CImgList<T> *const list_outputs=0) const {
+      _eval(output,0,expression,x,y,z,c,list_inputs,list_outputs);
     }
 
+    template<typename t>
+    void _eval(CImg<t>& output, CImg<T> *const img_output, const char *const expression,
+               const double x, const double y, const double z, const double c,
+               const CImgList<T> *const list_inputs, CImgList<T> *const list_outputs) const {
+      if (!expression) { output.assign(1); *output = 0; }
+      if (!expression[1]) switch (*expression) { // Single-char optimization.
+        case 'w' : output.assign(1); *output = (t)_width;
+        case 'h' : output.assign(1); *output = (t)_height;
+        case 'd' : output.assign(1); *output = (t)_depth;
+        case 's' : output.assign(1); *output = (t)_spectrum;
+        case 'r' : output.assign(1); *output = (t)_is_shared;
+        }
+      _cimg_math_parser mp(expression + (*expression=='>' || *expression=='<' ||
+                                         *expression=='*' || *expression==':'?1:0),"eval",
+                           *this,img_output,list_inputs,list_outputs);
+      output.assign(1,cimg::max(1U,mp.result_dim));
+      mp(x,y,z,c,output._data);
+    }
 
     //! Evaluate math formula on a set of variables.
     /**
@@ -16781,21 +21010,24 @@ namespace cimg_library_suffixed {
        \param xyzc Set of values (x,y,z,c) used for the evaluation.
     **/
     template<typename t>
-    CImg<doubleT> eval(const char *const expression, const CImg<t>& xyzc) {
-      return _eval(this,expression,xyzc);
+    CImg<doubleT> eval(const char *const expression, const CImg<t>& xyzc,
+                       const CImgList<T> *const list_inputs=0, CImgList<T> *const list_outputs=0) {
+      return _eval(this,expression,xyzc,list_inputs,list_outputs);
     }
 
     //! Evaluate math formula on a set of variables \const.
     template<typename t>
-    CImg<doubleT> eval(const char *const expression, const CImg<t>& xyzc) const {
-      return _eval(0,expression,xyzc);
+    CImg<doubleT> eval(const char *const expression, const CImg<t>& xyzc,
+                       const CImgList<T> *const list_inputs=0, CImgList<T> *const list_outputs=0) const {
+      return _eval(0,expression,xyzc,list_inputs,list_outputs);
     }
 
     template<typename t>
-    CImg<doubleT> _eval(CImg<T> *const output, const char *const expression, const CImg<t>& xyzc) const {
+    CImg<doubleT> _eval(CImg<T> *const output, const char *const expression, const CImg<t>& xyzc,
+                        const CImgList<T> *const list_inputs=0, CImgList<T> *const list_outputs=0) const {
       CImg<doubleT> res(1,xyzc.size()/4);
       if (!expression) return res.fill(0);
-      _cimg_math_parser mp(*this,output,expression,"eval");
+      _cimg_math_parser mp(expression,"eval",*this,output,list_inputs,list_outputs);
 #ifdef cimg_use_openmp
 #pragma omp parallel if (res._height>=512 && std::strlen(expression)>=6)
       {
@@ -16827,7 +21059,7 @@ namespace cimg_library_suffixed {
     **/
     CImg<Tdouble> get_stats(const unsigned int variance_method=1) const {
       if (is_empty()) return CImg<doubleT>();
-      const unsigned long siz = size();
+      const ulongT siz = size();
       const T *const odata = _data;
       const T *pm = odata, *pM = odata;
       double S = 0, S2 = 0, P = _data?1:0;
@@ -16957,9 +21189,9 @@ namespace cimg_library_suffixed {
                                     "dot(): Empty specified image.",
                                     cimg_instance);
 
-      const unsigned int nb = cimg::min(size(),img.size());
+      const ulongT nb = cimg::min(size(),img.size());
       double res = 0;
-      for (unsigned int off = 0; off<nb; ++off) res+=(double)_data[off]*(double)img[off];
+      for (ulongT off = 0; off<nb; ++off) res+=(double)_data[off]*(double)img[off];
       return res;
     }
 
@@ -16972,7 +21204,7 @@ namespace cimg_library_suffixed {
     CImg<T> get_vector_at(const unsigned int x, const unsigned int y=0, const unsigned int z=0) const {
       CImg<T> res;
       if (res._height!=_spectrum) res.assign(1,_spectrum);
-      const unsigned long whd = (unsigned long)_width*_height*_depth;
+      const ulongT whd = (ulongT)_width*_height*_depth;
       const T *ptrs = data(x,y,z);
       T *ptrd = res._data;
       cimg_forC(*this,c) { *(ptrd++) = *ptrs; ptrs+=whd; }
@@ -16989,7 +21221,7 @@ namespace cimg_library_suffixed {
     CImg<T> get_matrix_at(const unsigned int x=0, const unsigned int y=0, const unsigned int z=0) const {
       const int n = (int)std::sqrt((double)_spectrum);
       const T *ptrs = data(x,y,z,0);
-      const unsigned long whd = (unsigned long)_width*_height*_depth;
+      const ulongT whd = (ulongT)_width*_height*_depth;
       CImg<T> res(n,n);
       T *ptrd = res._data;
       cimg_forC(*this,c) { *(ptrd++) = *ptrs; ptrs+=whd; }
@@ -17004,7 +21236,7 @@ namespace cimg_library_suffixed {
     **/
     CImg<T> get_tensor_at(const unsigned int x, const unsigned int y=0, const unsigned int z=0) const {
       const T *ptrs = data(x,y,z,0);
-      const unsigned long whd = (unsigned long)_width*_height*_depth;
+      const ulongT whd = (ulongT)_width*_height*_depth;
       if (_spectrum==6)
         return tensor(*ptrs,*(ptrs + whd),*(ptrs + 2*whd),*(ptrs + 3*whd),*(ptrs + 4*whd),*(ptrs + 5*whd));
       if (_spectrum==3)
@@ -17023,7 +21255,7 @@ namespace cimg_library_suffixed {
     CImg<T>& set_vector_at(const CImg<t>& vec, const unsigned int x, const unsigned int y=0, const unsigned int z=0) {
       if (x<_width && y<_height && z<_depth) {
         const t *ptrs = vec._data;
-        const unsigned long whd = (unsigned long)_width*_height*_depth;
+        const ulongT whd = (ulongT)_width*_height*_depth;
         T *ptrd = data(x,y,z);
         for (unsigned int k = cimg::min((unsigned int)vec.size(),_spectrum); k; --k) {
           *ptrd = (T)*(ptrs++); ptrd+=whd;
@@ -17054,7 +21286,7 @@ namespace cimg_library_suffixed {
     template<typename t>
     CImg<T>& set_tensor_at(const CImg<t>& ten, const unsigned int x=0, const unsigned int y=0, const unsigned int z=0) {
       T *ptrd = data(x,y,z,0);
-      const unsigned long siz = (unsigned long)_width*_height*_depth;
+      const ulongT siz = (ulongT)_width*_height*_depth;
       if (ten._height==2) {
         *ptrd = (T)ten[0]; ptrd+=siz;
         *ptrd = (T)ten[1]; ptrd+=siz;
@@ -17088,7 +21320,7 @@ namespace cimg_library_suffixed {
     /**
      **/
     CImg<T>& matrix() {
-      const unsigned long siz = size();
+      const ulongT siz = size();
       switch (siz) {
       case 1 : break;
       case 4 : _width = _height = 2; break;
@@ -17101,7 +21333,7 @@ namespace cimg_library_suffixed {
       case 81 : _width = _height = 9; break;
       case 100 : _width = _height = 10; break;
       default : {
-        unsigned long i = 11, i2 = i*i;
+        ulongT i = 11, i2 = i*i;
         while (i2<siz) { i2+=2*i + 1; ++i; }
         if (i2==siz) _width = _height = i;
         else throw CImgInstanceException(_cimg_instance
@@ -17128,7 +21360,7 @@ namespace cimg_library_suffixed {
     //! Resize image to become a symmetric tensor \newinstance.
     CImg<T> get_tensor() const {
       CImg<T> res;
-      const unsigned long siz = size();
+      const ulongT siz = size();
       switch (siz) {
       case 1 : break;
       case 3 :
@@ -17360,13 +21592,13 @@ namespace cimg_library_suffixed {
                                     "incompatible dimensions.",
                                     cimg_instance,
                                     A._width,A._height,A._depth,A._spectrum,A._data);
-      if (_width!=1) {
-        cimg_forX(*this,i) draw_image(i,get_column(i).solve(A));
-        return *this;
-      }
-
       typedef _cimg_Ttfloat Ttfloat;
-      if (A._width==A._height) {
+      if (A._width==A._height) { // Classical linear system
+        if (_width!=1) {
+          CImg<T> res(_width,A._width);
+          cimg_forX(*this,i) res.draw_image(i,get_column(i).solve(A));
+          return res.move_to(*this);
+        }
 #ifdef cimg_use_lapack
         char TRANS = 'N';
         int INFO, N = _height, LWORK = 4*N, *const IPIV = new int[N];
@@ -17402,6 +21634,11 @@ namespace cimg_library_suffixed {
 #endif
       } else { // Least-square solution for non-square systems.
 #ifdef cimg_use_lapack
+        if (_width!=1) {
+          CImg<T> res(_width,A._width);
+          cimg_forX(*this,i) res.draw_image(i,get_column(i).solve(A));
+          return res.move_to(*this);
+        }
 	char TRANS = 'N';
         int INFO, N = A._width, M = A._height, LWORK = -1, LDA = M, LDB = M, NRHS = _width;
 	Ttfloat WORK_QUERY;
@@ -17509,8 +21746,8 @@ namespace cimg_library_suffixed {
                                       "eigen(): Instance is not a square matrix.",
                                       cimg_instance);
 
-        if (val.size()<(unsigned long)_width) val.assign(1,_width);
-        if (vec.size()<(unsigned long)_width*_width) vec.assign(_width,_width);
+        if (val.size()<(ulongT)_width) val.assign(1,_width);
+        if (vec.size()<(ulongT)_width*_width) vec.assign(_width,_width);
         switch (_width) {
         case 1 : { val[0] = (t)(*this)[0]; vec[0] = (t)1; } break;
         case 2 : {
@@ -18920,43 +23157,103 @@ namespace cimg_library_suffixed {
        \param expression C-string describing a math formula, or a list of values.
        \param repeat_values In case a list of values is provided, tells if this list must be repeated for the filling.
        \param allow_formula tells if a formula is allowed or only a list of values.
+       \param list_inputs In case of a mathematical expression, attach a list of images to the specified expression.
+       \param list_outputs In case of a mathematical expression, attach a list of images to the specified expression.
     **/
-    CImg<T>& fill(const char *const expression, const bool repeat_values, const bool allow_formula=true) {
+    CImg<T>& fill(const char *const expression, const bool repeat_values, const bool allow_formula=true,
+                  const CImgList<T> *const list_inputs=0, CImgList<T> *const list_outputs=0) {
+      return _fill(expression,repeat_values,allow_formula,list_inputs,list_outputs,"fill",0);
+    }
+
+    CImg<T>& _fill(const char *const expression, const bool repeat_values, const bool allow_formula,
+                   const CImgList<T> *const list_inputs, CImgList<T> *const list_outputs,
+                   const char *const calling_function, const CImg<T> *provides_copy) {
       if (is_empty() || !expression || !*expression) return *this;
       const unsigned int omode = cimg::exception_mode();
       cimg::exception_mode(0);
       CImg<charT> is_error;
 
-      if (allow_formula) try { // Try to fill values according to a formula.
-        const CImg<T> _base = cimg::_is_self_expr(expression)?+*this:CImg<T>(), &base = _base?_base:*this;
-        _cimg_math_parser mp(base,this,expression + (*expression=='>' || *expression=='<'?1:0),"fill");
-        T *ptrd = *expression=='<'?end() - 1:_data;
-        if (*expression=='<') cimg_rofXYZC(*this,x,y,z,c) *(ptrd--) = (T)mp(x,y,z,c);
-        else if (*expression=='>') cimg_forXYZC(*this,x,y,z,c) *(ptrd++) = (T)mp(x,y,z,c);
-        else {
+      if (allow_formula) try { // Try to fill values according to a formula
+          CImg<T> base = provides_copy?provides_copy->get_shared():get_shared();
+          _cimg_math_parser mp(expression + (*expression=='>' || *expression=='<' ||
+                                             *expression=='*' || *expression==':'?1:0),
+                               calling_function,base,this,list_inputs,list_outputs);
+          if (!provides_copy && expression && *expression!='>' && *expression!='<' && *expression!=':' &&
+              mp.need_input_copy)
+            base.assign().assign(*this); // Needs input copy
+
+          bool do_in_parallel = false;
+#ifdef cimg_use_openmp
+          cimg_openmp_if(*expression=='*' || *expression==':' ||
+                         (mp.is_parallelizable && _width>=320 && _height*_depth*_spectrum>=2 &&
+                          std::strlen(expression)>=6))
+            do_in_parallel = true;
+#endif
+          if (mp.result_dim) { // Vector-valued expression
+            const unsigned int N = cimg::min(mp.result_dim,_spectrum);
+            const ulongT whd = (ulongT)_width*_height*_depth;
+            T *ptrd = *expression=='<'?_data + _width*_height*_depth - 1:_data;
+            if (*expression=='<') {
+              CImg<doubleT> res(1,mp.result_dim);
+              cimg_rofXYZ(*this,x,y,z) {
+                mp(x,y,z,0,res._data);
+                const double *ptrs = res._data;
+                T *_ptrd = ptrd--; for (unsigned int n = N; n>0; --n) { *_ptrd = (T)(*ptrs++); _ptrd+=whd; }
+              }
+            } else if (*expression=='>' || !do_in_parallel) {
+              CImg<doubleT> res(1,mp.result_dim);
+              cimg_forXYZ(*this,x,y,z) {
+                mp(x,y,z,0,res._data);
+                const double *ptrs = res._data;
+                T *_ptrd = ptrd++; for (unsigned int n = N; n>0; --n) { *_ptrd = (T)(*ptrs++); _ptrd+=whd; }
+              }
+            } else {
 #ifdef cimg_use_openmp
-          if (_width>=512 && _height*_depth*_spectrum>=2 && std::strlen(expression)>=6)
 #pragma omp parallel
-            {
-              _cimg_math_parser _mp = omp_get_thread_num()?mp:_cimg_math_parser(), &lmp = omp_get_thread_num()?_mp:mp;
-#pragma omp for collapse(3)
-              cimg_forYZC(*this,y,z,c) {
-                T *ptrd = data(0,y,z,c);
-                cimg_forX(*this,x) *ptrd++ = (T)lmp(x,y,z,c);
+              {
+                _cimg_math_parser _mp = omp_get_thread_num()?mp:_cimg_math_parser(), &lmp = omp_get_thread_num()?_mp:mp;
+#pragma omp for collapse(2)
+                cimg_forYZ(*this,y,z) {
+                  CImg<doubleT> res(1,lmp.result_dim);
+                  T *ptrd = data(0,y,z,0);
+                  cimg_forX(*this,x) {
+                    lmp(x,y,z,0,res._data);
+                    const double *ptrs = res._data;
+                    T *_ptrd = ptrd++; for (unsigned int n = N; n>0; --n) { *_ptrd = (T)(*ptrs++); _ptrd+=whd; }
+                  }
+                }
               }
+#endif
             }
-          else
+
+          } else { // Scalar-valued expression
+            T *ptrd = *expression=='<'?end() - 1:_data;
+            if (*expression=='<')
+              cimg_rofXYZC(*this,x,y,z,c) *(ptrd--) = (T)mp(x,y,z,c);
+            else if (*expression=='>' || !do_in_parallel)
+              cimg_forXYZC(*this,x,y,z,c) *(ptrd++) = (T)mp(x,y,z,c);
+            else {
+#ifdef cimg_use_openmp
+#pragma omp parallel
+              {
+                _cimg_math_parser _mp = omp_get_thread_num()?mp:_cimg_math_parser(), &lmp = omp_get_thread_num()?_mp:mp;
+#pragma omp for collapse(3)
+                cimg_forYZC(*this,y,z,c) {
+                  T *ptrd = data(0,y,z,c);
+                  cimg_forX(*this,x) *ptrd++ = (T)lmp(x,y,z,c);
+                }
+              }
 #endif
-            cimg_forXYZC(*this,x,y,z,c) *(ptrd++) = (T)mp(x,y,z,c);
-        }
-      } catch (CImgException& e) { CImg<charT>::string(e._message).move_to(is_error); }
+            }
+          }
+        } catch (CImgException& e) { CImg<charT>::string(e._message).move_to(is_error); }
 
       // If failed, try to recognize a list of values.
       if (!allow_formula || is_error) {
         char *const item = new char[16384], sep = 0;
         const char *nexpression = expression;
-        unsigned long nb = 0;
-        const unsigned long siz = size();
+        ulongT nb = 0;
+        const ulongT siz = size();
         T *ptrd = _data;
         for (double val = 0; *nexpression && nb<siz; ++nb) {
           sep = 0;
@@ -18971,8 +23268,8 @@ namespace cimg_library_suffixed {
         if (nb<siz && (sep || *nexpression)) {
           if (is_error) throw CImgArgumentException("%s",is_error._data);
           else throw CImgArgumentException(_cimg_instance
-                                           "fill(): Invalid sequence of filling values '%s'.",
-                                           cimg_instance,expression);
+                                           "%s(): Invalid sequence of filling values '%s'.",
+                                           cimg_instance,calling_function,expression);
         }
         if (repeat_values && nb && nb<siz)
           for (T *ptrs = _data, *const ptre = _data + siz; ptrd<ptre; ++ptrs) *(ptrd++) = *ptrs;
@@ -18982,8 +23279,9 @@ namespace cimg_library_suffixed {
     }
 
     //! Fill sequentially pixel values according to a given expression \newinstance.
-    CImg<T> get_fill(const char *const expression, const bool repeat_values, const bool allow_formula=true) const {
-      return (+*this).fill(expression,repeat_values,allow_formula);
+    CImg<T> get_fill(const char *const expression, const bool repeat_values, const bool allow_formula=true,
+                     const CImgList<T> *const list_inputs=0, CImgList<T> *const list_outputs=0) const {
+      return (+*this).fill(expression,repeat_values,allow_formula,list_inputs,list_outputs);
     }
 
     //! Fill sequentially pixel values according to the values found in another image.
@@ -19019,7 +23317,7 @@ namespace cimg_library_suffixed {
     CImg<T>& fillX(const unsigned int y, const unsigned int z, const unsigned int c, const int a0, ...) {
 #define _cimg_fill1(x,y,z,c,off,siz,t) { \
     va_list ap; va_start(ap,a0); T *ptrd = data(x,y,z,c); *ptrd = (T)a0; \
-    for (unsigned long k = 1; k<siz; ++k) { ptrd+=off; *ptrd = (T)va_arg(ap,t); } \
+    for (unsigned int k = 1; k<siz; ++k) { ptrd+=off; *ptrd = (T)va_arg(ap,t); } \
     va_end(ap); }
       if (y<_height && z<_depth && c<_spectrum) _cimg_fill1(0,y,z,c,1,_width,int);
       return *this;
@@ -19057,14 +23355,14 @@ namespace cimg_library_suffixed {
        \param a0 First fill value.
     **/
     CImg<T>& fillZ(const unsigned int x, const unsigned int y, const unsigned int c, const int a0, ...) {
-      const unsigned long wh = (unsigned long)_width*_height;
+      const ulongT wh = (ulongT)_width*_height;
       if (x<_width && y<_height && c<_spectrum) _cimg_fill1(x,y,0,c,wh,_depth,int);
       return *this;
     }
 
     //! Fill pixel values along the Z-axis at a specified pixel position \overloading.
     CImg<T>& fillZ(const unsigned int x, const unsigned int y, const unsigned int c, const double a0, ...) {
-      const unsigned long wh = (unsigned long)_width*_height;
+      const ulongT wh = (ulongT)_width*_height;
       if (x<_width && y<_height && c<_spectrum) _cimg_fill1(x,y,0,c,wh,_depth,double);
       return *this;
     }
@@ -19077,14 +23375,14 @@ namespace cimg_library_suffixed {
        \param a0 First filling value.
     **/
     CImg<T>& fillC(const unsigned int x, const unsigned int y, const unsigned int z, const int a0, ...) {
-      const unsigned long whd = (unsigned long)_width*_height*_depth;
+      const ulongT whd = (ulongT)_width*_height*_depth;
       if (x<_width && y<_height && z<_depth) _cimg_fill1(x,y,z,0,whd,_spectrum,int);
       return *this;
     }
 
     //! Fill pixel values along the C-axis at a specified pixel position \overloading.
     CImg<T>& fillC(const unsigned int x, const unsigned int y, const unsigned int z, const double a0, ...) {
-      const unsigned long whd = (unsigned long)_width*_height*_depth;
+      const ulongT whd = (ulongT)_width*_height*_depth;
       if (x<_width && y<_height && z<_depth) _cimg_fill1(x,y,z,0,whd,_spectrum,double);
       return *this;
     }
@@ -19108,9 +23406,9 @@ namespace cimg_library_suffixed {
       CImg<T> res;
       if (!values) return +*this;
       if (is_empty()) return res;
-      const unsigned long vsiz = values.size();
+      const ulongT vsiz = values.size();
       const char _axis = cimg::uncase(axis);
-      unsigned long j = 0;
+      ulongT j = 0;
       unsigned int k = 0;
       int i0 = 0;
       res.assign(width(),height(),depth(),spectrum());
@@ -19168,8 +23466,8 @@ namespace cimg_library_suffixed {
             k+=i - i0 + 1; i0 = (int)i + 1; j = 0;
           } else { ++j; if (j>=vsiz) { j = 0; i0 = (int)i + 1; }}
         }
-        const unsigned long siz = size();
-        if ((unsigned long)i0<siz) { std::memcpy(res._data + k,_data + i0,(siz - i0)*sizeof(T)); k+=siz - i0; }
+        const ulongT siz = size();
+        if ((ulongT)i0<siz) { std::memcpy(res._data + k,_data + i0,(siz - i0)*sizeof(T)); k+=siz - i0; }
         res.resize(1,k,1,1,0);
       }
       }
@@ -19235,9 +23533,9 @@ namespace cimg_library_suffixed {
 
     //! Fill image with random values in specified range.
     /**
-       \param val_min Minimal random value.
-       \param val_max Maximal random value.
-       \note Random samples are following a uniform distribution.
+       \param val_min Minimal authorized random value.
+       \param val_max Maximal authorized random value.
+       \note Random variables are uniformely distributed in [val_min,val_max].
      **/
     CImg<T>& rand(const T& val_min, const T& val_max) {
       const float delta = (float)val_max - (float)val_min + (cimg::type<T>::is_float()?0:1);
@@ -19262,7 +23560,7 @@ namespace cimg_library_suffixed {
     CImg<T>& round(const double y=1, const int rounding_type=0) {
       if (y>0)
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (size()>=8192)
+#pragma omp parallel for cimg_openmp_if(size()>=8192)
 #endif
         cimg_rof(*this,ptrd,T) *ptrd = cimg::round(*ptrd,y,rounding_type);
       return *this;
@@ -19309,7 +23607,7 @@ namespace cimg_library_suffixed {
       } break;
       case 1 : { // Uniform noise
         cimg_rof(*this,ptrd,T) {
-          Tfloat val = (Tfloat)(*ptrd + nsigma*cimg::crand());
+          Tfloat val = (Tfloat)(*ptrd + nsigma*cimg::rand(-1,1));
           if (val>vmax) val = vmax;
           if (val<vmin) val = vmin;
           *ptrd = (T)val;
@@ -19318,7 +23616,7 @@ namespace cimg_library_suffixed {
       case 2 : { // Salt & Pepper noise
         if (nsigma<0) nsigma = -nsigma;
         if (M==m) { m = 0; M = (Tfloat)(cimg::type<T>::is_float()?1:cimg::type<T>::max()); }
-        cimg_rof(*this,ptrd,T) if (cimg::rand()*100<nsigma) *ptrd = (T)(cimg::rand()<0.5?M:m);
+        cimg_rof(*this,ptrd,T) if (cimg::rand(100)<nsigma) *ptrd = (T)(cimg::rand()<0.5?M:m);
       } break;
       case 3 : { // Poisson Noise
         cimg_rof(*this,ptrd,T) *ptrd = (T)cimg::prand(*ptrd);
@@ -19370,7 +23668,7 @@ namespace cimg_library_suffixed {
       if (m==M) return fill(min_value);
       if (m!=a || M!=b)
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (size()>=65536)
+#pragma omp parallel for cimg_openmp_if(size()>=65536)
 #endif
         cimg_rof(*this,ptrd,T) *ptrd = (T)((*ptrd - fm)/(fM - fm)*(b - a) + a);
       return *this;
@@ -19391,7 +23689,7 @@ namespace cimg_library_suffixed {
        \image html ref_normalize.jpg
     **/
     CImg<T>& normalize() {
-      const unsigned long whd = (unsigned long)_width*_height*_depth;
+      const ulongT whd = (ulongT)_width*_height*_depth;
 #ifdef cimg_use_openmp
 #pragma omp parallel for collapse(2) if (_width>=512 && _height*_depth>=16)
 #endif
@@ -19434,7 +23732,7 @@ namespace cimg_library_suffixed {
     CImg<Tfloat> get_norm(const int norm_type=2) const {
       if (is_empty()) return *this;
       if (_spectrum==1 && norm_type) return get_abs();
-      const unsigned long whd = (unsigned long)_width*_height*_depth;
+      const ulongT whd = (ulongT)_width*_height*_depth;
       CImg<Tfloat> res(_width,_height,_depth);
       switch (norm_type) {
       case -1 : { // Linf-norm.
@@ -19442,7 +23740,7 @@ namespace cimg_library_suffixed {
 #pragma omp parallel for collapse(2) if (_width>=512 && _height*_depth>=16)
 #endif
         cimg_forYZ(*this,y,z) {
-          const unsigned long off = (unsigned long)offset(0,y,z);
+          const ulongT off = (ulongT)offset(0,y,z);
           const T *ptrs = _data + off;
           Tfloat *ptrd = res._data + off;
           cimg_forX(*this,x) {
@@ -19458,7 +23756,7 @@ namespace cimg_library_suffixed {
 #pragma omp parallel for collapse(2) if (_width>=512 && _height*_depth>=16)
 #endif
         cimg_forYZ(*this,y,z) {
-          const unsigned long off = (unsigned long)offset(0,y,z);
+          const ulongT off = (ulongT)offset(0,y,z);
           const T *ptrs = _data + off;
           Tfloat *ptrd = res._data + off;
           cimg_forX(*this,x) {
@@ -19474,7 +23772,7 @@ namespace cimg_library_suffixed {
 #pragma omp parallel for collapse(2) if (_width>=512 && _height*_depth>=16)
 #endif
         cimg_forYZ(*this,y,z) {
-          const unsigned long off = (unsigned long)offset(0,y,z);
+          const ulongT off = (ulongT)offset(0,y,z);
           const T *ptrs = _data + off;
           Tfloat *ptrd = res._data + off;
           cimg_forX(*this,x) {
@@ -19490,7 +23788,7 @@ namespace cimg_library_suffixed {
 #pragma omp parallel for collapse(2) if (_width>=512 && _height*_depth>=16)
 #endif
         cimg_forYZ(*this,y,z) {
-          const unsigned long off = (unsigned long)offset(0,y,z);
+          const ulongT off = (ulongT)offset(0,y,z);
           const T *ptrs = _data + off;
           Tfloat *ptrd = res._data + off;
           cimg_forX(*this,x) {
@@ -19506,7 +23804,7 @@ namespace cimg_library_suffixed {
 #pragma omp parallel for collapse(2) if (_width>=512 && _height*_depth>=16)
 #endif
         cimg_forYZ(*this,y,z) {
-          const unsigned long off = (unsigned long)offset(0,y,z);
+          const ulongT off = (ulongT)offset(0,y,z);
           const T *ptrs = _data + off;
           Tfloat *ptrd = res._data + off;
           cimg_forX(*this,x) {
@@ -19536,7 +23834,7 @@ namespace cimg_library_suffixed {
       if (is_empty()) return *this;
       const T a = min_value<max_value?min_value:max_value, b = min_value<max_value?max_value:min_value;
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (size()>=32768)
+#pragma omp parallel for cimg_openmp_if(size()>=32768)
 #endif
       cimg_rof(*this,ptrd,T) *ptrd = (*ptrd<a)?a:((*ptrd>b)?b:*ptrd);
       return *this;
@@ -19569,14 +23867,14 @@ namespace cimg_library_suffixed {
       if (range>0) {
         if (keep_range)
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (size()>=32768)
+#pragma omp parallel for cimg_openmp_if(size()>=32768)
 #endif
           cimg_rof(*this,ptrd,T) {
             const unsigned int val = (unsigned int)((*ptrd-m)*nb_levels/range);
             *ptrd = (T)(m + cimg::min(val,nb_levels - 1)*range/nb_levels);
           } else
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (size()>=32768)
+#pragma omp parallel for cimg_openmp_if(size()>=32768)
 #endif
           cimg_rof(*this,ptrd,T) {
             const unsigned int val = (unsigned int)((*ptrd-m)*nb_levels/range);
@@ -19608,7 +23906,7 @@ namespace cimg_library_suffixed {
       if (strict_threshold) {
         if (soft_threshold)
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (size()>=32768)
+#pragma omp parallel for cimg_openmp_if(size()>=32768)
 #endif
           cimg_rof(*this,ptrd,T) {
             const T v = *ptrd;
@@ -19616,13 +23914,13 @@ namespace cimg_library_suffixed {
           }
         else
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (size()>=65536)
+#pragma omp parallel for cimg_openmp_if(size()>=65536)
 #endif
           cimg_rof(*this,ptrd,T) *ptrd = *ptrd>value?(T)1:(T)0;
       } else {
         if (soft_threshold)
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (size()>=32768)
+#pragma omp parallel for cimg_openmp_if(size()>=32768)
 #endif
           cimg_rof(*this,ptrd,T) {
             const T v = *ptrd;
@@ -19630,7 +23928,7 @@ namespace cimg_library_suffixed {
           }
         else
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (size()>=65536)
+#pragma omp parallel for cimg_openmp_if(size()>=65536)
 #endif
           cimg_rof(*this,ptrd,T) *ptrd = *ptrd>=value?(T)1:(T)0;
       }
@@ -19710,11 +24008,11 @@ namespace cimg_library_suffixed {
         vmin = min_value<max_value?min_value:max_value,
         vmax = min_value<max_value?max_value:min_value;
       CImg<ulongT> hist = get_histogram(nb_levels,vmin,vmax);
-      unsigned long cumul = 0;
+      ulongT cumul = 0;
       cimg_forX(hist,pos) { cumul+=hist[pos]; hist[pos] = cumul; }
       if (!cumul) cumul = 1;
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (size()>=1048576)
+#pragma omp parallel for cimg_openmp_if(size()>=1048576)
 #endif
       cimg_rof(*this,ptrd,T) {
         const int pos = (int)((*ptrd-vmin)*(nb_levels - 1.)/(vmax-vmin));
@@ -19773,9 +24071,9 @@ namespace cimg_library_suffixed {
 
       typedef typename CImg<t>::Tuint tuint;
       if (is_empty()) return CImg<tuint>();
-      const unsigned long
-        whd = (unsigned long)_width*_height*_depth,
-        pwhd = (unsigned long)colormap._width*colormap._height*colormap._depth;
+      const ulongT
+        whd = (ulongT)_width*_height*_depth,
+        pwhd = (ulongT)colormap._width*colormap._height*colormap._depth;
       CImg<tuint> res(_width,_height,_depth,map_indexes?_spectrum:1);
       tuint *ptrd = res._data;
       if (dithering>0) { // Dithered versions.
@@ -19784,7 +24082,7 @@ namespace cimg_library_suffixed {
         if (valm==valM && valm>=0 && valM<=255) { valm = 0; valM = 255; }
         CImg<Tfloat> cache = get_crop(-1,0,0,0,_width,1,0,_spectrum - 1);
         Tfloat *cache_current = cache.data(1,0,0,0), *cache_next = cache.data(1,1,0,0);
-        const unsigned long cwhd = (unsigned long)cache._width*cache._height*cache._depth;
+        const ulongT cwhd = (ulongT)cache._width*cache._height*cache._depth;
         switch (_spectrum) {
         case 1 : { // Optimized for scalars.
           cimg_forYZ(*this,y,z) {
@@ -20045,9 +24343,9 @@ namespace cimg_library_suffixed {
                                     cimg_instance,
                                     colormap._width,colormap._height,colormap._depth,colormap._spectrum,colormap._data);
 
-      const unsigned long
-        whd = (unsigned long)_width*_height*_depth,
-        pwhd = (unsigned long)colormap._width*colormap._height*colormap._depth;
+      const ulongT
+        whd = (ulongT)_width*_height*_depth,
+        pwhd = (ulongT)colormap._width*colormap._height*colormap._depth;
       CImg<t> res(_width,_height,_depth,colormap._spectrum==1?_spectrum:colormap._spectrum);
       switch (colormap._spectrum) {
 
@@ -20056,17 +24354,17 @@ namespace cimg_library_suffixed {
         switch (boundary_conditions) {
         case 2 : // Periodic boundaries.
           cimg_for(res,ptrd,t) {
-            const unsigned long ind = (unsigned long)*(ptrs++);
+            const ulongT ind = (ulongT)*(ptrs++);
             *ptrd = colormap[ind%pwhd];
           } break;
         case 1 : // Neumann boundaries.
           cimg_for(res,ptrd,t) {
-            const long ind = (long)*(ptrs++);
-            *ptrd = colormap[ind<0?0:ind>=(long)pwhd?pwhd - 1:ind];
+            const longT ind = (longT)*(ptrs++);
+            *ptrd = colormap[ind<0?0:ind>=(longT)pwhd?pwhd - 1:ind];
           } break;
         default : // Dirichlet boundaries.
           cimg_for(res,ptrd,t) {
-            const unsigned long ind = (unsigned long)*(ptrs++);
+            const ulongT ind = (ulongT)*(ptrs++);
             *ptrd = ind<pwhd?colormap[ind]:(t)0;
           }
         }
@@ -20078,7 +24376,7 @@ namespace cimg_library_suffixed {
           const t *const ptrp0 = colormap._data, *ptrp1 = ptrp0 + pwhd;
           t *ptrd0 = res._data, *ptrd1 = ptrd0 + whd;
           for (const T *ptrs = _data, *ptrs_end = ptrs + whd; ptrs<ptrs_end; ) {
-            const unsigned long _ind = (unsigned long)*(ptrs++), ind = _ind%pwhd;
+            const ulongT _ind = (ulongT)*(ptrs++), ind = _ind%pwhd;
             *(ptrd0++) = ptrp0[ind]; *(ptrd1++) = ptrp1[ind];
           }
         } break;
@@ -20086,7 +24384,7 @@ namespace cimg_library_suffixed {
           const t *const ptrp0 = colormap._data, *ptrp1 = ptrp0 + pwhd;
           t *ptrd0 = res._data, *ptrd1 = ptrd0 + whd;
           for (const T *ptrs = _data, *ptrs_end = ptrs + whd; ptrs<ptrs_end; ) {
-            const long _ind = (long)*(ptrs++), ind = _ind<0?0:_ind>=(long)pwhd?(long)pwhd - 1:_ind;
+            const longT _ind = (longT)*(ptrs++), ind = _ind<0?0:_ind>=(longT)pwhd?(longT)pwhd - 1:_ind;
             *(ptrd0++) = ptrp0[ind]; *(ptrd1++) = ptrp1[ind];
           }
         } break;
@@ -20094,7 +24392,7 @@ namespace cimg_library_suffixed {
           const t *const ptrp0 = colormap._data, *ptrp1 = ptrp0 + pwhd;
           t *ptrd0 = res._data, *ptrd1 = ptrd0 + whd;
           for (const T *ptrs = _data, *ptrs_end = ptrs + whd; ptrs<ptrs_end; ) {
-            const unsigned long ind = (unsigned long)*(ptrs++);
+            const ulongT ind = (ulongT)*(ptrs++);
             const bool is_in = ind<pwhd;
             *(ptrd0++) = is_in?ptrp0[ind]:(t)0; *(ptrd1++) = is_in?ptrp1[ind]:(t)0;
           }
@@ -20108,7 +24406,7 @@ namespace cimg_library_suffixed {
           const t *const ptrp0 = colormap._data, *ptrp1 = ptrp0 + pwhd, *ptrp2 = ptrp1 + pwhd;
           t *ptrd0 = res._data, *ptrd1 = ptrd0 + whd, *ptrd2 = ptrd1 + whd;
           for (const T *ptrs = _data, *ptrs_end = ptrs + whd; ptrs<ptrs_end; ) {
-            const unsigned long _ind = (unsigned long)*(ptrs++), ind = _ind%pwhd;
+            const ulongT _ind = (ulongT)*(ptrs++), ind = _ind%pwhd;
             *(ptrd0++) = ptrp0[ind]; *(ptrd1++) = ptrp1[ind]; *(ptrd2++) = ptrp2[ind];
           }
         } break;
@@ -20116,7 +24414,7 @@ namespace cimg_library_suffixed {
           const t *const ptrp0 = colormap._data, *ptrp1 = ptrp0 + pwhd, *ptrp2 = ptrp1 + pwhd;
           t *ptrd0 = res._data, *ptrd1 = ptrd0 + whd, *ptrd2 = ptrd1 + whd;
           for (const T *ptrs = _data, *ptrs_end = ptrs + whd; ptrs<ptrs_end; ) {
-            const long _ind = (long)*(ptrs++), ind = _ind<0?0:_ind>=(long)pwhd?(long)pwhd - 1:_ind;
+            const longT _ind = (longT)*(ptrs++), ind = _ind<0?0:_ind>=(longT)pwhd?(longT)pwhd - 1:_ind;
             *(ptrd0++) = ptrp0[ind]; *(ptrd1++) = ptrp1[ind]; *(ptrd2++) = ptrp2[ind];
           }
         } break;
@@ -20124,7 +24422,7 @@ namespace cimg_library_suffixed {
           const t *const ptrp0 = colormap._data, *ptrp1 = ptrp0 + pwhd, *ptrp2 = ptrp1 + pwhd;
           t *ptrd0 = res._data, *ptrd1 = ptrd0 + whd, *ptrd2 = ptrd1 + whd;
           for (const T *ptrs = _data, *ptrs_end = ptrs + whd; ptrs<ptrs_end; ) {
-            const unsigned long ind = (unsigned long)*(ptrs++);
+            const ulongT ind = (ulongT)*(ptrs++);
             const bool is_in = ind<pwhd;
             *(ptrd0++) = is_in?ptrp0[ind]:(t)0; *(ptrd1++) = is_in?ptrp1[ind]:(t)0; *(ptrd2++) = is_in?ptrp2[ind]:(t)0;
           }
@@ -20137,7 +24435,7 @@ namespace cimg_library_suffixed {
         case 2 : { // Periodic boundaries.
           t *ptrd = res._data;
           for (const T *ptrs = _data, *ptrs_end = ptrs + whd; ptrs<ptrs_end; ) {
-            const unsigned long _ind = (unsigned long)*(ptrs++), ind = _ind%pwhd;
+            const ulongT _ind = (ulongT)*(ptrs++), ind = _ind%pwhd;
             const t *ptrp = colormap._data + ind;
             t *_ptrd = ptrd++; cimg_forC(res,c) { *_ptrd = *ptrp; _ptrd+=whd; ptrp+=pwhd; }
           }
@@ -20145,7 +24443,7 @@ namespace cimg_library_suffixed {
         case 1 : { // Neumann boundaries.
           t *ptrd = res._data;
           for (const T *ptrs = _data, *ptrs_end = ptrs + whd; ptrs<ptrs_end; ) {
-            const long _ind = (long)*(ptrs++), ind = _ind<0?0:_ind>=(long)pwhd?(long)pwhd - 1:_ind;
+            const longT _ind = (longT)*(ptrs++), ind = _ind<0?0:_ind>=(longT)pwhd?(longT)pwhd - 1:_ind;
             const t *ptrp = colormap._data + ind;
             t *_ptrd = ptrd++; cimg_forC(res,c) { *_ptrd = *ptrp; _ptrd+=whd; ptrp+=pwhd; }
           }
@@ -20153,7 +24451,7 @@ namespace cimg_library_suffixed {
         default : { // Dirichlet boundaries.
           t *ptrd = res._data;
           for (const T *ptrs = _data, *ptrs_end = ptrs + whd; ptrs<ptrs_end; ) {
-            const unsigned long ind = (unsigned long)*(ptrs++);
+            const ulongT ind = (ulongT)*(ptrs++);
             const bool is_in = ind<pwhd;
             if (is_in) {
               const t *ptrp = colormap._data + ind;
@@ -20185,9 +24483,9 @@ namespace cimg_library_suffixed {
     }
 
     //! Label connected components \newinstance.
-    CImg<unsigned long> get_label(const bool is_high_connectivity=false,
-                                  const Tfloat tolerance=0) const {
-      if (is_empty()) return CImg<unsigned long>();
+    CImg<ulongT> get_label(const bool is_high_connectivity=false,
+                           const Tfloat tolerance=0) const {
+      if (is_empty()) return CImg<ulongT>();
 
       // Create neighborhood tables.
       int dx[13], dy[13], dz[13], nb = 0;
@@ -20226,8 +24524,8 @@ namespace cimg_library_suffixed {
 
     //! Label connected components \newinstance.
     template<typename t>
-    CImg<unsigned long> get_label(const CImg<t>& connectivity_mask,
-                                  const Tfloat tolerance=0) const {
+    CImg<ulongT> get_label(const CImg<t>& connectivity_mask,
+                           const Tfloat tolerance=0) const {
       int nb = 0;
       cimg_for(connectivity_mask,ptr,t) if (*ptr) ++nb;
       CImg<intT> dx(nb,1,1,1,0), dy(nb,1,1,1,0), dz(nb,1,1,1,0);
@@ -20239,15 +24537,15 @@ namespace cimg_library_suffixed {
       return _get_label(nb,dx,dy,dz,tolerance);
     }
 
-    CImg<unsigned long> _get_label(const unsigned int nb, const int
-                                   *const dx, const int *const dy, const int *const dz,
-                                   const Tfloat tolerance) const {
-      CImg<unsigned long> res(_width,_height,_depth,_spectrum);
+    CImg<ulongT> _get_label(const unsigned int nb, const int
+                            *const dx, const int *const dy, const int *const dz,
+                            const Tfloat tolerance) const {
+      CImg<ulongT> res(_width,_height,_depth,_spectrum);
       cimg_forC(*this,c) {
-        CImg<unsigned long> _res = res.get_shared_channel(c);
+        CImg<ulongT> _res = res.get_shared_channel(c);
 
         // Init label numbers.
-        unsigned long *ptr = _res.data();
+        ulongT *ptr = _res.data();
         cimg_foroff(_res,p) *(ptr++) = p;
 
         // For each neighbour-direction, label.
@@ -20261,28 +24559,28 @@ namespace cimg_library_suffixed {
               y1 = _dy<0?height():height() - _dy,
               z0 = _dz<0?-_dz:0,
               z1 = _dz<0?depth():depth() - _dz;
-            const long
-              wh = width()*height(),
-              whd = width()*height()*depth(),
+            const longT
+              wh = (longT)width()*height(),
+              whd = (longT)width()*height()*depth(),
               offset = _dz*wh + _dy*width() + _dx;
-            for (long z = z0, nz = z0 + _dz, pz = z0*wh; z<z1; ++z, ++nz, pz+=wh) {
-              for (long y = y0, ny = y0 + _dy, py = y0*width() + pz; y<y1; ++y, ++ny, py+=width()) {
-                for (long x = x0, nx = x0 + _dx, p = x0 + py; x<x1; ++x, ++nx, ++p) {
+            for (longT z = z0, nz = z0 + _dz, pz = z0*wh; z<z1; ++z, ++nz, pz+=wh) {
+              for (longT y = y0, ny = y0 + _dy, py = y0*width() + pz; y<y1; ++y, ++ny, py+=width()) {
+                for (longT x = x0, nx = x0 + _dx, p = x0 + py; x<x1; ++x, ++nx, ++p) {
                   if ((Tfloat)cimg::abs((*this)(x,y,z,c,wh,whd) - (*this)(nx,ny,nz,c,wh,whd))<=tolerance) {
-                    const long q = p + offset;
-                    unsigned long x, y;
-                    for (x = (unsigned long)(p<q?q:p), y = (unsigned long)(p<q?p:q); x!=y && _res[x]!=x; ) {
+                    const longT q = p + offset;
+                    ulongT x, y;
+                    for (x = (ulongT)(p<q?q:p), y = (ulongT)(p<q?p:q); x!=y && _res[x]!=x; ) {
                       x = _res[x]; if (x<y) cimg::swap(x,y);
                     }
-                    if (x!=y) _res[x] = (unsigned long)y;
-                    for (unsigned long _p = (unsigned long)p; _p!=y; ) {
-                      const unsigned long h = _res[_p];
-                      _res[_p] = (unsigned long)y;
+                    if (x!=y) _res[x] = (ulongT)y;
+                    for (ulongT _p = (ulongT)p; _p!=y; ) {
+                      const ulongT h = _res[_p];
+                      _res[_p] = (ulongT)y;
                       _p = h;
                     }
-                    for (unsigned long _q = (unsigned long)q; _q!=y; ) {
-                      const unsigned long h = _res[_q];
-                      _res[_q] = (unsigned long)y;
+                    for (ulongT _q = (ulongT)q; _q!=y; ) {
+                      const ulongT h = _res[_q];
+                      _res[_q] = (ulongT)y;
                       _q = h;
                     }
                   }
@@ -20293,7 +24591,7 @@ namespace cimg_library_suffixed {
         }
 
         // Resolve equivalences.
-        unsigned long counter = 0;
+        ulongT counter = 0;
         ptr = _res.data();
         cimg_foroff(_res,p) { *ptr = *ptr==p?counter++:_res[*ptr]; ++ptr; }
       }
@@ -20524,7 +24822,7 @@ namespace cimg_library_suffixed {
                                     cimg_instance);
 
       T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2);
-      for (unsigned long N = (unsigned long)_width*_height*_depth; N; --N) {
+      for (ulongT N = (ulongT)_width*_height*_depth; N; --N) {
         const Tfloat
           R = (Tfloat)*p1,
           G = (Tfloat)*p2,
@@ -20564,7 +24862,7 @@ namespace cimg_library_suffixed {
                                     cimg_instance);
 
       T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2);
-      for (unsigned long N = (unsigned long)_width*_height*_depth; N; --N) {
+      for (ulongT N = (ulongT)_width*_height*_depth; N; --N) {
         Tfloat
           H = cimg::mod((Tfloat)*p1,(Tfloat)360),
           S = (Tfloat)*p2,
@@ -20609,7 +24907,7 @@ namespace cimg_library_suffixed {
                                     cimg_instance);
 
       T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2);
-      for (unsigned long N = (unsigned long)_width*_height*_depth; N; --N) {
+      for (ulongT N = (ulongT)_width*_height*_depth; N; --N) {
         const Tfloat
           R = (Tfloat)*p1,
           G = (Tfloat)*p2,
@@ -20651,7 +24949,7 @@ namespace cimg_library_suffixed {
                                     cimg_instance);
 
       T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2);
-      for (unsigned long N = (unsigned long)_width*_height*_depth; N; --N) {
+      for (ulongT N = (ulongT)_width*_height*_depth; N; --N) {
         const Tfloat
           H = cimg::mod((Tfloat)*p1,(Tfloat)360),
           S = (Tfloat)*p2,
@@ -20688,7 +24986,7 @@ namespace cimg_library_suffixed {
                                     cimg_instance);
 
       T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2);
-      for (unsigned long N = (unsigned long)_width*_height*_depth; N; --N) {
+      for (ulongT N = (ulongT)_width*_height*_depth; N; --N) {
         const Tfloat
           R = (Tfloat)*p1,
           G = (Tfloat)*p2,
@@ -20724,7 +25022,7 @@ namespace cimg_library_suffixed {
                                     cimg_instance);
 
       T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2);
-      for (unsigned long N = (unsigned long)_width*_height*_depth; N; --N) {
+      for (ulongT N = (ulongT)_width*_height*_depth; N; --N) {
         Tfloat
           H = cimg::mod((Tfloat)*p1,(Tfloat)360),
           S = (Tfloat)*p2,
@@ -20767,7 +25065,7 @@ namespace cimg_library_suffixed {
                                     cimg_instance);
 
       T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2);
-      for (unsigned long N = (unsigned long)_width*_height*_depth; N; --N) {
+      for (ulongT N = (ulongT)_width*_height*_depth; N; --N) {
         const Tfloat
           R = (Tfloat)*p1,
           G = (Tfloat)*p2,
@@ -20795,7 +25093,7 @@ namespace cimg_library_suffixed {
                                     cimg_instance);
 
       T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2);
-      for (unsigned long N = (unsigned long)_width*_height*_depth; N; --N) {
+      for (ulongT N = (ulongT)_width*_height*_depth; N; --N) {
         const Tfloat
           Y = (Tfloat)*p1 - 16,
           Cb = (Tfloat)*p2 - 128,
@@ -20823,7 +25121,7 @@ namespace cimg_library_suffixed {
                                     cimg_instance);
 
       T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2);
-      for (unsigned long N = (unsigned long)_width*_height*_depth; N; --N) {
+      for (ulongT N = (ulongT)_width*_height*_depth; N; --N) {
         const Tfloat
           R = (Tfloat)*p1/255,
           G = (Tfloat)*p2/255,
@@ -20849,7 +25147,7 @@ namespace cimg_library_suffixed {
                                     cimg_instance);
 
       T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2);
-      for (unsigned long N = (unsigned long)_width*_height*_depth; N; --N) {
+      for (ulongT N = (ulongT)_width*_height*_depth; N; --N) {
         const Tfloat
           Y = (Tfloat)*p1,
           U = (Tfloat)*p2,
@@ -20877,7 +25175,7 @@ namespace cimg_library_suffixed {
                                     cimg_instance);
 
       T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2);
-      for (unsigned long N = (unsigned long)_width*_height*_depth; N; --N) {
+      for (ulongT N = (ulongT)_width*_height*_depth; N; --N) {
         const Tfloat
           R = (Tfloat)*p1,
           G = (Tfloat)*p2,
@@ -20905,7 +25203,7 @@ namespace cimg_library_suffixed {
                                     cimg_instance);
 
       T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2);
-      for (unsigned long N = (unsigned long)_width*_height*_depth; N; --N) {
+      for (ulongT N = (ulongT)_width*_height*_depth; N; --N) {
         const Tfloat
           C = (Tfloat)*p1,
           M = (Tfloat)*p2,
@@ -20940,7 +25238,7 @@ namespace cimg_library_suffixed {
       CImg<Tfloat> res(_width,_height,_depth,4);
       const T *ps1 = data(0,0,0,0), *ps2 = data(0,0,0,1), *ps3 = data(0,0,0,2);
       Tfloat *pd1 = res.data(0,0,0,0), *pd2 = res.data(0,0,0,1), *pd3 = res.data(0,0,0,2), *pd4 = res.data(0,0,0,3);
-      for (unsigned long N = (unsigned long)_width*_height*_depth; N; --N) {
+      for (ulongT N = (ulongT)_width*_height*_depth; N; --N) {
         Tfloat
 	  C = (Tfloat)*(ps1++),
 	  M = (Tfloat)*(ps2++),
@@ -20971,7 +25269,7 @@ namespace cimg_library_suffixed {
       CImg<Tfloat> res(_width,_height,_depth,3);
       const T *ps1 = data(0,0,0,0), *ps2 = data(0,0,0,1), *ps3 = data(0,0,0,2), *ps4 = data(0,0,0,3);
       Tfloat *pd1 = res.data(0,0,0,0), *pd2 = res.data(0,0,0,1), *pd3 = res.data(0,0,0,2);
-      for (unsigned long N = (unsigned long)_width*_height*_depth; N; --N) {
+      for (ulongT N = (ulongT)_width*_height*_depth; N; --N) {
         const Tfloat
 	  C = (Tfloat)*(ps1++),
 	  M = (Tfloat)*(ps2++),
@@ -20999,7 +25297,7 @@ namespace cimg_library_suffixed {
                                     cimg_instance);
 
       T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2);
-      for (unsigned long N = (unsigned long)_width*_height*_depth; N; --N) {
+      for (ulongT N = (ulongT)_width*_height*_depth; N; --N) {
         const Tfloat
           R = (Tfloat)*p1/255,
           G = (Tfloat)*p2/255,
@@ -21024,7 +25322,7 @@ namespace cimg_library_suffixed {
                                     cimg_instance);
 
       T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2);
-      for (unsigned long N = (unsigned long)_width*_height*_depth; N; --N) {
+      for (ulongT N = (ulongT)_width*_height*_depth; N; --N) {
         const Tfloat
           X = (Tfloat)*p1*255,
           Y = (Tfloat)*p2*255,
@@ -21058,7 +25356,7 @@ namespace cimg_library_suffixed {
         Yn = (Tfloat)(0.212671f + 0.715160f + 0.072169f),
         Zn = (Tfloat)(0.019334f + 0.119193f + 0.950227f);
       T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2);
-      for (unsigned long N = (unsigned long)_width*_height*_depth; N; --N) {
+      for (ulongT N = (ulongT)_width*_height*_depth; N; --N) {
         const Tfloat
           X = (Tfloat)*p1,
           Y = (Tfloat)*p2,
@@ -21093,7 +25391,7 @@ namespace cimg_library_suffixed {
         Yn = (Tfloat)(0.212671f + 0.715160f + 0.072169f),
         Zn = (Tfloat)(0.019334f + 0.119193f + 0.950227f);
       T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2);
-      for (unsigned long N = (unsigned long)_width*_height*_depth; N; --N) {
+      for (ulongT N = (ulongT)_width*_height*_depth; N; --N) {
         const Tfloat
           L = (Tfloat)*p1,
           a = (Tfloat)*p2,
@@ -21124,7 +25422,7 @@ namespace cimg_library_suffixed {
                                     cimg_instance);
 
       T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2);
-      for (unsigned long N = (unsigned long)_width*_height*_depth; N; --N) {
+      for (ulongT N = (ulongT)_width*_height*_depth; N; --N) {
         const Tfloat
           X = (Tfloat)*p1,
           Y = (Tfloat)*p2,
@@ -21151,7 +25449,7 @@ namespace cimg_library_suffixed {
                                     cimg_instance);
 
       T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2);
-      for (unsigned long N = (unsigned long)_width*_height*_depth; N; --N) {
+      for (ulongT N = (ulongT)_width*_height*_depth; N; --N) {
         const Tfloat
          px = (Tfloat)*p1,
          py = (Tfloat)*p2,
@@ -21327,7 +25625,7 @@ namespace cimg_library_suffixed {
           cc = (int)(centering_c*((int)sc - spectrum()));
 
         switch (boundary_conditions) {
-        case 2 : { // Periodic borders.
+        case 2 : { // Periodic boundary.
           res.assign(sx,sy,sz,sc);
           const int
             x0 = ((int)xc%width()) - width(),
@@ -21343,7 +25641,7 @@ namespace cimg_library_suffixed {
                 for (int x = x0; x<(int)sx; x+=width())
                   res.draw_image(x,y,z,c,*this);
         } break;
-        case 1 : { // Neumann borders.
+        case 1 : { // Neumann boundary.
           res.assign(sx,sy,sz,sc).draw_image(xc,yc,zc,cc,*this);
           CImg<T> sprite;
           if (xc>0) {  // X-backward
@@ -21381,7 +25679,7 @@ namespace cimg_library_suffixed {
             for (int c = cc + spectrum(); c<(int)sc; ++c) res.draw_image(0,0,0,c,sprite);
           }
         } break;
-        default : // Dirichlet borders.
+        default : // Dirichlet boundary.
           res.assign(sx,sy,sz,sc,0).draw_image(xc,yc,zc,cc,*this);
         }
         break;
@@ -21392,46 +25690,46 @@ namespace cimg_library_suffixed {
       case 1 : {
         res.assign(sx,sy,sz,sc);
         CImg<ulongT> off_x(sx), off_y(sy + 1), off_z(sz + 1), off_c(sc + 1);
-        const unsigned long
-          wh = (unsigned long)_width*_height,
-          whd = (unsigned long)_width*_height*_depth,
-          sxy = (unsigned long)sx*sy,
-          sxyz = (unsigned long)sx*sy*sz;
+        const ulongT
+          wh = (ulongT)_width*_height,
+          whd = (ulongT)_width*_height*_depth,
+          sxy = (ulongT)sx*sy,
+          sxyz = (ulongT)sx*sy*sz;
         if (sx==_width) off_x.fill(1);
         else {
-          unsigned long *poff_x = off_x._data, curr = 0;
+          ulongT *poff_x = off_x._data, curr = 0;
           cimg_forX(res,x) {
-            const unsigned long old = curr;
-            curr = (unsigned long)((x + 1.0)*_width/sx);
+            const ulongT old = curr;
+            curr = (ulongT)((x + 1.0)*_width/sx);
             *(poff_x++) = curr - old;
           }
         }
         if (sy==_height) off_y.fill(_width);
         else {
-          unsigned long *poff_y = off_y._data, curr = 0;
+          ulongT *poff_y = off_y._data, curr = 0;
           cimg_forY(res,y) {
-            const unsigned long old = curr;
-            curr = (unsigned long)((y + 1.0)*_height/sy);
+            const ulongT old = curr;
+            curr = (ulongT)((y + 1.0)*_height/sy);
             *(poff_y++) = _width*(curr - old);
           }
           *poff_y = 0;
         }
         if (sz==_depth) off_z.fill(wh);
         else {
-          unsigned long *poff_z = off_z._data, curr = 0;
+          ulongT *poff_z = off_z._data, curr = 0;
           cimg_forZ(res,z) {
-            const unsigned long old = curr;
-            curr = (unsigned long)((z + 1.0)*_depth/sz);
+            const ulongT old = curr;
+            curr = (ulongT)((z + 1.0)*_depth/sz);
             *(poff_z++) = wh*(curr - old);
           }
           *poff_z = 0;
         }
         if (sc==_spectrum) off_c.fill(whd);
         else {
-          unsigned long *poff_c = off_c._data, curr = 0;
+          ulongT *poff_c = off_c._data, curr = 0;
           cimg_forC(res,c) {
-            const unsigned long old = curr;
-            curr = (unsigned long)((c + 1.0)*_spectrum/sc);
+            const ulongT old = curr;
+            curr = (ulongT)((c + 1.0)*_spectrum/sc);
             *(poff_c++) = whd*(curr - old);
           }
           *poff_c = 0;
@@ -21439,29 +25737,29 @@ namespace cimg_library_suffixed {
 
         T *ptrd = res._data;
         const T* ptrc = _data;
-        const unsigned long *poff_c = off_c._data;
+        const ulongT *poff_c = off_c._data;
         for (unsigned int c = 0; c<sc; ) {
           const T *ptrz = ptrc;
-          const unsigned long *poff_z = off_z._data;
+          const ulongT *poff_z = off_z._data;
           for (unsigned int z = 0; z<sz; ) {
             const T *ptry = ptrz;
-            const unsigned long *poff_y = off_y._data;
+            const ulongT *poff_y = off_y._data;
             for (unsigned int y = 0; y<sy; ) {
               const T *ptrx = ptry;
-              const unsigned long *poff_x = off_x._data;
+              const ulongT *poff_x = off_x._data;
               cimg_forX(res,x) { *(ptrd++) = *ptrx; ptrx+=*(poff_x++); }
               ++y;
-              unsigned long dy = *(poff_y++);
+              ulongT dy = *(poff_y++);
               for ( ; !dy && y<dy; std::memcpy(ptrd,ptrd - sx,sizeof(T)*sx), ++y, ptrd+=sx, dy = *(poff_y++)) {}
               ptry+=dy;
             }
             ++z;
-            unsigned long dz = *(poff_z++);
+            ulongT dz = *(poff_z++);
             for ( ; !dz && z<dz; std::memcpy(ptrd,ptrd-sxy,sizeof(T)*sxy), ++z, ptrd+=sxy, dz = *(poff_z++)) {}
             ptrz+=dz;
           }
           ++c;
-          unsigned long dc = *(poff_c++);
+          ulongT dc = *(poff_c++);
           for ( ; !dc && c<dc; std::memcpy(ptrd,ptrd-sxyz,sizeof(T)*sxyz), ++c, ptrd+=sxyz, dc = *(poff_c++)) {}
           ptrc+=dc;
         }
@@ -22246,11 +26544,10 @@ namespace cimg_library_suffixed {
     //! Resize image to half-size along XY axes, using an optimized filter \newinstance.
     CImg<T> get_resize_halfXY() const {
       if (is_empty()) return *this;
-      const Tfloat mask[9] = { 0.07842776544f, 0.1231940459f, 0.07842776544f,
-                              0.1231940459f,  0.1935127547f, 0.1231940459f,
-                              0.07842776544f, 0.1231940459f, 0.07842776544f };
-      T I[9] = { 0 };
-      CImg<T> res(_width/2,_height/2,_depth,_spectrum);
+      static const Tfloat mask[9] = { 0.07842776544f, 0.1231940459f, 0.07842776544f,
+                                      0.1231940459f,  0.1935127547f, 0.1231940459f,
+                                      0.07842776544f, 0.1231940459f, 0.07842776544f };
+      CImg<T> I(9), res(_width/2,_height/2,_depth,_spectrum);
       T *ptrd = res._data;
       cimg_forZC(*this,z,c) cimg_for3x3(*this,x,y,z,c,I,T)
         if (x%2 && y%2) *(ptrd++) = (T)
@@ -22407,12 +26704,12 @@ namespace cimg_library_suffixed {
             pf+=_width;
             pb-=_width;
           }
-          pf+=(unsigned long)_width*(_height - height2);
-          pb+=(unsigned long)_width*(_height + height2);
+          pf+=(ulongT)_width*(_height - height2);
+          pb+=(ulongT)_width*(_height + height2);
         }
       } break;
       case 'z' : {
-        buf = new T[(unsigned long)_width*_height];
+        buf = new T[(ulongT)_width*_height];
         pf = _data; pb = data(0,0,_depth - 1);
         const unsigned int depth2 = _depth/2;
         cimg_forC(*this,c) {
@@ -22420,23 +26717,23 @@ namespace cimg_library_suffixed {
             std::memcpy(buf,pf,_width*_height*sizeof(T));
             std::memcpy(pf,pb,_width*_height*sizeof(T));
             std::memcpy(pb,buf,_width*_height*sizeof(T));
-            pf+=(unsigned long)_width*_height;
-            pb-=(unsigned long)_width*_height;
+            pf+=(ulongT)_width*_height;
+            pb-=(ulongT)_width*_height;
           }
-          pf+=(unsigned long)_width*_height*(_depth - depth2);
-          pb+=(unsigned long)_width*_height*(_depth + depth2);
+          pf+=(ulongT)_width*_height*(_depth - depth2);
+          pb+=(ulongT)_width*_height*(_depth + depth2);
         }
       } break;
       case 'c' : {
-        buf = new T[(unsigned long)_width*_height*_depth];
+        buf = new T[(ulongT)_width*_height*_depth];
         pf = _data; pb = data(0,0,0,_spectrum - 1);
         const unsigned int _spectrum2 = _spectrum/2;
         for (unsigned int v = 0; v<_spectrum2; ++v) {
           std::memcpy(buf,pf,_width*_height*_depth*sizeof(T));
           std::memcpy(pf,pb,_width*_height*_depth*sizeof(T));
           std::memcpy(pb,buf,_width*_height*_depth*sizeof(T));
-          pf+=(unsigned long)_width*_height*_depth;
-          pb-=(unsigned long)_width*_height*_depth;
+          pf+=(ulongT)_width*_height*_depth;
+          pb-=(ulongT)_width*_height*_depth;
         }
       } break;
       default :
@@ -22569,7 +26866,7 @@ namespace cimg_library_suffixed {
         default : {
           const int ml = cimg::mod(-delta_y,height()), ndelta_y = (ml<=height()/2)?ml:(ml-height());
           if (!ndelta_y) return *this;
-          T *const buf = new T[(unsigned long)_width*cimg::abs(ndelta_y)];
+          T *const buf = new T[(size_t)_width*cimg::abs(ndelta_y)];
           if (ndelta_y>0) cimg_forZC(*this,z,c) {
             std::memcpy(buf,data(0,0,z,c),_width*ndelta_y*sizeof(T));
             std::memmove(data(0,0,z,c),data(0,ndelta_y,z,c),_width*(_height-ndelta_y)*sizeof(T));
@@ -22603,7 +26900,7 @@ namespace cimg_library_suffixed {
               std::memmove(data(0,0,0,c),data(0,0,ndelta_z,c),_width*_height*(_depth-ndelta_z)*sizeof(T));
               T *ptrd = data(0,0,_depth-ndelta_z,c), *ptrs = data(0,0,_depth - 1,c);
               for (int l = 0; l<ndelta_z - 1; ++l) {
-                std::memcpy(ptrd,ptrs,_width*_height*sizeof(T)); ptrd+=(unsigned long)_width*_height;
+                std::memcpy(ptrd,ptrs,_width*_height*sizeof(T)); ptrd+=(ulongT)_width*_height;
               }
             }
           } else {
@@ -22613,7 +26910,7 @@ namespace cimg_library_suffixed {
               std::memmove(data(0,0,ndelta_z,c),data(0,0,0,c),_width*_height*(_depth-ndelta_z)*sizeof(T));
               T *ptrd = data(0,0,1,c), *ptrs = data(0,0,0,c);
               for (int l = 0; l<ndelta_z - 1; ++l) {
-                std::memcpy(ptrd,ptrs,_width*_height*sizeof(T)); ptrd+=(unsigned long)_width*_height;
+                std::memcpy(ptrd,ptrs,_width*_height*sizeof(T)); ptrd+=(ulongT)_width*_height;
               }
             }
           }
@@ -22621,7 +26918,7 @@ namespace cimg_library_suffixed {
         default : {
           const int ml = cimg::mod(-delta_z,depth()), ndelta_z = (ml<=depth()/2)?ml:(ml-depth());
           if (!ndelta_z) return *this;
-          T *const buf = new T[(unsigned long)_width*_height*cimg::abs(ndelta_z)];
+          T *const buf = new T[(size_t)_width*_height*cimg::abs(ndelta_z)];
           if (ndelta_z>0) cimg_forC(*this,c) {
             std::memcpy(buf,data(0,0,0,c),_width*_height*ndelta_z*sizeof(T));
             std::memmove(data(0,0,0,c),data(0,0,ndelta_z,c),_width*_height*(_depth-ndelta_z)*sizeof(T));
@@ -22654,7 +26951,7 @@ namespace cimg_library_suffixed {
             std::memmove(_data,data(0,0,0,ndelta_c),_width*_height*_depth*(_spectrum-ndelta_c)*sizeof(T));
             T *ptrd = data(0,0,0,_spectrum-ndelta_c), *ptrs = data(0,0,0,_spectrum - 1);
             for (int l = 0; l<ndelta_c - 1; ++l) {
-              std::memcpy(ptrd,ptrs,_width*_height*_depth*sizeof(T)); ptrd+=(unsigned long)_width*_height*_depth;
+              std::memcpy(ptrd,ptrs,_width*_height*_depth*sizeof(T)); ptrd+=(ulongT)_width*_height*_depth;
             }
           } else {
             const int ndelta_c = (delta_c>=spectrum())?spectrum() - 1:delta_c;
@@ -22662,14 +26959,14 @@ namespace cimg_library_suffixed {
             std::memmove(data(0,0,0,ndelta_c),_data,_width*_height*_depth*(_spectrum-ndelta_c)*sizeof(T));
             T *ptrd = data(0,0,0,1);
             for (int l = 0; l<ndelta_c - 1; ++l) {
-              std::memcpy(ptrd,_data,_width*_height*_depth*sizeof(T)); ptrd+=(unsigned long)_width*_height*_depth;
+              std::memcpy(ptrd,_data,_width*_height*_depth*sizeof(T)); ptrd+=(ulongT)_width*_height*_depth;
             }
           }
           break;
         default : {
           const int ml = cimg::mod(-delta_c,spectrum()), ndelta_c = (ml<=spectrum()/2)?ml:(ml-spectrum());
           if (!ndelta_c) return *this;
-          T *const buf = new T[(unsigned long)_width*_height*_depth*cimg::abs(ndelta_c)];
+          T *const buf = new T[(size_t)_width*_height*_depth*cimg::abs(ndelta_c)];
           if (ndelta_c>0) {
             std::memcpy(buf,_data,_width*_height*_depth*ndelta_c*sizeof(T));
             std::memmove(_data,data(0,0,0,ndelta_c),_width*_height*_depth*(_spectrum-ndelta_c)*sizeof(T));
@@ -22714,42 +27011,42 @@ namespace cimg_library_suffixed {
       if (!cimg::strncasecmp(permut,"xyzc",4)) return +*this;
       if (!cimg::strncasecmp(permut,"xycz",4)) {
 	res.assign(_width,_height,_spectrum,_depth);
-        const unsigned long wh = (unsigned long)res._width*res._height, whd = wh*res._depth;
+        const ulongT wh = (ulongT)res._width*res._height, whd = wh*res._depth;
 	cimg_forXYZC(*this,x,y,z,c) res(x,y,c,z,wh,whd) = (t)*(ptrs++);
       }
       if (!cimg::strncasecmp(permut,"xzyc",4)) {
 	res.assign(_width,_depth,_height,_spectrum);
-        const unsigned long wh = (unsigned long)res._width*res._height, whd = wh*res._depth;
+        const ulongT wh = (ulongT)res._width*res._height, whd = wh*res._depth;
 	cimg_forXYZC(*this,x,y,z,c) res(x,z,y,c,wh,whd) = (t)*(ptrs++);
       }
       if (!cimg::strncasecmp(permut,"xzcy",4)) {
 	res.assign(_width,_depth,_spectrum,_height);
-        const unsigned long wh = (unsigned long)res._width*res._height, whd = wh*res._depth;
+        const ulongT wh = (ulongT)res._width*res._height, whd = wh*res._depth;
 	cimg_forXYZC(*this,x,y,z,c) res(x,z,c,y,wh,whd) = (t)*(ptrs++);
       }
       if (!cimg::strncasecmp(permut,"xcyz",4)) {
 	res.assign(_width,_spectrum,_height,_depth);
-        const unsigned long wh = (unsigned long)res._width*res._height, whd = wh*res._depth;
+        const ulongT wh = (ulongT)res._width*res._height, whd = wh*res._depth;
 	cimg_forXYZC(*this,x,y,z,c) res(x,c,y,z,wh,whd) = (t)*(ptrs++);
       }
       if (!cimg::strncasecmp(permut,"xczy",4)) {
 	res.assign(_width,_spectrum,_depth,_height);
-        const unsigned long wh = (unsigned long)res._width*res._height, whd = wh*res._depth;
+        const ulongT wh = (ulongT)res._width*res._height, whd = wh*res._depth;
 	cimg_forXYZC(*this,x,y,z,c) res(x,c,z,y,wh,whd) = (t)*(ptrs++);
       }
       if (!cimg::strncasecmp(permut,"yxzc",4)) {
 	res.assign(_height,_width,_depth,_spectrum);
-        const unsigned long wh = (unsigned long)res._width*res._height, whd = wh*res._depth;
+        const ulongT wh = (ulongT)res._width*res._height, whd = wh*res._depth;
 	cimg_forXYZC(*this,x,y,z,c) res(y,x,z,c,wh,whd) = (t)*(ptrs++);
       }
       if (!cimg::strncasecmp(permut,"yxcz",4)) {
 	res.assign(_height,_width,_spectrum,_depth);
-        const unsigned long wh = (unsigned long)res._width*res._height, whd = wh*res._depth;
+        const ulongT wh = (ulongT)res._width*res._height, whd = wh*res._depth;
 	cimg_forXYZC(*this,x,y,z,c) res(y,x,c,z,wh,whd) = (t)*(ptrs++);
       }
       if (!cimg::strncasecmp(permut,"yzxc",4)) {
 	res.assign(_height,_depth,_width,_spectrum);
-        const unsigned long wh = (unsigned long)res._width*res._height, whd = wh*res._depth;
+        const ulongT wh = (ulongT)res._width*res._height, whd = wh*res._depth;
 	cimg_forXYZC(*this,x,y,z,c) res(y,z,x,c,wh,whd) = (t)*(ptrs++);
       }
       if (!cimg::strncasecmp(permut,"yzcx",4)) {
@@ -22780,7 +27077,7 @@ namespace cimg_library_suffixed {
 	  }
 	} break;
 	default : {
-          const unsigned long wh = (unsigned long)res._width*res._height, whd = wh*res._depth;
+          const ulongT wh = (ulongT)res._width*res._height, whd = wh*res._depth;
 	  cimg_forXYZC(*this,x,y,z,c) res(y,z,c,x,wh,whd) = *(ptrs++);
           return res;
 	}
@@ -22788,42 +27085,42 @@ namespace cimg_library_suffixed {
       }
       if (!cimg::strncasecmp(permut,"ycxz",4)) {
 	res.assign(_height,_spectrum,_width,_depth);
-        const unsigned long wh = (unsigned long)res._width*res._height, whd = wh*res._depth;
+        const ulongT wh = (ulongT)res._width*res._height, whd = wh*res._depth;
 	cimg_forXYZC(*this,x,y,z,c) res(y,c,x,z,wh,whd) = (t)*(ptrs++);
       }
       if (!cimg::strncasecmp(permut,"yczx",4)) {
 	res.assign(_height,_spectrum,_depth,_width);
-        const unsigned long wh = (unsigned long)res._width*res._height, whd = wh*res._depth;
+        const ulongT wh = (ulongT)res._width*res._height, whd = wh*res._depth;
 	cimg_forXYZC(*this,x,y,z,c) res(y,c,z,x,wh,whd) = (t)*(ptrs++);
       }
       if (!cimg::strncasecmp(permut,"zxyc",4)) {
 	res.assign(_depth,_width,_height,_spectrum);
-        const unsigned long wh = (unsigned long)res._width*res._height, whd = wh*res._depth;
+        const ulongT wh = (ulongT)res._width*res._height, whd = wh*res._depth;
 	cimg_forXYZC(*this,x,y,z,c) res(z,x,y,c,wh,whd) = (t)*(ptrs++);
       }
       if (!cimg::strncasecmp(permut,"zxcy",4)) {
 	res.assign(_depth,_width,_spectrum,_height);
-        const unsigned long wh = (unsigned long)res._width*res._height, whd = wh*res._depth;
+        const ulongT wh = (ulongT)res._width*res._height, whd = wh*res._depth;
 	cimg_forXYZC(*this,x,y,z,c) res(z,x,c,y,wh,whd) = (t)*(ptrs++);
       }
       if (!cimg::strncasecmp(permut,"zyxc",4)) {
 	res.assign(_depth,_height,_width,_spectrum);
-        const unsigned long wh = (unsigned long)res._width*res._height, whd = wh*res._depth;
+        const ulongT wh = (ulongT)res._width*res._height, whd = wh*res._depth;
 	cimg_forXYZC(*this,x,y,z,c) res(z,y,x,c,wh,whd) = (t)*(ptrs++);
       }
       if (!cimg::strncasecmp(permut,"zycx",4)) {
 	res.assign(_depth,_height,_spectrum,_width);
-        const unsigned long wh = (unsigned long)res._width*res._height, whd = wh*res._depth;
+        const ulongT wh = (ulongT)res._width*res._height, whd = wh*res._depth;
 	cimg_forXYZC(*this,x,y,z,c) res(z,y,c,x,wh,whd) = (t)*(ptrs++);
       }
       if (!cimg::strncasecmp(permut,"zcxy",4)) {
 	res.assign(_depth,_spectrum,_width,_height);
-        const unsigned long wh = (unsigned long)res._width*res._height, whd = wh*res._depth;
+        const ulongT wh = (ulongT)res._width*res._height, whd = wh*res._depth;
 	cimg_forXYZC(*this,x,y,z,c) res(z,c,x,y,wh,whd) = (t)*(ptrs++);
       }
       if (!cimg::strncasecmp(permut,"zcyx",4)) {
 	res.assign(_depth,_spectrum,_height,_width);
-        const unsigned long wh = (unsigned long)res._width*res._height, whd = wh*res._depth;
+        const ulongT wh = (ulongT)res._width*res._height, whd = wh*res._depth;
 	cimg_forXYZC(*this,x,y,z,c) res(z,c,y,x,wh,whd) = (t)*(ptrs++);
       }
       if (!cimg::strncasecmp(permut,"cxyz",4)) {
@@ -22832,58 +27129,58 @@ namespace cimg_library_suffixed {
 	case 1 : {
 	  const T *ptr_r = data(0,0,0,0);
 	  t *ptrd = res._data;
-	  for (unsigned long siz = (unsigned long)_width*_height*_depth; siz; --siz) *(ptrd++) = (t)*(ptr_r++);
+	  for (ulongT siz = (ulongT)_width*_height*_depth; siz; --siz) *(ptrd++) = (t)*(ptr_r++);
 	} break;
 	case 2 : {
 	  const T *ptr_r = data(0,0,0,0), *ptr_g = data(0,0,0,1);
 	  t *ptrd = res._data;
-	  for (unsigned long siz = (unsigned long)_width*_height*_depth; siz; --siz) {
+	  for (ulongT siz = (ulongT)_width*_height*_depth; siz; --siz) {
 	    *(ptrd++) = (t)*(ptr_r++); *(ptrd++) = (t)*(ptr_g++);
 	  }
 	} break;
 	case 3 : { // Optimization for the classical conversion from planar RGB to interleaved RGB
 	  const T *ptr_r = data(0,0,0,0), *ptr_g = data(0,0,0,1), *ptr_b = data(0,0,0,2);
 	  t *ptrd = res._data;
-	  for (unsigned long siz = (unsigned long)_width*_height*_depth; siz; --siz) {
+	  for (ulongT siz = (ulongT)_width*_height*_depth; siz; --siz) {
 	    *(ptrd++) = (t)*(ptr_r++); *(ptrd++) = (t)*(ptr_g++); *(ptrd++) = (t)*(ptr_b++);
 	  }
 	} break;
 	case 4 : { // Optimization for the classical conversion from planar RGBA to interleaved RGBA
 	  const T *ptr_r = data(0,0,0,0), *ptr_g = data(0,0,0,1), *ptr_b = data(0,0,0,2), *ptr_a = data(0,0,0,3);
 	  t *ptrd = res._data;
-	  for (unsigned long siz = (unsigned long)_width*_height*_depth; siz; --siz) {
+	  for (ulongT siz = (ulongT)_width*_height*_depth; siz; --siz) {
 	    *(ptrd++) = (t)*(ptr_r++); *(ptrd++) = (t)*(ptr_g++); *(ptrd++) = (t)*(ptr_b++); *(ptrd++) = (t)*(ptr_a++);
 	  }
 	} break;
 	default : {
-          const unsigned long wh = (unsigned long)res._width*res._height, whd = wh*res._depth;
+          const ulongT wh = (ulongT)res._width*res._height, whd = wh*res._depth;
 	  cimg_forXYZC(*this,x,y,z,c) res(c,x,y,z,wh,whd) = (t)*(ptrs++);
 	}
 	}
       }
       if (!cimg::strncasecmp(permut,"cxzy",4)) {
 	res.assign(_spectrum,_width,_depth,_height);
-        const unsigned long wh = (unsigned long)res._width*res._height, whd = wh*res._depth;
+        const ulongT wh = (ulongT)res._width*res._height, whd = wh*res._depth;
 	cimg_forXYZC(*this,x,y,z,c) res(c,x,z,y,wh,whd) = (t)*(ptrs++);
       }
       if (!cimg::strncasecmp(permut,"cyxz",4)) {
 	res.assign(_spectrum,_height,_width,_depth);
-        const unsigned long wh = (unsigned long)res._width*res._height, whd = wh*res._depth;
+        const ulongT wh = (ulongT)res._width*res._height, whd = wh*res._depth;
 	cimg_forXYZC(*this,x,y,z,c) res(c,y,x,z,wh,whd) = (t)*(ptrs++);
       }
       if (!cimg::strncasecmp(permut,"cyzx",4)) {
 	res.assign(_spectrum,_height,_depth,_width);
-        const unsigned long wh = (unsigned long)res._width*res._height, whd = wh*res._depth;
+        const ulongT wh = (ulongT)res._width*res._height, whd = wh*res._depth;
 	cimg_forXYZC(*this,x,y,z,c) res(c,y,z,x,wh,whd) = (t)*(ptrs++);
       }
       if (!cimg::strncasecmp(permut,"czxy",4)) {
 	res.assign(_spectrum,_depth,_width,_height);
-        const unsigned long wh = (unsigned long)res._width*res._height, whd = wh*res._depth;
+        const ulongT wh = (ulongT)res._width*res._height, whd = wh*res._depth;
 	cimg_forXYZC(*this,x,y,z,c) res(c,z,x,y,wh,whd) = (t)*(ptrs++);
       }
       if (!cimg::strncasecmp(permut,"czyx",4)) {
 	res.assign(_spectrum,_depth,_height,_width);
-        const unsigned long wh = (unsigned long)res._width*res._height, whd = wh*res._depth;
+        const ulongT wh = (ulongT)res._width*res._height, whd = wh*res._depth;
 	cimg_forXYZC(*this,x,y,z,c) res(c,z,y,x,wh,whd) = (t)*(ptrs++);
       }
       if (!res)
@@ -22899,7 +27196,7 @@ namespace cimg_library_suffixed {
        \param axis Unroll axis (can be \c 'x', \c 'y', \c 'z' or c 'c').
     **/
     CImg<T>& unroll(const char axis) {
-      const unsigned int siz = size();
+      const unsigned int siz = (unsigned int)size();
       if (siz) switch (cimg::uncase(axis)) {
       case 'x' : _width = siz; _height = _depth = _spectrum = 1; break;
       case 'y' : _height = siz; _width = _depth = _spectrum = 1; break;
@@ -22921,18 +27218,20 @@ namespace cimg_library_suffixed {
        \param boundary Boundary conditions. Can be <tt>{  0=dirichlet | 1=neumann | 2=periodic }</tt>.
        \note Most of the time, size of the image is modified.
     **/
-    CImg<T>& rotate(const float angle, const unsigned int interpolation=1, const unsigned int boundary=0) {
+    CImg<T>& rotate(const float angle, const unsigned int interpolation=1,
+                    const unsigned int boundary_conditions=0) {
       const float nangle = cimg::mod(angle,360.0f);
       if (nangle==0.0f) return *this;
-      return get_rotate(angle,interpolation,boundary).move_to(*this);
+      return get_rotate(angle,interpolation,boundary_conditions).move_to(*this);
     }
 
     //! Rotate image with arbitrary angle \newinstance.
-    CImg<T> get_rotate(const float angle, const unsigned int interpolation=1, const unsigned int boundary=0) const {
+    CImg<T> get_rotate(const float angle, const unsigned int interpolation=1,
+                       const unsigned int boundary_conditions=0) const {
       if (is_empty()) return *this;
       CImg<T> res;
       const float nangle = cimg::mod(angle,360.0f);
-      if (boundary!=1 && cimg::mod(nangle,90.0f)==0) { // Optimized version for orthogonal angles.
+      if (boundary_conditions!=1 && cimg::mod(nangle,90.0f)==0) { // Optimized version for orthogonal angles.
         const int wm1 = width() - 1, hm1 = height() - 1;
         const int iangle = (int)nangle/90;
         switch (iangle) {
@@ -22965,7 +27264,7 @@ namespace cimg_library_suffixed {
           w2 = 0.5f*_width, h2 = 0.5f*_height,
           dw2 = 0.5f*(ux + vx), dh2 = 0.5f*(uy + vy);
         res.assign((int)(ux + vx),(int)(uy + vy),_depth,_spectrum);
-        switch (boundary) {
+        switch (boundary_conditions) {
         case 0 : { // Dirichlet boundaries.
           switch (interpolation) {
           case 2 : { // Cubic interpolation.
@@ -23055,7 +27354,7 @@ namespace cimg_library_suffixed {
                                       "rotate(): Invalid specified border conditions %d "
                                       "(should be { 0=dirichlet | 1=neumann | 2=periodic }).",
 				      cimg_instance,
-                                      boundary);
+                                      boundary_conditions);
         }
       }
       return res;
@@ -23071,13 +27370,13 @@ namespace cimg_library_suffixed {
        \param interpolation_type Type of interpolation. Can be <tt>{ 0=nearest | 1=linear | 2=cubic }</tt>.
     **/
     CImg<T>& rotate(const float angle, const float cx, const float cy, const float zoom,
-                    const unsigned int interpolation=1, const unsigned int boundary=3) {
-      return get_rotate(angle,cx,cy,zoom,interpolation,boundary).move_to(*this);
+                    const unsigned int interpolation=1, const unsigned int boundary_conditions=0) {
+      return get_rotate(angle,cx,cy,zoom,interpolation,boundary_conditions).move_to(*this);
     }
 
     //! Rotate image with arbitrary angle, around a center point \newinstance.
     CImg<T> get_rotate(const float angle, const float cx, const float cy, const float zoom,
-                       const unsigned int interpolation=1, const unsigned int boundary=3) const {
+                       const unsigned int interpolation=1, const unsigned int boundary_conditions=0) const {
       if (interpolation>2)
         throw CImgArgumentException(_cimg_instance
                                     "rotate(): Invalid specified interpolation type %d "
@@ -23091,7 +27390,7 @@ namespace cimg_library_suffixed {
         rad = (float)((angle*cimg::PI)/180.0),
         ca = (float)std::cos(rad)/zoom,
         sa = (float)std::sin(rad)/zoom;
-      switch (boundary) {
+      switch (boundary_conditions) {
       case 0 : {
         switch (interpolation) {
         case 2 : {
@@ -23181,7 +27480,7 @@ namespace cimg_library_suffixed {
                                     "rotate(): Invalid specified border conditions %d "
                                     "(should be { 0=dirichlet | 1=neumann | 2=periodic }).",
                                     cimg_instance,
-                                    boundary);
+                                    boundary_conditions);
       }
       return res;
     }
@@ -23319,7 +27618,7 @@ namespace cimg_library_suffixed {
                 cimg_forX(res,x) *(ptrd++) = atX(x - (int)*(ptrs0++),y,z,c,0);
               }
           }
-        } else { // Absolute warp.
+        } else { // Backward-absolute warp.
           if (interpolation==2) { // Cubic interpolation.
             if (boundary_conditions==2) // Periodic boundaries.
 #ifdef cimg_use_openmp
@@ -23497,7 +27796,7 @@ namespace cimg_library_suffixed {
                 cimg_forX(res,x) *(ptrd++) = atXY(x - (int)*(ptrs0++),y - (int)*(ptrs1++),z,c,0);
               }
           }
-        } else { // Absolute warp.
+        } else { // Backward-absolute warp.
           if (interpolation==2) { // Cubic interpolation.
             if (boundary_conditions==2) // Periodic boundaries.
 #ifdef cimg_use_openmp
@@ -23570,7 +27869,7 @@ namespace cimg_library_suffixed {
           }
         }
 
-      } else if (warp._spectrum==3) { // 3d warping.
+      } else { // 3d warping.
         if (mode>=3) { // Forward-relative warp.
           res.fill(0);
           if (interpolation>=1) // Linear interpolation.
@@ -23699,7 +27998,7 @@ namespace cimg_library_suffixed {
                 cimg_forX(res,x) *(ptrd++) = atXYZ(x - (int)*(ptrs0++),y - (int)*(ptrs1++),z - (int)*(ptrs2++),c,0);
               }
           }
-        } else { // Absolute warp.
+        } else { // Backward-absolute warp.
           if (interpolation==2) { // Cubic interpolation.
             if (boundary_conditions==2) // Periodic boundaries.
 #ifdef cimg_use_openmp
@@ -24413,7 +28712,7 @@ namespace cimg_library_suffixed {
       _cimg_math_parser *mp;
       ~_functor4d_streamline_expr() { delete mp; }
       _functor4d_streamline_expr(const char *const expr):mp(0) {
-        mp = new _cimg_math_parser(CImg<T>::empty(),0,expr,"streamline");
+        mp = new _cimg_math_parser(expr,"streamline",CImg<T>::const_empty(),0);
       }
       float operator()(const float x, const float y, const float z, const unsigned int c) const {
         return (float)(*mp)(x,y,z,c);
@@ -24638,7 +28937,7 @@ namespace cimg_library_suffixed {
             res.assign(_width/dp + (_width%dp?1:0),1,1);
             const unsigned int pe = _width - dp;
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (res._width>=128 && _height*_depth*_spectrum>=128)
+#pragma omp parallel for cimg_openmp_if(res._width>=128 && _height*_depth*_spectrum>=128)
 #endif
             for (unsigned int p = 0; p<pe; p+=dp)
               get_crop(p,0,0,0,p + dp - 1,_height - 1,_depth - 1,_spectrum - 1).move_to(res[p/dp]);
@@ -24650,7 +28949,7 @@ namespace cimg_library_suffixed {
             res.assign(_height/dp + (_height%dp?1:0),1,1);
             const unsigned int pe = _height - dp;
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (res._width>=128 && _width*_depth*_spectrum>=128)
+#pragma omp parallel for cimg_openmp_if(res._width>=128 && _width*_depth*_spectrum>=128)
 #endif
             for (unsigned int p = 0; p<pe; p+=dp)
               get_crop(0,p,0,0,_width - 1,p + dp - 1,_depth - 1,_spectrum - 1).move_to(res[p/dp]);
@@ -24662,7 +28961,7 @@ namespace cimg_library_suffixed {
             res.assign(_depth/dp + (_depth%dp?1:0),1,1);
             const unsigned int pe = _depth - dp;
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (res._width>=128 && _width*_height*_spectrum>=128)
+#pragma omp parallel for cimg_openmp_if(res._width>=128 && _width*_height*_spectrum>=128)
 #endif
             for (unsigned int p = 0; p<pe; p+=dp)
               get_crop(0,0,p,0,_width - 1,_height - 1,p + dp - 1,_spectrum - 1).move_to(res[p/dp]);
@@ -24674,7 +28973,7 @@ namespace cimg_library_suffixed {
             res.assign(_spectrum/dp + (_spectrum%dp?1:0),1,1);
             const unsigned int pe = _spectrum - dp;
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (res._width>=128 && _width*_height*_depth>=128)
+#pragma omp parallel for cimg_openmp_if(res._width>=128 && _width*_height*_depth>=128)
 #endif
             for (unsigned int p = 0; p<pe; p+=dp)
               get_crop(0,0,0,p,_width - 1,_height - 1,_depth - 1,p + dp - 1).move_to(res[p/dp]);
@@ -24752,9 +29051,9 @@ namespace cimg_library_suffixed {
           get_channels(i0,spectrum() - 1).move_to(res);
         } break;
         default : {
-          long i0 = 0;
+          longT i0 = 0;
           cimg_foroff(*this,i)
-            if ((*this)[i]!=current) { CImg<T>(_data + i0,1,i - i0).move_to(res); i0 = (long)i; current = (*this)[i]; }
+            if ((*this)[i]!=current) { CImg<T>(_data + i0,1,i - i0).move_to(res); i0 = (longT)i; current = (*this)[i]; }
           CImg<T>(_data + i0,1,size() - i0).move_to(res);
         }
         }
@@ -24772,7 +29071,7 @@ namespace cimg_library_suffixed {
     CImgList<T> get_split(const CImg<t>& values, const char axis=0, const bool keep_values=true) const {
       CImgList<T> res;
       if (is_empty()) return res;
-      const unsigned long vsiz = values.size();
+      const ulongT vsiz = values.size();
       const char _axis = cimg::uncase(axis);
       if (!vsiz) return CImgList<T>(*this);
       if (vsiz==1) { // Split according to a single value.
@@ -24815,8 +29114,8 @@ namespace cimg_library_suffixed {
           } while (i<_spectrum);
         } break;
         default : {
-          const unsigned long siz = size();
-          unsigned long i0 = 0, i = 0;
+          const ulongT siz = size();
+          ulongT i0 = 0, i = 0;
           do {
             while (i<siz && (*this)[i]==value) ++i;
             if (i>i0) { if (keep_values) CImg<T>(_data + i0,1,i - i0).move_to(res); i0 = i; }
@@ -24826,7 +29125,7 @@ namespace cimg_library_suffixed {
         }
         }
       } else { // Split according to multiple values.
-        unsigned long j = 0;
+        ulongT j = 0;
         switch (_axis) {
         case 'x' : {
           unsigned int i0 = 0, i1 = 0, i = 0;
@@ -24893,8 +29192,8 @@ namespace cimg_library_suffixed {
           if (i0<_spectrum) get_channels(i0,spectrum() - 1).move_to(res);
         } break;
         default : {
-          unsigned long i0 = 0, i1 = 0, i = 0;
-          const unsigned long siz = size();
+          ulongT i0 = 0, i1 = 0, i = 0;
+          const ulongT siz = size();
           do {
             if ((*this)[i]==*values) {
               i1 = i; j = 0;
@@ -24982,9 +29281,10 @@ namespace cimg_library_suffixed {
           ((mask._depth==1 && mask._width<=5) || (mask._depth==mask._width && mask._width<=3))) {
         // A special optimization is done for 2x2, 3x3, 4x4, 5x5, 2x2x2 and 3x3x3 mask (with boundary_conditions=1)
         Ttfloat *ptrd = res._data;
+        CImg<T> I;
         switch (mask._depth) {
         case 3 : {
-          T I[27] = { 0 };
+          I.assign(27);
           cimg_forC(res,c) {
             cimg_test_abort();
             const CImg<T> _img = get_shared_channel(c%_spectrum);
@@ -25024,7 +29324,7 @@ namespace cimg_library_suffixed {
           }
         } break;
         case 2 : {
-          T I[8] = { 0 };
+          I.assign(8);
           cimg_forC(res,c) {
             cimg_test_abort();
             const CImg<T> _img = get_shared_channel(c%_spectrum);
@@ -25052,7 +29352,7 @@ namespace cimg_library_suffixed {
         case 1 :
           switch (mask._width) {
           case 6 : {
-            T I[36] = { 0 };
+            I.assign(36);
             cimg_forC(res,c) {
               cimg_test_abort();
               const CImg<T> _img = get_shared_channel(c%_spectrum);
@@ -25092,7 +29392,7 @@ namespace cimg_library_suffixed {
             }
           } break;
           case 5 : {
-            T I[25] = { 0 };
+            I.assign(25);
             cimg_forC(res,c) {
               cimg_test_abort();
               const CImg<T> _img = get_shared_channel(c%_spectrum);
@@ -25124,7 +29424,7 @@ namespace cimg_library_suffixed {
             }
           } break;
           case 4 : {
-            T I[16] = { 0 };
+            I.assign(16);
             cimg_forC(res,c) {
               cimg_test_abort();
               const CImg<T> _img = get_shared_channel(c%_spectrum);
@@ -25150,7 +29450,7 @@ namespace cimg_library_suffixed {
             }
           } break;
           case 3 : {
-            T I[9] = { 0 };
+            I.assign(9);
             cimg_forC(res,c) {
               cimg_test_abort();
               const CImg<T> _img = get_shared_channel(c%_spectrum);
@@ -25172,7 +29472,7 @@ namespace cimg_library_suffixed {
             }
           } break;
           case 2 : {
-            T I[4] = { 0 };
+            I.assign(4);
             cimg_forC(res,c) {
               cimg_test_abort();
               const CImg<T> _img = get_shared_channel(c%_spectrum);
@@ -25201,13 +29501,13 @@ namespace cimg_library_suffixed {
             break;
           }
         }
-      } else { // Generic version for other masks and borders conditions.
+      } else { // Generic version for other masks and boundary conditions.
         const int
           mx2 = mask.width()/2, my2 = mask.height()/2, mz2 = mask.depth()/2,
           mx1 = mx2 - 1 + (mask.width()%2), my1 = my2 - 1 + (mask.height()%2), mz1 = mz2 - 1 + (mask.depth()%2),
           mxe = width() - mx2, mye = height() - my2, mze = depth() - mz2;
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (res._spectrum>=2)
+#pragma omp parallel for cimg_openmp_if(res._spectrum>=2)
 #endif
         cimg_forC(res,c) {
           cimg_test_abort();
@@ -25219,7 +29519,8 @@ namespace cimg_library_suffixed {
 #pragma omp parallel for collapse(3) if (_width*_height*_depth>=32768)
 #endif
             for (int z = mz1; z<mze; ++z)
-              for (int y = my1; y<mye; ++y)
+              for (int y = my1; y<mye; ++y) {
+                cimg_test_abort2();
                 for (int x = mx1; x<mxe; ++x) {
                   Ttfloat val = 0, N = 0;
                   for (int zm = -mz1; zm<=mz2; ++zm)
@@ -25232,11 +29533,13 @@ namespace cimg_library_suffixed {
                   N*=M;
                   res(x,y,z,c) = (Ttfloat)(N?val/std::sqrt(N):0);
                 }
+              }
             if (boundary_conditions)
 #ifdef cimg_use_openmp
 #pragma omp parallel for collapse(2) if (_width>=256 && _height*_depth>=128)
 #endif
-              cimg_forYZ(res,y,z)
+              cimg_forYZ(res,y,z) {
+                cimg_test_abort2();
                 for (int x = 0; x<width();
                      (y<my1 || y>=mye || z<mz1 || z>=mze)?++x:((x<mx1 - 1 || x>=mxe)?++x:(x=mxe))) {
                   Ttfloat val = 0, N = 0;
@@ -25250,11 +29553,13 @@ namespace cimg_library_suffixed {
                   N*=M;
                   res(x,y,z,c) = (Ttfloat)(N?val/std::sqrt(N):0);
                 }
+              }
             else
 #ifdef cimg_use_openmp
 #pragma omp parallel for collapse(2) if (_width>=256 && _height*_depth>=128)
 #endif
-              cimg_forYZ(res,y,z)
+              cimg_forYZ(res,y,z) {
+                cimg_test_abort2();
                 for (int x = 0; x<width();
                      (y<my1 || y>=mye || z<mz1 || z>=mze)?++x:((x<mx1 - 1 || x>=mxe)?++x:(x=mxe))) {
                   Ttfloat val = 0, N = 0;
@@ -25268,12 +29573,14 @@ namespace cimg_library_suffixed {
                   N*=M;
                   res(x,y,z,c) = (Ttfloat)(N?val/std::sqrt(N):0);
                 }
+              }
           } else { // Classical correlation.
 #ifdef cimg_use_openmp
 #pragma omp parallel for collapse(3) if (_width*_height*_depth>=32768)
 #endif
             for (int z = mz1; z<mze; ++z)
-              for (int y = my1; y<mye; ++y)
+              for (int y = my1; y<mye; ++y) {
+                cimg_test_abort2();
                 for (int x = mx1; x<mxe; ++x) {
                   Ttfloat val = 0;
                   for (int zm = -mz1; zm<=mz2; ++zm)
@@ -25282,11 +29589,13 @@ namespace cimg_library_suffixed {
                         val+=_img(x + xm,y + ym,z + zm)*_mask(mx1 + xm,my1 + ym,mz1 + zm);
                   res(x,y,z,c) = (Ttfloat)val;
                 }
+              }
             if (boundary_conditions)
 #ifdef cimg_use_openmp
 #pragma omp parallel for collapse(2) if (_width>=256 && _height*_depth>=128)
 #endif
-              cimg_forYZ(res,y,z)
+              cimg_forYZ(res,y,z) {
+                cimg_test_abort2();
                 for (int x = 0; x<width();
                      (y<my1 || y>=mye || z<mz1 || z>=mze)?++x:((x<mx1 - 1 || x>=mxe)?++x:(x=mxe))) {
                   Ttfloat val = 0;
@@ -25296,11 +29605,13 @@ namespace cimg_library_suffixed {
                         val+=_img._atXYZ(x + xm,y + ym,z + zm)*_mask(mx1 + xm,my1 + ym,mz1 + zm);
                   res(x,y,z,c) = (Ttfloat)val;
                 }
+              }
             else
 #ifdef cimg_use_openmp
 #pragma omp parallel for collapse(2) if (_width>=256 && _height*_depth>=128)
 #endif
-              cimg_forYZ(res,y,z)
+              cimg_forYZ(res,y,z) {
+                cimg_test_abort2();
                 for (int x = 0; x<width();
                      (y<my1 || y>=mye || z<mz1 || z>=mze)?++x:((x<mx1 - 1 || x>=mxe)?++x:(x=mxe))) {
                   Ttfloat val = 0;
@@ -25310,6 +29621,7 @@ namespace cimg_library_suffixed {
                         val+=_img.atXYZ(x + xm,y + ym,z + zm,0,0)*_mask(mx1 + xm,my1 + ym,mz1 + zm);
                   res(x,y,z,c) = (Ttfloat)val;
                 }
+              }
           }
         }
       }
@@ -25348,7 +29660,7 @@ namespace cimg_library_suffixed {
         }
         break;
       case 'y' : {
-        const unsigned long w = (unsigned long)_width;
+        const ulongT w = (ulongT)_width;
 #ifdef cimg_use_openmp
 #pragma omp parallel for collapse(3) if (_height>=512 && _width*_depth*_spectrum>=16)
 #endif
@@ -25359,7 +29671,7 @@ namespace cimg_library_suffixed {
         }
       } break;
       case 'z' : {
-        const unsigned long wh = (unsigned long)_width*_height;
+        const ulongT wh = (ulongT)_width*_height;
 #ifdef cimg_use_openmp
 #pragma omp parallel for collapse(3) if (_depth>=512 && _width*_depth*_spectrum>=16)
 #endif
@@ -25370,7 +29682,7 @@ namespace cimg_library_suffixed {
         }
       } break;
       case 'c' : {
-        const unsigned long whd = (unsigned long)_width*_height*_depth;
+        const ulongT whd = (ulongT)_width*_height*_depth;
 #ifdef cimg_use_openmp
 #pragma omp parallel for collapse(3) if (_spectrum>=512 && _width*_height*_depth>=16)
 #endif
@@ -25442,7 +29754,7 @@ namespace cimg_library_suffixed {
         mx1 = mx2 - 1 + (mask.width()%2), my1 = my2 - 1 + (mask.height()%2), mz1 = mz2 - 1 + (mask.depth()%2),
         mxe = width() - mx2, mye = height() - my2, mze = depth() - mz2;
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (_spectrum>=2)
+#pragma omp parallel for cimg_openmp_if(_spectrum>=2)
 #endif
       cimg_forC(*this,c) {
         cimg_test_abort();
@@ -25453,7 +29765,8 @@ namespace cimg_library_suffixed {
 #pragma omp parallel for collapse(3) if (_width*_height*_depth>=32768)
 #endif
           for (int z = mz1; z<mze; ++z)
-            for (int y = my1; y<mye; ++y)
+            for (int y = my1; y<mye; ++y) {
+              cimg_test_abort2();
               for (int x = mx1; x<mxe; ++x) {
                 Tt min_val = cimg::type<Tt>::max();
                 for (int zm = -mz1; zm<=mz2; ++zm)
@@ -25465,11 +29778,13 @@ namespace cimg_library_suffixed {
                     }
                 res(x,y,z,c) = min_val;
               }
+            }
           if (boundary_conditions)
 #ifdef cimg_use_openmp
 #pragma omp parallel for collapse(2) if (_width>=256 && _height*_depth>=128)
 #endif
-            cimg_forYZ(res,y,z)
+            cimg_forYZ(res,y,z) {
+              cimg_test_abort2();
               for (int x = 0; x<width(); (y<my1 || y>=mye || z<mz1 || z>=mze)?++x:((x<mx1 - 1 || x>=mxe)?++x:(x=mxe))) {
                 Tt min_val = cimg::type<Tt>::max();
                 for (int zm = -mz1; zm<=mz2; ++zm)
@@ -25481,11 +29796,13 @@ namespace cimg_library_suffixed {
                     }
                 res(x,y,z,c) = min_val;
               }
+            }
           else
 #ifdef cimg_use_openmp
 #pragma omp parallel for collapse(2) if (_width>=256 && _height*_depth>=128)
 #endif
-            cimg_forYZ(res,y,z)
+            cimg_forYZ(res,y,z) {
+              cimg_test_abort2();
               for (int x = 0; x<width(); (y<my1 || y>=mye || z<mz1 || z>=mze)?++x:((x<mx1 - 1 || x>=mxe)?++x:(x=mxe))) {
                 Tt min_val = cimg::type<Tt>::max();
                 for (int zm = -mz1; zm<=mz2; ++zm)
@@ -25497,13 +29814,15 @@ namespace cimg_library_suffixed {
                     }
                 res(x,y,z,c) = min_val;
               }
+            }
 
         } else { // Classical erosion.
 #ifdef cimg_use_openmp
 #pragma omp parallel for collapse(3) if (_width*_height*_depth>=32768)
 #endif
           for (int z = mz1; z<mze; ++z)
-            for (int y = my1; y<mye; ++y)
+            for (int y = my1; y<mye; ++y) {
+              cimg_test_abort2();
               for (int x = mx1; x<mxe; ++x) {
                 Tt min_val = cimg::type<Tt>::max();
                 for (int zm = -mz1; zm<=mz2; ++zm)
@@ -25514,11 +29833,13 @@ namespace cimg_library_suffixed {
                     }
                 res(x,y,z,c) = min_val;
               }
+            }
           if (boundary_conditions)
 #ifdef cimg_use_openmp
 #pragma omp parallel for collapse(2) if (_width>=256 && _height*_depth>=128)
 #endif
-            cimg_forYZ(res,y,z)
+            cimg_forYZ(res,y,z) {
+              cimg_test_abort2();
               for (int x = 0; x<width(); (y<my1 || y>=mye || z<mz1 || z>=mze)?++x:((x<mx1 - 1 || x>=mxe)?++x:(x=mxe))) {
                 Tt min_val = cimg::type<Tt>::max();
                 for (int zm = -mz1; zm<=mz2; ++zm)
@@ -25529,11 +29850,13 @@ namespace cimg_library_suffixed {
                     }
                 res(x,y,z,c) = min_val;
               }
+            }
           else
 #ifdef cimg_use_openmp
 #pragma omp parallel for collapse(2) if (_width>=256 && _height*_depth>=128)
 #endif
-            cimg_forYZ(res,y,z)
+            cimg_forYZ(res,y,z) {
+              cimg_test_abort2();
               for (int x = 0; x<width(); (y<my1 || y>=mye || z<mz1 || z>=mze)?++x:((x<mx1 - 1 || x>=mxe)?++x:(x=mxe))) {
                 Tt min_val = cimg::type<Tt>::max();
                 for (int zm = -mz1; zm<=mz2; ++zm)
@@ -25544,6 +29867,7 @@ namespace cimg_library_suffixed {
                     }
                 res(x,y,z,c) = min_val;
               }
+            }
         }
       }
       return res;
@@ -25732,7 +30056,7 @@ namespace cimg_library_suffixed {
         mx1 = mx2 - 1 + (mask.width()%2), my1 = my2 - 1 + (mask.height()%2), mz1 = mz2 - 1 + (mask.depth()%2),
         mxe = width() - mx2, mye = height() - my2, mze = depth() - mz2;
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (_spectrum>=2)
+#pragma omp parallel for cimg_openmp_if(_spectrum>=2)
 #endif
       cimg_forC(*this,c) {
         cimg_test_abort();
@@ -25743,7 +30067,8 @@ namespace cimg_library_suffixed {
 #pragma omp parallel for collapse(3) if (_width*_height*_depth>=32768)
 #endif
           for (int z = mz1; z<mze; ++z)
-            for (int y = my1; y<mye; ++y)
+            for (int y = my1; y<mye; ++y) {
+              cimg_test_abort2();
               for (int x = mx1; x<mxe; ++x) {
                 Tt max_val = cimg::type<Tt>::min();
                 for (int zm = -mz1; zm<=mz2; ++zm)
@@ -25755,11 +30080,13 @@ namespace cimg_library_suffixed {
                     }
                 res(x,y,z,c) = max_val;
               }
+            }
           if (boundary_conditions)
 #ifdef cimg_use_openmp
 #pragma omp parallel for collapse(2) if (_width>=256 && _height*_depth>=128)
 #endif
-            cimg_forYZ(res,y,z)
+            cimg_forYZ(res,y,z) {
+              cimg_test_abort2();
               for (int x = 0; x<width(); (y<my1 || y>=mye || z<mz1 || z>=mze)?++x:((x<mx1 - 1 || x>=mxe)?++x:(x=mxe))) {
                 Tt max_val = cimg::type<Tt>::min();
                 for (int zm = -mz1; zm<=mz2; ++zm)
@@ -25771,11 +30098,13 @@ namespace cimg_library_suffixed {
                     }
                 res(x,y,z,c) = max_val;
               }
+            }
           else
 #ifdef cimg_use_openmp
 #pragma omp parallel for collapse(2) if (_width>=256 && _height*_depth>=128)
 #endif
-            cimg_forYZ(*this,y,z)
+            cimg_forYZ(*this,y,z) {
+              cimg_test_abort2();
               for (int x = 0; x<width(); (y<my1 || y>=mye || z<mz1 || z>=mze)?++x:((x<mx1 - 1 || x>=mxe)?++x:(x=mxe))) {
                 Tt max_val = cimg::type<Tt>::min();
                 for (int zm = -mz1; zm<=mz2; ++zm)
@@ -25787,12 +30116,14 @@ namespace cimg_library_suffixed {
                     }
                 res(x,y,z,c) = max_val;
               }
+            }
         } else { // Classical dilation.
 #ifdef cimg_use_openmp
 #pragma omp parallel for collapse(3) if (_width>=256 && _height*_depth>=128)
 #endif
           for (int z = mz1; z<mze; ++z)
-            for (int y = my1; y<mye; ++y)
+            for (int y = my1; y<mye; ++y) {
+              cimg_test_abort2();
               for (int x = mx1; x<mxe; ++x) {
                 Tt max_val = cimg::type<Tt>::min();
                 for (int zm = -mz1; zm<=mz2; ++zm)
@@ -25803,11 +30134,13 @@ namespace cimg_library_suffixed {
                     }
                 res(x,y,z,c) = max_val;
               }
+            }
           if (boundary_conditions)
 #ifdef cimg_use_openmp
 #pragma omp parallel for collapse(2) if (_width>=256 && _height*_depth>=128)
 #endif
-            cimg_forYZ(res,y,z)
+            cimg_forYZ(res,y,z) {
+              cimg_test_abort2();
               for (int x = 0; x<width(); (y<my1 || y>=mye || z<mz1 || z>=mze)?++x:((x<mx1 - 1 || x>=mxe)?++x:(x=mxe))) {
                 Tt max_val = cimg::type<Tt>::min();
                 for (int zm = -mz1; zm<=mz2; ++zm)
@@ -25818,11 +30151,13 @@ namespace cimg_library_suffixed {
                     }
                 res(x,y,z,c) = max_val;
               }
+            }
           else
 #ifdef cimg_use_openmp
 #pragma omp parallel for collapse(2) if (_width>=256 && _height*_depth>=128)
 #endif
-            cimg_forYZ(res,y,z)
+            cimg_forYZ(res,y,z) {
+              cimg_test_abort2();
               for (int x = 0; x<width(); (y<my1 || y>=mye || z<mz1 || z>=mze)?++x:((x<mx1 - 1 || x>=mxe)?++x:(x=mxe))) {
                 Tt max_val = cimg::type<Tt>::min();
                 for (int zm = -mz1; zm<=mz2; ++zm)
@@ -25833,6 +30168,7 @@ namespace cimg_library_suffixed {
                     }
                 res(x,y,z,c) = max_val;
               }
+            }
         }
       }
       return res;
@@ -26000,12 +30336,25 @@ namespace cimg_library_suffixed {
     //! Compute watershed transform.
     /**
        \param priority Priority map.
-       \param fill_lines Tells if watershed lines must be filled or not.
+       \param is_high_connectivity Boolean that choose between 4(false)- or 8(true)-connectivity
+       in 2d case, and between 6(false)- or 26(true)-connectivity in 3d case.
        \note Non-zero values of the instance instance are propagated to zero-valued ones according to
-         specified the priority map.
+       specified the priority map.
     **/
     template<typename t>
-    CImg<T>& watershed(const CImg<t>& priority, const bool fill_lines=true) {
+    CImg<T>& watershed(const CImg<t>& priority, const bool is_high_connectivity=false) {
+#define _cimg_watershed_init(cond,X,Y,Z) \
+      if (cond && !(*this)(X,Y,Z)) Q._priority_queue_insert(labels,sizeQ,priority(X,Y,Z),X,Y,Z,nb_seeds)
+
+#define _cimg_watershed_propagate(cond,X,Y,Z) \
+      if (cond) { \
+        if ((*this)(X,Y,Z)) { \
+          ns = labels(X,Y,Z) - 1; xs = seeds(ns,0); ys = seeds(ns,1); zs = seeds(ns,2); \
+          d = cimg::sqr((float)x - xs) + cimg::sqr((float)y - ys) + cimg::sqr((float)z - zs); \
+          if (d<dmin) { dmin = d; nmin = ns; label = (*this)(xs,ys,zs); } \
+        } else Q._priority_queue_insert(labels,sizeQ,priority(X,Y,Z),X,Y,Z,n); \
+      }
+
       if (is_empty()) return *this;
       if (!is_sameXYZ(priority))
         throw CImgArgumentException(_cimg_instance
@@ -26015,29 +30364,62 @@ namespace cimg_library_suffixed {
                                     priority._width,priority._height,priority._depth,priority._spectrum,priority._data);
       if (_spectrum!=1) {
         cimg_forC(*this,c)
-          get_shared_channel(c).watershed(priority.get_shared_channel(c%priority._spectrum),fill_lines);
+          get_shared_channel(c).watershed(priority.get_shared_channel(c%priority._spectrum));
         return *this;
       }
 
-      CImg<boolT> is_queued(_width,_height,_depth,1,0);
+      CImg<uintT> labels(_width,_height,_depth,1,0), seeds(64,3);
       CImg<typename cimg::superset2<T,t,int>::type> Q;
       unsigned int sizeQ = 0;
+      int px, nx, py, ny, pz, nz;
+      bool is_px, is_nx, is_py, is_ny, is_pz, is_nz;
+      const bool is_3d = _depth>1;
 
       // Find seed points and insert them in priority queue.
+      unsigned int nb_seeds = 0;
       const T *ptrs = _data;
-      cimg_forXYZ(*this,x,y,z) if (*(ptrs++)) {
-        if (x - 1>=0 && !(*this)(x - 1,y,z))
-          Q._priority_queue_insert(is_queued,sizeQ,priority(x - 1,y,z),x - 1,y,z);
-        if (x + 1<width() && !(*this)(x + 1,y,z))
-          Q._priority_queue_insert(is_queued,sizeQ,priority(x + 1,y,z),x + 1,y,z);
-        if (y - 1>=0 && !(*this)(x,y - 1,z))
-          Q._priority_queue_insert(is_queued,sizeQ,priority(x,y - 1,z),x,y - 1,z);
-        if (y + 1<height() && !(*this)(x,y + 1,z))
-          Q._priority_queue_insert(is_queued,sizeQ,priority(x,y + 1,z),x,y + 1,z);
-        if (z - 1>=0 && !(*this)(x,y,z - 1))
-          Q._priority_queue_insert(is_queued,sizeQ,priority(x,y,z - 1),x,y,z - 1);
-        if (z + 1<depth() && !(*this)(x,y,z + 1))
-          Q._priority_queue_insert(is_queued,sizeQ,priority(x,y,z + 1),x,y,z + 1);
+      cimg_forXYZ(*this,x,y,z) if (*(ptrs++)) { // 3d version
+        if (nb_seeds>=seeds._width) seeds.resize(2*seeds._width,3,1,1,0);
+        seeds(nb_seeds,0) = x; seeds(nb_seeds,1) = y; seeds(nb_seeds++,2) = z;
+        px = x - 1; nx = x + 1;
+        py = y - 1; ny = y + 1;
+        pz = z - 1; nz = z + 1;
+        is_px = px>=0; is_nx = nx<width();
+        is_py = py>=0; is_ny = ny<height();
+        is_pz = pz>=0; is_nz = nz<depth();
+        _cimg_watershed_init(is_px,px,y,z);
+        _cimg_watershed_init(is_nx,nx,y,z);
+        _cimg_watershed_init(is_py,x,py,z);
+        _cimg_watershed_init(is_ny,x,ny,z);
+        if (is_3d) {
+          _cimg_watershed_init(is_pz,x,y,pz);
+          _cimg_watershed_init(is_nz,x,y,nz);
+        }
+        if (is_high_connectivity) {
+          _cimg_watershed_init(is_px && is_py,px,py,z);
+          _cimg_watershed_init(is_nx && is_py,nx,py,z);
+          _cimg_watershed_init(is_px && is_ny,px,ny,z);
+          _cimg_watershed_init(is_nx && is_ny,nx,ny,z);
+          if (is_3d) {
+            _cimg_watershed_init(is_px && is_pz,px,y,pz);
+            _cimg_watershed_init(is_nx && is_pz,nx,y,pz);
+            _cimg_watershed_init(is_px && is_nz,px,y,nz);
+            _cimg_watershed_init(is_nx && is_nz,nx,y,nz);
+            _cimg_watershed_init(is_py && is_pz,x,py,pz);
+            _cimg_watershed_init(is_ny && is_pz,x,ny,pz);
+            _cimg_watershed_init(is_py && is_nz,x,py,nz);
+            _cimg_watershed_init(is_ny && is_nz,x,ny,nz);
+            _cimg_watershed_init(is_px && is_py && is_pz,px,py,pz);
+            _cimg_watershed_init(is_nx && is_py && is_pz,nx,py,pz);
+            _cimg_watershed_init(is_px && is_ny && is_pz,px,ny,pz);
+            _cimg_watershed_init(is_nx && is_ny && is_pz,nx,ny,pz);
+            _cimg_watershed_init(is_px && is_py && is_nz,px,py,nz);
+            _cimg_watershed_init(is_nx && is_py && is_nz,nx,py,nz);
+            _cimg_watershed_init(is_px && is_ny && is_nz,px,ny,nz);
+            _cimg_watershed_init(is_nx && is_ny && is_nz,nx,ny,nz);
+          }
+        }
+        labels(x,y,z) = nb_seeds;
       }
 
       // Start watershed computation.
@@ -26045,145 +30427,113 @@ namespace cimg_library_suffixed {
 
         // Get and remove point with maximal priority from the queue.
         const int x = (int)Q(0,1), y = (int)Q(0,2), z = (int)Q(0,3);
-        Q._priority_queue_remove(sizeQ);
+        const unsigned int n = labels(x,y,z);
+        px = x - 1; nx = x + 1;
+        py = y - 1; ny = y + 1;
+        pz = z - 1; nz = z + 1;
+        is_px = px>=0; is_nx = nx<width();
+        is_py = py>=0; is_ny = ny<height();
+        is_pz = pz>=0; is_nz = nz<depth();
 
         // Check labels of the neighbors.
-        bool is_same_label = true;
-        unsigned int label = 0;
-        if (x - 1>=0) {
-          if ((*this)(x - 1,y,z)) {
-            if (!label) label = (unsigned int)(*this)(x - 1,y,z);
-            else if (label!=(*this)(x - 1,y,z)) is_same_label = false;
-          } else Q._priority_queue_insert(is_queued,sizeQ,priority(x - 1,y,z),x - 1,y,z);
-        }
-        if (x + 1<width()) {
-          if ((*this)(x + 1,y,z)) {
-            if (!label) label = (unsigned int)(*this)(x + 1,y,z);
-            else if (label!=(*this)(x + 1,y,z)) is_same_label = false;
-          } else Q._priority_queue_insert(is_queued,sizeQ,priority(x + 1,y,z),x + 1,y,z);
-        }
-        if (y - 1>=0) {
-          if ((*this)(x,y - 1,z)) {
-            if (!label) label = (unsigned int)(*this)(x,y - 1,z);
-            else if (label!=(*this)(x,y - 1,z)) is_same_label = false;
-          } else Q._priority_queue_insert(is_queued,sizeQ,priority(x,y - 1,z),x,y - 1,z);
-        }
-        if (y + 1<height()) {
-          if ((*this)(x,y + 1,z)) {
-            if (!label) label = (unsigned int)(*this)(x,y + 1,z);
-            else if (label!=(*this)(x,y + 1,z)) is_same_label = false;
-          } else Q._priority_queue_insert(is_queued,sizeQ,priority(x,y + 1,z),x,y + 1,z);
-        }
-        if (z - 1>=0) {
-          if ((*this)(x,y,z - 1)) {
-            if (!label) label = (unsigned int)(*this)(x,y,z - 1);
-            else if (label!=(*this)(x,y,z - 1)) is_same_label = false;
-          } else Q._priority_queue_insert(is_queued,sizeQ,priority(x,y,z - 1),x,y,z - 1);
-        }
-        if (z + 1<depth()) {
-          if ((*this)(x,y,z + 1)) {
-            if (!label) label = (unsigned int)(*this)(x,y,z + 1);
-            else if (label!=(*this)(x,y,z + 1)) is_same_label = false;
-          } else Q._priority_queue_insert(is_queued,sizeQ,priority(x,y,z + 1),x,y,z + 1);
-        }
-        if (is_same_label) (*this)(x,y,z) = (T)label;
-      }
-
-      // Fill lines.
-      if (fill_lines) {
-
-        // Sort all non-labeled pixels with labeled neighbors.
-        is_queued = false;
-        const T *ptrs = _data;
-        cimg_forXYZ(*this,x,y,z) if (!*(ptrs++) &&
-                                     ((x - 1>=0 && (*this)(x - 1,y,z)) || (x + 1<width() && (*this)(x + 1,y,z)) ||
-                                      (y - 1>=0 && (*this)(x,y - 1,z)) || (y + 1<height() && (*this)(x,y + 1,z)) ||
-                                      (z - 1>=0 && (*this)(x,y,z - 1)) || (z + 1>depth() && (*this)(x,y,z + 1))))
-          Q._priority_queue_insert(is_queued,sizeQ,priority(x,y,z),x,y,z);
+        Q._priority_queue_remove(sizeQ);
 
-        // Start line filling process.
-        while (sizeQ) {
-          const int x = (int)Q(0,1), y = (int)Q(0,2), z = (int)Q(0,3);
-          Q._priority_queue_remove(sizeQ);
-          t pmax = cimg::type<t>::min();
-          int xmax = 0, ymax = 0, zmax = 0;
-          if (x - 1>=0) {
-            if ((*this)(x - 1,y,z)) {
-              if (priority(x - 1,y,z)>pmax) { pmax = priority(x - 1,y,z); xmax = x - 1; ymax = y; zmax = z; }
-            } else Q._priority_queue_insert(is_queued,sizeQ,priority(x - 1,y,z),x - 1,y,z);
-          }
-          if (x + 1<width()) {
-            if ((*this)(x + 1,y,z)) {
-              if (priority(x + 1,y,z)>pmax) { pmax = priority(x + 1,y,z); xmax = x + 1; ymax = y; zmax = z; }
-            } else Q._priority_queue_insert(is_queued,sizeQ,priority(x + 1,y,z),x + 1,y,z);
-          }
-          if (y - 1>=0) {
-            if ((*this)(x,y - 1,z)) {
-              if (priority(x,y - 1,z)>pmax) { pmax = priority(x,y - 1,z); xmax = x; ymax = y - 1; zmax = z; }
-            } else Q._priority_queue_insert(is_queued,sizeQ,priority(x,y - 1,z),x,y - 1,z);
-          }
-          if (y + 1<height()) {
-            if ((*this)(x,y + 1,z)) {
-              if (priority(x,y + 1,z)>pmax) { pmax = priority(x,y + 1,z); xmax = x; ymax = y + 1; zmax = z; }
-            } else Q._priority_queue_insert(is_queued,sizeQ,priority(x,y + 1,z),x,y + 1,z);
-          }
-          if (z - 1>=0) {
-            if ((*this)(x,y,z - 1)) {
-              if (priority(x,y,z - 1)>pmax) { pmax = priority(x,y,z - 1); xmax = x; ymax = y; zmax = z - 1; }
-            } else Q._priority_queue_insert(is_queued,sizeQ,priority(x,y,z - 1),x,y,z - 1);
-          }
-          if (z + 1<depth()) {
-            if ((*this)(x,y,z + 1)) {
-              if (priority(x,y,z + 1)>pmax) { pmax = priority(x,y,z + 1); xmax = x; ymax = y; zmax = z + 1; }
-            } else Q._priority_queue_insert(is_queued,sizeQ,priority(x,y,z + 1),x,y,z + 1);
-          }
-          (*this)(x,y,z) = (*this)(xmax,ymax,zmax);
+        unsigned int xs, ys, zs, ns, nmin = 0;
+        float d, dmin = cimg::type<float>::inf();
+        T label = 0;
+        _cimg_watershed_propagate(is_px,px,y,z);
+        _cimg_watershed_propagate(is_nx,nx,y,z);
+        _cimg_watershed_propagate(is_py,x,py,z);
+        _cimg_watershed_propagate(is_ny,x,ny,z);
+        if (is_3d) {
+          _cimg_watershed_propagate(is_pz,x,y,pz);
+          _cimg_watershed_propagate(is_nz,x,y,nz);
         }
+        if (is_high_connectivity) {
+          _cimg_watershed_propagate(is_px && is_py,px,py,z);
+          _cimg_watershed_propagate(is_nx && is_py,nx,py,z);
+          _cimg_watershed_propagate(is_px && is_ny,px,ny,z);
+          _cimg_watershed_propagate(is_nx && is_ny,nx,ny,z);
+          if (is_3d) {
+            _cimg_watershed_propagate(is_px && is_pz,px,y,pz);
+            _cimg_watershed_propagate(is_nx && is_pz,nx,y,pz);
+            _cimg_watershed_propagate(is_px && is_nz,px,y,nz);
+            _cimg_watershed_propagate(is_nx && is_nz,nx,y,nz);
+            _cimg_watershed_propagate(is_py && is_pz,x,py,pz);
+            _cimg_watershed_propagate(is_ny && is_pz,x,ny,pz);
+            _cimg_watershed_propagate(is_py && is_nz,x,py,nz);
+            _cimg_watershed_propagate(is_ny && is_nz,x,ny,nz);
+            _cimg_watershed_propagate(is_px && is_py && is_pz,px,py,pz);
+            _cimg_watershed_propagate(is_nx && is_py && is_pz,nx,py,pz);
+            _cimg_watershed_propagate(is_px && is_ny && is_pz,px,ny,pz);
+            _cimg_watershed_propagate(is_nx && is_ny && is_pz,nx,ny,pz);
+            _cimg_watershed_propagate(is_px && is_py && is_nz,px,py,nz);
+            _cimg_watershed_propagate(is_nx && is_py && is_nz,nx,py,nz);
+            _cimg_watershed_propagate(is_px && is_ny && is_nz,px,ny,nz);
+            _cimg_watershed_propagate(is_nx && is_ny && is_nz,nx,ny,nz);
+          }
+        }
+        (*this)(x,y,z) = label;
+        labels(x,y,z) = ++nmin;
       }
       return *this;
     }
 
     //! Compute watershed transform \newinstance.
     template<typename t>
-    CImg<T> get_watershed(const CImg<t>& priority, const bool fill_lines=true) const {
-      return (+*this).watershed(priority,fill_lines);
+    CImg<T> get_watershed(const CImg<t>& priority, const bool is_high_connectivity=false) const {
+      return (+*this).watershed(priority,is_high_connectivity);
     }
 
     // [internal] Insert/Remove items in priority queue, for watershed/distance transforms.
-    template<typename t>
-    bool _priority_queue_insert(CImg<boolT>& is_queued, unsigned int& siz, const t value,
-                                const unsigned int x, const unsigned int y, const unsigned int z) {
+    template<typename tq, typename tv>
+    bool _priority_queue_insert(CImg<tq>& is_queued, unsigned int& siz, const tv value,
+                                const unsigned int x, const unsigned int y, const unsigned int z,
+                                const unsigned int n=1) {
       if (is_queued(x,y,z)) return false;
-      is_queued(x,y,z) = true;
+      is_queued(x,y,z) = (tq)n;
       if (++siz>=_width) { if (!is_empty()) resize(_width*2,4,1,1,0); else assign(64,4); }
-      (*this)(siz - 1,0) = (T)value; (*this)(siz - 1,1) = (T)x; (*this)(siz - 1,2) = (T)y; (*this)(siz - 1,3) = (T)z;
+      (*this)(siz - 1,0) = (T)value;
+      (*this)(siz - 1,1) = (T)x;
+      (*this)(siz - 1,2) = (T)y;
+      (*this)(siz - 1,3) = (T)z;
       for (unsigned int pos = siz - 1, par = 0; pos && value>(*this)(par=(pos + 1)/2 - 1,0); pos = par) {
-        cimg::swap((*this)(pos,0),(*this)(par,0)); cimg::swap((*this)(pos,1),(*this)(par,1));
-        cimg::swap((*this)(pos,2),(*this)(par,2)); cimg::swap((*this)(pos,3),(*this)(par,3));
+        cimg::swap((*this)(pos,0),(*this)(par,0));
+        cimg::swap((*this)(pos,1),(*this)(par,1));
+        cimg::swap((*this)(pos,2),(*this)(par,2));
+        cimg::swap((*this)(pos,3),(*this)(par,3));
       }
       return true;
     }
 
     CImg<T>& _priority_queue_remove(unsigned int& siz) {
-      (*this)(0,0) = (*this)(--siz,0); (*this)(0,1) = (*this)(siz,1);
-      (*this)(0,2) = (*this)(siz,2); (*this)(0,3) = (*this)(siz,3);
+      (*this)(0,0) = (*this)(--siz,0);
+      (*this)(0,1) = (*this)(siz,1);
+      (*this)(0,2) = (*this)(siz,2);
+      (*this)(0,3) = (*this)(siz,3);
       const float value = (*this)(0,0);
       for (unsigned int pos = 0, left = 0, right = 0;
            ((right=2*(pos + 1),(left=right - 1))<siz && value<(*this)(left,0)) ||
              (right<siz && value<(*this)(right,0));) {
         if (right<siz) {
           if ((*this)(left,0)>(*this)(right,0)) {
-            cimg::swap((*this)(pos,0),(*this)(left,0)); cimg::swap((*this)(pos,1),(*this)(left,1));
-            cimg::swap((*this)(pos,2),(*this)(left,2)); cimg::swap((*this)(pos,3),(*this)(left,3));
+            cimg::swap((*this)(pos,0),(*this)(left,0));
+            cimg::swap((*this)(pos,1),(*this)(left,1));
+            cimg::swap((*this)(pos,2),(*this)(left,2));
+            cimg::swap((*this)(pos,3),(*this)(left,3));
             pos = left;
           } else {
-            cimg::swap((*this)(pos,0),(*this)(right,0)); cimg::swap((*this)(pos,1),(*this)(right,1));
-            cimg::swap((*this)(pos,2),(*this)(right,2)); cimg::swap((*this)(pos,3),(*this)(right,3));
+            cimg::swap((*this)(pos,0),(*this)(right,0));
+            cimg::swap((*this)(pos,1),(*this)(right,1));
+            cimg::swap((*this)(pos,2),(*this)(right,2));
+            cimg::swap((*this)(pos,3),(*this)(right,3));
             pos = right;
           }
         } else {
-          cimg::swap((*this)(pos,0),(*this)(left,0)); cimg::swap((*this)(pos,1),(*this)(left,1));
-          cimg::swap((*this)(pos,2),(*this)(left,2)); cimg::swap((*this)(pos,3),(*this)(left,3));
+          cimg::swap((*this)(pos,0),(*this)(left,0));
+          cimg::swap((*this)(pos,1),(*this)(left,1));
+          cimg::swap((*this)(pos,2),(*this)(left,2));
+          cimg::swap((*this)(pos,3),(*this)(left,3));
           pos = left;
         }
       }
@@ -26265,7 +30615,7 @@ namespace cimg_library_suffixed {
       switch (naxis) {
       case 'x' : {
         const int N = width();
-        const unsigned long off = 1U;
+        const ulongT off = 1U;
 #ifdef cimg_use_openmp
 #pragma omp parallel for collapse(3) if (_width>=256 && _height*_depth*_spectrum>=16)
 #endif
@@ -26273,7 +30623,7 @@ namespace cimg_library_suffixed {
       } break;
       case 'y' : {
         const int N = height();
-        const unsigned long off = (unsigned long)_width;
+        const ulongT off = (ulongT)_width;
 #ifdef cimg_use_openmp
 #pragma omp parallel for collapse(3) if (_width>=256 && _height*_depth*_spectrum>=16)
 #endif
@@ -26281,7 +30631,7 @@ namespace cimg_library_suffixed {
       } break;
       case 'z' : {
         const int N = depth();
-        const unsigned long off = (unsigned long)_width*_height;
+        const ulongT off = (ulongT)_width*_height;
 #ifdef cimg_use_openmp
 #pragma omp parallel for collapse(3) if (_width>=256 && _height*_depth*_spectrum>=16)
 #endif
@@ -26289,7 +30639,7 @@ namespace cimg_library_suffixed {
       } break;
       default : {
         const int N = spectrum();
-        const unsigned long off = (unsigned long)_width*_height*_depth;
+        const ulongT off = (ulongT)_width*_height*_depth;
 #ifdef cimg_use_openmp
 #pragma omp parallel for collapse(3) if (_width>=256 && _height*_depth*_spectrum>=16)
 #endif
@@ -26315,7 +30665,7 @@ namespace cimg_library_suffixed {
        \param boundary_conditions Boundary conditions. Can be <tt>{ 0=dirichlet | 1=neumann }</tt>.
        \note Boundary condition using B. Triggs method (IEEE trans on Sig Proc 2005).
     */
-    static void _cimg_recursive_apply(T *data, const double filter[], const int N, const unsigned long off,
+    static void _cimg_recursive_apply(T *data, const double filter[], const int N, const ulongT off,
 				      const unsigned int order, const bool boundary_conditions) {
       double val[4] = { 0 };  // res[n,n - 1,n - 2,n - 3,..] or res[n,n + 1,n + 2,n + 3,..]
       const double
@@ -26505,14 +30855,14 @@ namespace cimg_library_suffixed {
 #pragma omp parallel for collapse(3) if (_width>=256 && _height*_depth*_spectrum>=16)
 #endif
 	cimg_forXZC(*this,x,z,c)
-	  _cimg_recursive_apply(data(x,0,z,c),filter,_height,(unsigned long)_width,order,boundary_conditions);
+	  _cimg_recursive_apply(data(x,0,z,c),filter,_height,(ulongT)_width,order,boundary_conditions);
       } break;
       case 'z' : {
 #ifdef cimg_use_openmp
 #pragma omp parallel for collapse(3) if (_width>=256 && _height*_depth*_spectrum>=16)
 #endif
 	cimg_forXYC(*this,x,y,c)
-	  _cimg_recursive_apply(data(x,y,0,c),filter,_depth,(unsigned long)(_width*_height),
+	  _cimg_recursive_apply(data(x,y,0,c),filter,_depth,(ulongT)_width*_height,
 				order,boundary_conditions);
       } break;
       default : {
@@ -26520,7 +30870,7 @@ namespace cimg_library_suffixed {
 #pragma omp parallel for collapse(3) if (_width>=256 && _height*_depth*_spectrum>=16)
 #endif
 	cimg_forXYZ(*this,x,y,z)
-	  _cimg_recursive_apply(data(x,y,z,0),filter,_spectrum,(unsigned long)(_width*_height*_depth),
+	  _cimg_recursive_apply(data(x,y,z,0),filter,_spectrum,(ulongT)_width*_height*_depth,
 				order,boundary_conditions);
       }
       }
@@ -26649,7 +30999,7 @@ namespace cimg_library_suffixed {
           if (veloc_max>0) *this+=(velocity*=dl/veloc_max);
         }
       } else { // LIC-based smoothing.
-        const unsigned long whd = (unsigned long)_width*_height*_depth;
+        const ulongT whd = (ulongT)_width*_height*_depth;
         const float sqrt2amplitude = (float)std::sqrt(2*amplitude);
         const int dx1 = width() - 1, dy1 = height() - 1, dz1 = depth() - 1;
         CImg<Tfloat> res(_width,_height,_depth,_spectrum,0), W(_width,_height,_depth,is_3d?4:3), val(_spectrum,1,1,1,0);
@@ -26686,163 +31036,169 @@ namespace cimg_library_suffixed {
 #ifdef cimg_use_openmp
 #pragma omp parallel for collapse(2) if (_width>=256 && _height*_depth>=2) firstprivate(val)
 #endif
-              cimg_forXYZ(*this,x,y,z) {
+              cimg_forYZ(*this,y,z) {
+                cimg_test_abort2();
+                cimg_forX(*this,x) {
+                  val.fill(0);
+                  const float
+                    n = (float)W(x,y,z,3),
+                    fsigma = (float)(n*sqrt2amplitude),
+                    fsigma2 = 2*fsigma*fsigma,
+                    length = gauss_prec*fsigma;
+                  float
+                    S = 0,
+                    X = (float)x,
+                    Y = (float)y,
+                    Z = (float)z;
+                  switch (interpolation_type) {
+                  case 0 : { // Nearest neighbor
+                    for (float l = 0; l<length && X>=0 && X<=dx1 && Y>=0 && Y<=dy1 && Z>=0 && Z<=dz1; l+=dl) {
+                      const int
+                        cx = (int)(X + 0.5f),
+                        cy = (int)(Y + 0.5f),
+                        cz = (int)(Z + 0.5f);
+                      const float
+                        u = (float)W(cx,cy,cz,0),
+                        v = (float)W(cx,cy,cz,1),
+                        w = (float)W(cx,cy,cz,2);
+                      if (is_fast_approx) { cimg_forC(*this,c) val[c]+=(Tfloat)(*this)(cx,cy,cz,c); ++S; }
+                      else {
+                        const float coef = (float)std::exp(-l*l/fsigma2);
+                        cimg_forC(*this,c) val[c]+=(Tfloat)(coef*(*this)(cx,cy,cz,c));
+                        S+=coef;
+                      }
+                      X+=u; Y+=v; Z+=w;
+                    }
+                  } break;
+                  case 1 : { // Linear interpolation
+                    for (float l = 0; l<length && X>=0 && X<=dx1 && Y>=0 && Y<=dy1 && Z>=0 && Z<=dz1; l+=dl) {
+                      const float
+                        u = (float)(W._linear_atXYZ(X,Y,Z,0)),
+                        v = (float)(W._linear_atXYZ(X,Y,Z,1)),
+                        w = (float)(W._linear_atXYZ(X,Y,Z,2));
+                      if (is_fast_approx) { cimg_forC(*this,c) val[c]+=(Tfloat)_linear_atXYZ(X,Y,Z,c); ++S; }
+                      else {
+                        const float coef = (float)std::exp(-l*l/fsigma2);
+                        cimg_forC(*this,c) val[c]+=(Tfloat)(coef*_linear_atXYZ(X,Y,Z,c));
+                        S+=coef;
+                      }
+                      X+=u; Y+=v; Z+=w;
+                    }
+                  } break;
+                  default : { // 2nd order Runge Kutta
+                    for (float l = 0; l<length && X>=0 && X<=dx1 && Y>=0 && Y<=dy1 && Z>=0 && Z<=dz1; l+=dl) {
+                      const float
+                        u0 = (float)(0.5f*W._linear_atXYZ(X,Y,Z,0)),
+                        v0 = (float)(0.5f*W._linear_atXYZ(X,Y,Z,1)),
+                        w0 = (float)(0.5f*W._linear_atXYZ(X,Y,Z,2)),
+                        u = (float)(W._linear_atXYZ(X + u0,Y + v0,Z + w0,0)),
+                        v = (float)(W._linear_atXYZ(X + u0,Y + v0,Z + w0,1)),
+                        w = (float)(W._linear_atXYZ(X + u0,Y + v0,Z + w0,2));
+                      if (is_fast_approx) { cimg_forC(*this,c) val[c]+=(Tfloat)_linear_atXYZ(X,Y,Z,c); ++S; }
+                      else {
+                        const float coef = (float)std::exp(-l*l/fsigma2);
+                        cimg_forC(*this,c) val[c]+=(Tfloat)(coef*_linear_atXYZ(X,Y,Z,c));
+                        S+=coef;
+                      }
+                      X+=u; Y+=v; Z+=w;
+                    }
+                  } break;
+                  }
+                  Tfloat *ptrd = res.data(x,y,z);
+                  if (S>0) cimg_forC(res,c) { *ptrd+=val[c]/S; ptrd+=whd; }
+                  else cimg_forC(res,c) { *ptrd+=(Tfloat)((*this)(x,y,z,c)); ptrd+=whd; }
+                }
+              }
+            }
+          }
+        } else { // 2d LIC algorithm
+          for (float theta = (360%(int)da)/2.0f; theta<360; (theta+=da),++N) {
+            const float thetar = (float)(theta*cimg::PI/180),
+              vx = (float)(std::cos(thetar)), vy = (float)(std::sin(thetar));
+            const t *pa = G.data(0,0,0,0), *pb = G.data(0,0,0,1), *pc = G.data(0,0,0,2);
+            Tfloat *pd0 = W.data(0,0,0,0), *pd1 = W.data(0,0,0,1), *pd2 = W.data(0,0,0,2);
+            cimg_forXY(G,xg,yg) {
+              const t a = *(pa++), b = *(pb++), c = *(pc++);
+              const float
+                u = (float)(a*vx + b*vy),
+                v = (float)(b*vx + c*vy),
+                n = (float)std::sqrt(1e-5 + u*u + v*v),
+                dln = dl/n;
+              *(pd0++) = (Tfloat)(u*dln);
+              *(pd1++) = (Tfloat)(v*dln);
+              *(pd2++) = (Tfloat)n;
+            }
+
+            cimg_test_abort();
+#ifdef cimg_use_openmp
+#pragma omp parallel for cimg_openmp_if(_width>=256 && _height>=2) firstprivate(val)
+#endif
+            cimg_forY(*this,y) {
+              cimg_test_abort2();
+              cimg_forX(*this,x) {
                 val.fill(0);
                 const float
-                  n = (float)W(x,y,z,3),
+                  n = (float)W(x,y,0,2),
                   fsigma = (float)(n*sqrt2amplitude),
                   fsigma2 = 2*fsigma*fsigma,
                   length = gauss_prec*fsigma;
                 float
                   S = 0,
                   X = (float)x,
-                  Y = (float)y,
-                  Z = (float)z;
+                  Y = (float)y;
                 switch (interpolation_type) {
-                case 0 : { // Nearest neighbor
-                  for (float l = 0; l<length && X>=0 && X<=dx1 && Y>=0 && Y<=dy1 && Z>=0 && Z<=dz1; l+=dl) {
+                case 0 : { // Nearest-neighbor
+                  for (float l = 0; l<length && X>=0 && X<=dx1 && Y>=0 && Y<=dy1; l+=dl) {
                     const int
                       cx = (int)(X + 0.5f),
-                      cy = (int)(Y + 0.5f),
-                      cz = (int)(Z + 0.5f);
+                      cy = (int)(Y + 0.5f);
                     const float
-                      u = (float)W(cx,cy,cz,0),
-                      v = (float)W(cx,cy,cz,1),
-                      w = (float)W(cx,cy,cz,2);
-                    if (is_fast_approx) { cimg_forC(*this,c) val[c]+=(Tfloat)(*this)(cx,cy,cz,c); ++S; }
+                      u = (float)W(cx,cy,0,0),
+                      v = (float)W(cx,cy,0,1);
+                    if (is_fast_approx) { cimg_forC(*this,c) val[c]+=(Tfloat)(*this)(cx,cy,0,c); ++S; }
                     else {
                       const float coef = (float)std::exp(-l*l/fsigma2);
-                      cimg_forC(*this,c) val[c]+=(Tfloat)(coef*(*this)(cx,cy,cz,c));
+                      cimg_forC(*this,c) val[c]+=(Tfloat)(coef*(*this)(cx,cy,0,c));
                       S+=coef;
                     }
-                    X+=u; Y+=v; Z+=w;
+                    X+=u; Y+=v;
                   }
                 } break;
                 case 1 : { // Linear interpolation
-                  for (float l = 0; l<length && X>=0 && X<=dx1 && Y>=0 && Y<=dy1 && Z>=0 && Z<=dz1; l+=dl) {
+                  for (float l = 0; l<length && X>=0 && X<=dx1 && Y>=0 && Y<=dy1; l+=dl) {
                     const float
-                      u = (float)(W._linear_atXYZ(X,Y,Z,0)),
-                      v = (float)(W._linear_atXYZ(X,Y,Z,1)),
-                      w = (float)(W._linear_atXYZ(X,Y,Z,2));
-                    if (is_fast_approx) { cimg_forC(*this,c) val[c]+=(Tfloat)_linear_atXYZ(X,Y,Z,c); ++S; }
+                      u = (float)(W._linear_atXY(X,Y,0,0)),
+                      v = (float)(W._linear_atXY(X,Y,0,1));
+                    if (is_fast_approx) { cimg_forC(*this,c) val[c]+=(Tfloat)_linear_atXY(X,Y,0,c); ++S; }
                     else {
                       const float coef = (float)std::exp(-l*l/fsigma2);
-                      cimg_forC(*this,c) val[c]+=(Tfloat)(coef*_linear_atXYZ(X,Y,Z,c));
+                      cimg_forC(*this,c) val[c]+=(Tfloat)(coef*_linear_atXY(X,Y,0,c));
                       S+=coef;
                     }
-                    X+=u; Y+=v; Z+=w;
+                    X+=u; Y+=v;
                   }
                 } break;
-                default : { // 2nd order Runge Kutta
-                  for (float l = 0; l<length && X>=0 && X<=dx1 && Y>=0 && Y<=dy1 && Z>=0 && Z<=dz1; l+=dl) {
+                default : { // 2nd-order Runge-kutta interpolation
+                  for (float l = 0; l<length && X>=0 && X<=dx1 && Y>=0 && Y<=dy1; l+=dl) {
                     const float
-                      u0 = (float)(0.5f*W._linear_atXYZ(X,Y,Z,0)),
-                      v0 = (float)(0.5f*W._linear_atXYZ(X,Y,Z,1)),
-                      w0 = (float)(0.5f*W._linear_atXYZ(X,Y,Z,2)),
-                      u = (float)(W._linear_atXYZ(X + u0,Y + v0,Z + w0,0)),
-                      v = (float)(W._linear_atXYZ(X + u0,Y + v0,Z + w0,1)),
-                      w = (float)(W._linear_atXYZ(X + u0,Y + v0,Z + w0,2));
-                    if (is_fast_approx) { cimg_forC(*this,c) val[c]+=(Tfloat)_linear_atXYZ(X,Y,Z,c); ++S; }
+                      u0 = (float)(0.5f*W._linear_atXY(X,Y,0,0)),
+                      v0 = (float)(0.5f*W._linear_atXY(X,Y,0,1)),
+                      u = (float)(W._linear_atXY(X + u0,Y + v0,0,0)),
+                      v = (float)(W._linear_atXY(X + u0,Y + v0,0,1));
+                    if (is_fast_approx) { cimg_forC(*this,c) val[c]+=(Tfloat)_linear_atXY(X,Y,0,c); ++S; }
                     else {
                       const float coef = (float)std::exp(-l*l/fsigma2);
-                      cimg_forC(*this,c) val[c]+=(Tfloat)(coef*_linear_atXYZ(X,Y,Z,c));
+                      cimg_forC(*this,c) val[c]+=(Tfloat)(coef*_linear_atXY(X,Y,0,c));
                       S+=coef;
                     }
-                    X+=u; Y+=v; Z+=w;
+                    X+=u; Y+=v;
                   }
-                } break;
-                }
-                Tfloat *ptrd = res.data(x,y,z);
-                if (S>0) cimg_forC(res,c) { *ptrd+=val[c]/S; ptrd+=whd; }
-                else cimg_forC(res,c) { *ptrd+=(Tfloat)((*this)(x,y,z,c)); ptrd+=whd; }
-              }
-            }
-          }
-        } else { // 2d LIC algorithm
-          for (float theta = (360%(int)da)/2.0f; theta<360; (theta+=da),++N) {
-            const float thetar = (float)(theta*cimg::PI/180),
-              vx = (float)(std::cos(thetar)), vy = (float)(std::sin(thetar));
-            const t *pa = G.data(0,0,0,0), *pb = G.data(0,0,0,1), *pc = G.data(0,0,0,2);
-            Tfloat *pd0 = W.data(0,0,0,0), *pd1 = W.data(0,0,0,1), *pd2 = W.data(0,0,0,2);
-            cimg_forXY(G,xg,yg) {
-              const t a = *(pa++), b = *(pb++), c = *(pc++);
-              const float
-                u = (float)(a*vx + b*vy),
-                v = (float)(b*vx + c*vy),
-                n = (float)std::sqrt(1e-5 + u*u + v*v),
-                dln = dl/n;
-              *(pd0++) = (Tfloat)(u*dln);
-              *(pd1++) = (Tfloat)(v*dln);
-              *(pd2++) = (Tfloat)n;
-            }
-
-            cimg_test_abort();
-#ifdef cimg_use_openmp
-#pragma omp parallel for if (_width>=256 && _height>=2) firstprivate(val)
-#endif
-            cimg_forXY(*this,x,y) {
-              val.fill(0);
-              const float
-                n = (float)W(x,y,0,2),
-                fsigma = (float)(n*sqrt2amplitude),
-                fsigma2 = 2*fsigma*fsigma,
-                length = gauss_prec*fsigma;
-              float
-                S = 0,
-                X = (float)x,
-                Y = (float)y;
-              switch (interpolation_type) {
-              case 0 : { // Nearest-neighbor
-                for (float l = 0; l<length && X>=0 && X<=dx1 && Y>=0 && Y<=dy1; l+=dl) {
-                  const int
-                    cx = (int)(X + 0.5f),
-                    cy = (int)(Y + 0.5f);
-                  const float
-                    u = (float)W(cx,cy,0,0),
-                    v = (float)W(cx,cy,0,1);
-                  if (is_fast_approx) { cimg_forC(*this,c) val[c]+=(Tfloat)(*this)(cx,cy,0,c); ++S; }
-                  else {
-                    const float coef = (float)std::exp(-l*l/fsigma2);
-                    cimg_forC(*this,c) val[c]+=(Tfloat)(coef*(*this)(cx,cy,0,c));
-                    S+=coef;
-                  }
-                  X+=u; Y+=v;
                 }
-              } break;
-              case 1 : { // Linear interpolation
-                for (float l = 0; l<length && X>=0 && X<=dx1 && Y>=0 && Y<=dy1; l+=dl) {
-                  const float
-                    u = (float)(W._linear_atXY(X,Y,0,0)),
-                    v = (float)(W._linear_atXY(X,Y,0,1));
-                  if (is_fast_approx) { cimg_forC(*this,c) val[c]+=(Tfloat)_linear_atXY(X,Y,0,c); ++S; }
-                  else {
-                    const float coef = (float)std::exp(-l*l/fsigma2);
-                    cimg_forC(*this,c) val[c]+=(Tfloat)(coef*_linear_atXY(X,Y,0,c));
-                    S+=coef;
-                  }
-                  X+=u; Y+=v;
-                }
-              } break;
-              default : { // 2nd-order Runge-kutta interpolation
-                for (float l = 0; l<length && X>=0 && X<=dx1 && Y>=0 && Y<=dy1; l+=dl) {
-                  const float
-                    u0 = (float)(0.5f*W._linear_atXY(X,Y,0,0)),
-                    v0 = (float)(0.5f*W._linear_atXY(X,Y,0,1)),
-                    u = (float)(W._linear_atXY(X + u0,Y + v0,0,0)),
-                    v = (float)(W._linear_atXY(X + u0,Y + v0,0,1));
-                  if (is_fast_approx) { cimg_forC(*this,c) val[c]+=(Tfloat)_linear_atXY(X,Y,0,c); ++S; }
-                  else {
-                    const float coef = (float)std::exp(-l*l/fsigma2);
-                    cimg_forC(*this,c) val[c]+=(Tfloat)(coef*_linear_atXY(X,Y,0,c));
-                    S+=coef;
-                  }
-                  X+=u; Y+=v;
                 }
+                Tfloat *ptrd = res.data(x,y);
+                if (S>0) cimg_forC(res,c) { *ptrd+=val[c]/S; ptrd+=whd; }
+                else cimg_forC(res,c) { *ptrd+=(Tfloat)((*this)(x,y,0,c)); ptrd+=whd; }
               }
-              }
-              Tfloat *ptrd = res.data(x,y);
-              if (S>0) cimg_forC(res,c) { *ptrd+=val[c]/S; ptrd+=whd; }
-              else cimg_forC(res,c) { *ptrd+=(Tfloat)((*this)(x,y,0,c)); ptrd+=whd; }
             }
           }
         }
@@ -27054,18 +31410,18 @@ namespace cimg_library_suffixed {
     /*
       \param ptr the pointer of the data
       \param N size of the data
-      \param sigma sigma of the box filter
+      \param boxsize Size of the box filter (can be subpixel).
       \param off the offset between two data point
       \param order the order of the filter 0 (smoothing), 1st derivtive and 2nd derivative.
       \param boundary_conditions Boundary conditions. Can be <tt>{ 0=dirichlet | 1=neumann }</tt>.
     */
-    static void _cimg_blur_box_apply(T *ptr, const float sigma, const int N, const unsigned long off,
+    static void _cimg_blur_box_apply(T *ptr, const float boxsize, const int N, const ulongT off,
                                      const int order, const bool boundary_conditions) {
       // Smooth.
-      if (sigma>1) {
-        const int w2 = (int)(sigma - 1)/2;
+      if (boxsize>1) {
+        const int w2 = (int)(boxsize - 1)/2;
         const unsigned int winsize = 2*w2 + 1U;
-        const double frac = (sigma - winsize)/2.0;
+        const double frac = (boxsize - winsize)/2.0;
         CImg<Tfloat> win(winsize);
         Tfloat sum = 0; // window sum
         for (int x = -w2; x<=w2; ++x) {
@@ -27078,7 +31434,7 @@ namespace cimg_library_suffixed {
           next = __cimg_blur_box_apply(ptr,N,off,boundary_conditions,w2 + 1);
         for (int x = 0; x < N - 1; ++x) {
           const double sum2 = sum + frac * (prev + next);
-          ptr[x*off] = (T)(sum2/sigma);
+          ptr[x*off] = (T)(sum2/boxsize);
           prev = win[ifirst];
           sum-=prev;
           ifirst = (int)((ifirst + 1)%winsize);
@@ -27088,7 +31444,7 @@ namespace cimg_library_suffixed {
           next = __cimg_blur_box_apply(ptr,N,off,boundary_conditions,x + w2 + 2);
         }
         const double sum2 = sum + frac * (prev + next);
-        ptr[(N - 1)*off] = (T)(sum2/sigma);
+        ptr[(N - 1)*off] = (T)(sum2/boxsize);
       }
 
       // Derive.
@@ -27124,7 +31480,7 @@ namespace cimg_library_suffixed {
       }
     }
 
-    static T __cimg_blur_box_apply(T *ptr, const int N, const unsigned long off,
+    static T __cimg_blur_box_apply(T *ptr, const int N, const ulongT off,
                                    const bool boundary_conditions, const int x) {
       if (x<0) return boundary_conditions?ptr[0]:T();
       if (x>=N) return boundary_conditions?ptr[(N - 1)*off]:T();
@@ -27133,44 +31489,44 @@ namespace cimg_library_suffixed {
 
     // Apply box filter of order 0,1,2.
     /**
-      \param sigma sigma of the box filter
+      \param boxsize Size of the box window (can be subpixel)
       \param order the order of the filter 0,1 or 2.
       \param axis  Axis along which the filter is computed. Can be <tt>{ 'x' | 'y' | 'z' | 'c' }</tt>.
       \param boundary_conditions Boundary conditions. Can be <tt>{ 0=dirichlet | 1=neumann }</tt>.
     **/
-    CImg<T>& boxfilter(const float sigma, const int order, const char axis='x',
+    CImg<T>& boxfilter(const float boxsize, const int order, const char axis='x',
                        const bool boundary_conditions=true) {
-      if (is_empty() || !sigma || (sigma<=1 && !order)) return *this;
+      if (is_empty() || !boxsize || (boxsize<=1 && !order)) return *this;
       const char naxis = cimg::uncase(axis);
-      const float nsigma = sigma>=0?sigma:-sigma*(naxis=='x'?_width:naxis=='y'?_height:naxis=='z'?_depth:_spectrum)/100;
+      const float nboxsize = boxsize>=0?boxsize:-boxsize*(naxis=='x'?_width:naxis=='y'?_height:naxis=='z'?_depth:_spectrum)/100;
       switch (naxis) {
       case 'x' : {
 #ifdef cimg_use_openmp
 #pragma omp parallel for collapse(3) if (_width>=256 && _height*_depth*_spectrum>=16)
 #endif
         cimg_forYZC(*this,y,z,c)
-          _cimg_blur_box_apply(data(0,y,z,c),nsigma,_width,1U,order,boundary_conditions);
+          _cimg_blur_box_apply(data(0,y,z,c),nboxsize,_width,1U,order,boundary_conditions);
       } break;
       case 'y' : {
 #ifdef cimg_use_openmp
 #pragma omp parallel for collapse(3) if (_width>=256 && _height*_depth*_spectrum>=16)
 #endif
         cimg_forXZC(*this,x,z,c)
-          _cimg_blur_box_apply(data(x,0,z,c),nsigma,_height,(unsigned long)_width,order,boundary_conditions);
+          _cimg_blur_box_apply(data(x,0,z,c),nboxsize,_height,(ulongT)_width,order,boundary_conditions);
       } break;
       case 'z' : {
 #ifdef cimg_use_openmp
 #pragma omp parallel for collapse(3) if (_width>=256 && _height*_depth*_spectrum>=16)
 #endif
         cimg_forXYC(*this,x,y,c)
-          _cimg_blur_box_apply(data(x,y,0,c),nsigma,_depth,(unsigned long)(_width*_height),order,boundary_conditions);
+          _cimg_blur_box_apply(data(x,y,0,c),nboxsize,_depth,(ulongT)_width*_height,order,boundary_conditions);
       } break;
       default : {
 #ifdef cimg_use_openmp
 #pragma omp parallel for collapse(3) if (_width>=256 && _height*_depth*_spectrum>=16)
 #endif
         cimg_forXYZ(*this,x,y,z)
-          _cimg_blur_box_apply(data(x,y,z,0),nsigma,_spectrum,(unsigned long)(_width*_height*_depth),
+          _cimg_blur_box_apply(data(x,y,z,0),nboxsize,_spectrum,(ulongT)_width*_height*_depth,
                                order,boundary_conditions);
       }
       }
@@ -27178,50 +31534,50 @@ namespace cimg_library_suffixed {
     }
 
     // Apply box filter of order 0,1 or 2 \newinstance.
-    CImg<Tfloat> get_boxfilter(const float sigma, const int order, const char axis='x',
+    CImg<Tfloat> get_boxfilter(const float boxsize, const int order, const char axis='x',
                                const bool boundary_conditions=true) const {
-      return CImg<Tfloat>(*this,false).boxfilter(sigma,order,axis,boundary_conditions);
+      return CImg<Tfloat>(*this,false).boxfilter(boxsize,order,axis,boundary_conditions);
     }
 
     //! Blur image with a box filter.
     /**
-       \param sigma_x Size of the box window, along the X-axis.
-       \param sigma_y Size of the box window, along the Y-axis.
-       \param sigma_z Size of the box window, along the Z-axis.
+       \param boxsize_x Size of the box window, along the X-axis (can be subpixel).
+       \param boxsize_y Size of the box window, along the Y-axis (can be subpixel).
+       \param boxsize_z Size of the box window, along the Z-axis (can be subpixel).
        \param boundary_conditions Boundary conditions. Can be <tt>{ false=dirichlet | true=neumann }</tt>.
        \note
        - This is a recursive algorithm, not depending on the values of the box kernel size.
        \see blur().
     **/
-    CImg<T>& blur_box(const float sigma_x, const float sigma_y, const float sigma_z,
+    CImg<T>& blur_box(const float boxsize_x, const float boxsize_y, const float boxsize_z,
                       const bool boundary_conditions=true) {
       if (is_empty()) return *this;
-      if (_width>1) boxfilter(sigma_x,0,'x',boundary_conditions);
-      if (_height>1) boxfilter(sigma_y,0,'y',boundary_conditions);
-      if (_depth>1) boxfilter(sigma_z,0,'z',boundary_conditions);
+      if (_width>1) boxfilter(boxsize_x,0,'x',boundary_conditions);
+      if (_height>1) boxfilter(boxsize_y,0,'y',boundary_conditions);
+      if (_depth>1) boxfilter(boxsize_z,0,'z',boundary_conditions);
       return *this;
     }
 
     //! Blur image with a box filter \newinstance.
-    CImg<Tfloat> get_blur_box(const float sigma_x, const float sigma_y, const float sigma_z,
+    CImg<Tfloat> get_blur_box(const float boxsize_x, const float boxsize_y, const float boxsize_z,
                               const bool boundary_conditions=true) const {
-      return CImg<Tfloat>(*this,false).blur_box(sigma_x,sigma_y,sigma_z,boundary_conditions);
+      return CImg<Tfloat>(*this,false).blur_box(boxsize_x,boxsize_y,boxsize_z,boundary_conditions);
     }
 
     //! Blur image with a box filter.
     /**
-       \param sigma Size of the box window.
+       \param boxsize Size of the box window (can be subpixel).
        \param boundary_conditions Boundary conditions. Can be <tt>{ 0=dirichlet | 1=neumann }</tt>.a
        \see deriche(), vanvliet().
     **/
-    CImg<T>& blur_box(const float sigma, const bool boundary_conditions=true) {
-      const float nsigma = sigma>=0?sigma:-sigma*cimg::max(_width,_height,_depth)/100;
-      return blur_box(nsigma,nsigma,nsigma,boundary_conditions);
+    CImg<T>& blur_box(const float boxsize, const bool boundary_conditions=true) {
+      const float nboxsize = boxsize>=0?boxsize:-boxsize*cimg::max(_width,_height,_depth)/100;
+      return blur_box(nboxsize,nboxsize,nboxsize,boundary_conditions);
     }
 
     //! Blur image with a box filter \newinstance.
-    CImg<Tfloat> get_blur_box(const float sigma, const bool boundary_conditions=true) const {
-      return CImg<Tfloat>(*this,false).blur_box(sigma,boundary_conditions);
+    CImg<Tfloat> get_blur_box(const float boxsize, const bool boundary_conditions=true) const {
+      return CImg<Tfloat>(*this,false).blur_box(boxsize,boundary_conditions);
     }
 
     //! Blur image, with the image guided filter.
@@ -27456,7 +31812,7 @@ namespace cimg_library_suffixed {
           const int psize2 = (int)patch_size/2, psize1 = (int)patch_size - psize2 - 1;
           if (is_fast_approx)
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (res._width>=32 && res._height>=4) firstprivate(P,Q)
+#pragma omp parallel for cimg_openmp_if(res._width>=32 && res._height>=4) firstprivate(P,Q)
 #endif
             cimg_forXY(res,x,y) { // 2d fast approximation.
               P = img.get_crop(x - psize1,y - psize1,x + psize2,y + psize2,true);
@@ -27475,7 +31831,7 @@ namespace cimg_library_suffixed {
               else cimg_forC(res,c) res(x,y,c) = (Tfloat)((*this)(x,y,c));
             } else
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (res._width>=32 && res._height>=4) firstprivate(P,Q)
+#pragma omp parallel for cimg_openmp_if(res._width>=32 && res._height>=4) firstprivate(P,Q)
 #endif
             cimg_forXY(res,x,y) { // 2d exact algorithm.
               P = img.get_crop(x - psize1,y - psize1,x + psize2,y + psize2,true);
@@ -27569,7 +31925,7 @@ namespace cimg_library_suffixed {
           else switch (n) { // Without threshold.
             case 3 : {
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (_spectrum>=2)
+#pragma omp parallel for cimg_openmp_if(_spectrum>=2)
 #endif
               cimg_forC(*this,c) {
                 T I[9] = { 0 };
@@ -27589,7 +31945,7 @@ namespace cimg_library_suffixed {
             } break;
             case 5 : {
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (_spectrum>=2)
+#pragma omp parallel for cimg_openmp_if(_spectrum>=2)
 #endif
               cimg_forC(*this,c) {
                 T I[25] = { 0 };
@@ -27648,9 +32004,10 @@ namespace cimg_library_suffixed {
             }
         } else { // 1d
 
+          CImg<T> I;
           if (threshold>0)
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (_width>=16 && _spectrum>=2)
+#pragma omp parallel for cimg_openmp_if(_width>=16 && _spectrum>=2)
 #endif
             cimg_forXC(*this,x,c) { // With threshold.
               const int
@@ -27667,26 +32024,26 @@ namespace cimg_library_suffixed {
           else switch (n) { // Without threshold.
             case 2 : {
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (_spectrum>=2)
+#pragma omp parallel for cimg_openmp_if(_spectrum>=2)
 #endif
               cimg_forC(*this,c) {
-                T I[4] = { 0 };
+                I.assign(4);
                 cimg_for2x2(*this,x,y,0,c,I,T) res(x,c) = (T)(0.5f*(I[0] + I[1]));
               }
             } break;
             case 3 : {
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (_spectrum>=2)
+#pragma omp parallel for cimg_openmp_if(_spectrum>=2)
 #endif
               cimg_forC(*this,c) {
-                T I[9] = { 0 };
+                I.assign(9);
                 cimg_for3x3(*this,x,y,0,c,I,T)
                   res(x,c) = I[3]<I[4]?(I[4]<I[5]?I[4]:(I[3]<I[5]?I[5]:I[3])):(I[3]<I[5]?I[3]:(I[4]<I[5]?I[5]:I[4]));
               }
             } break;
             default : {
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (_width>=16 && _spectrum>=2)
+#pragma omp parallel for cimg_openmp_if(_width>=16 && _spectrum>=2)
 #endif
               cimg_forXC(*this,x,c) {
                 const int
@@ -27739,7 +32096,7 @@ namespace cimg_library_suffixed {
             }
           }
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (_width*_height*_depth>=512 && _spectrum>=2)
+#pragma omp parallel for cimg_openmp_if(_width*_height*_depth>=512 && _spectrum>=2)
 #endif
           cimg_forC(*this,c) {
             Tfloat *ptrd = velocity.data(0,0,0,c), veloc_max = 0;
@@ -27786,7 +32143,7 @@ namespace cimg_library_suffixed {
           CImg<Tfloat> G = (alpha>0?get_blur(alpha).get_structure_tensors():get_structure_tensors());
           if (sigma>0) G.blur(sigma);
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (_width>=32 && _height>=16)
+#pragma omp parallel for cimg_openmp_if(_width>=32 && _height>=16)
 #endif
           cimg_forY(G,y) {
             CImg<Tfloat> val, vec;
@@ -27801,7 +32158,7 @@ namespace cimg_library_suffixed {
             }
           }
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (_width*_height>=512 && _spectrum>=2)
+#pragma omp parallel for cimg_openmp_if(_width*_height>=512 && _spectrum>=2)
 #endif
           cimg_forC(*this,c) {
             Tfloat *ptrd = velocity.data(0,0,0,c), veloc_max = 0;
@@ -27883,10 +32240,10 @@ namespace cimg_library_suffixed {
         switch (scheme) { // 3d.
         case -1 : { // Backward finite differences.
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (_width*_height*_depth>=1048576 && _spectrum>=2)
+#pragma omp parallel for cimg_openmp_if(_width*_height*_depth>=1048576 && _spectrum>=2)
 #endif
           cimg_forC(*this,c) {
-            const unsigned long off = c*_width*_height*_depth;
+            const ulongT off = (ulongT)c*_width*_height*_depth;
             Tfloat *ptrd0 = grad[0]._data + off, *ptrd1 = grad[1]._data + off, *ptrd2 = grad[2]._data + off;
             CImg_3x3x3(I,Tfloat);
             cimg_for3x3x3(*this,x,y,z,c,I,Tfloat) {
@@ -27898,10 +32255,10 @@ namespace cimg_library_suffixed {
         } break;
         case 1 : { // Forward finite differences.
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (_width*_height*_depth>=1048576 && _spectrum>=2)
+#pragma omp parallel for cimg_openmp_if(_width*_height*_depth>=1048576 && _spectrum>=2)
 #endif
           cimg_forC(*this,c) {
-            const unsigned long off = c*_width*_height*_depth;
+            const ulongT off = (ulongT)c*_width*_height*_depth;
             Tfloat *ptrd0 = grad[0]._data + off, *ptrd1 = grad[1]._data + off, *ptrd2 = grad[2]._data + off;
             CImg_2x2x2(I,Tfloat);
             cimg_for2x2x2(*this,x,y,z,c,I,Tfloat) {
@@ -27923,10 +32280,10 @@ namespace cimg_library_suffixed {
         } break;
         default : { // Central finite differences.
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (_width*_height*_depth>=1048576 && _spectrum>=2)
+#pragma omp parallel for cimg_openmp_if(_width*_height*_depth>=1048576 && _spectrum>=2)
 #endif
           cimg_forC(*this,c) {
-            const unsigned long off = c*_width*_height*_depth;
+            const ulongT off = (ulongT)c*_width*_height*_depth;
             Tfloat *ptrd0 = grad[0]._data + off, *ptrd1 = grad[1]._data + off, *ptrd2 = grad[2]._data + off;
             CImg_3x3x3(I,Tfloat);
             cimg_for3x3x3(*this,x,y,z,c,I,Tfloat) {
@@ -27943,7 +32300,7 @@ namespace cimg_library_suffixed {
 #pragma omp parallel for collapse(2) if (_width*_height>=1048576 && _depth*_spectrum>=2)
 #endif
         cimg_forZC(*this,z,c) {
-          const unsigned long off = c*_width*_height*_depth + z*_width*_height;
+          const ulongT off = (ulongT)c*_width*_height*_depth + z*_width*_height;
           Tfloat *ptrd0 = grad[0]._data + off, *ptrd1 = grad[1]._data + off;
           CImg_3x3(I,Tfloat);
           cimg_for3x3(*this,x,y,z,c,I,Tfloat) {
@@ -27957,7 +32314,7 @@ namespace cimg_library_suffixed {
 #pragma omp parallel for collapse(2) if (_width*_height>=1048576 && _depth*_spectrum>=2)
 #endif
         cimg_forZC(*this,z,c) {
-          const unsigned long off = c*_width*_height*_depth + z*_width*_height;
+          const ulongT off = (ulongT)c*_width*_height*_depth + z*_width*_height;
           Tfloat *ptrd0 = grad[0]._data + off, *ptrd1 = grad[1]._data + off;
           CImg_2x2(I,Tfloat);
           cimg_for2x2(*this,x,y,z,c,I,Tfloat) {
@@ -27971,7 +32328,7 @@ namespace cimg_library_suffixed {
 #pragma omp parallel for collapse(2) if (_width*_height>=1048576 && _depth*_spectrum>=2)
 #endif
         cimg_forZC(*this,z,c) {
-          const unsigned long off = c*_width*_height*_depth + z*_width*_height;
+          const ulongT off = (ulongT)c*_width*_height*_depth + z*_width*_height;
           Tfloat *ptrd0 = grad[0]._data + off, *ptrd1 = grad[1]._data + off;
           CImg_3x3(I,Tfloat);
           cimg_for3x3(*this,x,y,z,c,I,Tfloat) {
@@ -27985,7 +32342,7 @@ namespace cimg_library_suffixed {
 #pragma omp parallel for collapse(2) if (_width*_height>=1048576 && _depth*_spectrum>=2)
 #endif
         cimg_forZC(*this,z,c) {
-          const unsigned long off = c*_width*_height*_depth + z*_width*_height;
+          const ulongT off = (ulongT)c*_width*_height*_depth + z*_width*_height;
           Tfloat *ptrd0 = grad[0]._data + off, *ptrd1 = grad[1]._data + off;
           CImg_3x3(I,Tfloat);
           const Tfloat a = (Tfloat)(0.25f*(2-std::sqrt(2.0f))), b = (Tfloat)(0.5f*(std::sqrt(2.0f) - 1));
@@ -28008,7 +32365,7 @@ namespace cimg_library_suffixed {
 #pragma omp parallel for collapse(2) if (_width*_height>=1048576 && _depth*_spectrum>=2)
 #endif
         cimg_forZC(*this,z,c) {
-          const unsigned long off = c*_width*_height*_depth + z*_width*_height;
+          const ulongT off = (ulongT)c*_width*_height*_depth + z*_width*_height;
           Tfloat *ptrd0 = grad[0]._data + off, *ptrd1 = grad[1]._data + off;
           CImg_3x3(I,Tfloat);
           cimg_for3x3(*this,x,y,z,c,I,Tfloat) {
@@ -28051,10 +32408,10 @@ namespace cimg_library_suffixed {
       if (!cimg::strcasecmp(naxes,def_axes3d)) { // 3d
 
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (_width*_height*_depth>=1048576 && _spectrum>=2)
+#pragma omp parallel for cimg_openmp_if(_width*_height*_depth>=1048576 && _spectrum>=2)
 #endif
         cimg_forC(*this,c) {
-          const unsigned long off = c*_width*_height*_depth;
+          const ulongT off = (ulongT)c*_width*_height*_depth;
           Tfloat
             *ptrd0 = res[0]._data + off, *ptrd1 = res[1]._data + off, *ptrd2 = res[2]._data + off,
             *ptrd3 = res[3]._data + off, *ptrd4 = res[4]._data + off, *ptrd5 = res[5]._data + off;
@@ -28073,7 +32430,7 @@ namespace cimg_library_suffixed {
 #pragma omp parallel for collapse(2) if (_width*_height>=1048576 && _depth*_spectrum>=2)
 #endif
         cimg_forZC(*this,z,c) {
-          const unsigned long off = c*_width*_height*_depth + z*_width*_height;
+          const ulongT off = (ulongT)c*_width*_height*_depth + z*_width*_height;
           Tfloat *ptrd0 = res[0]._data + off, *ptrd1 = res[1]._data + off, *ptrd2 = res[2]._data + off;
           CImg_3x3(I,Tfloat);
           cimg_for3x3(*this,x,y,z,c,I,Tfloat) {
@@ -28112,7 +32469,7 @@ namespace cimg_library_suffixed {
           else if (axis1=='x' && axis2=='z') { // Ixz
             valid_axis = true;
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (_width*_height*_depth>=1048576 && _spectrum>=2)
+#pragma omp parallel for cimg_openmp_if(_width*_height*_depth>=1048576 && _spectrum>=2)
 #endif
             cimg_forC(*this,c) {
               Tfloat *ptrd = res[l2].data(0,0,0,c);
@@ -28134,7 +32491,7 @@ namespace cimg_library_suffixed {
           else if (axis1=='y' && axis2=='z') { // Iyz
             valid_axis = true;
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (_width*_height*_depth>=1048576 && _spectrum>=2)
+#pragma omp parallel for cimg_openmp_if(_width*_height*_depth>=1048576 && _spectrum>=2)
 #endif
             cimg_forC(*this,c) {
               Tfloat *ptrd = res[l2].data(0,0,0,c);
@@ -28145,7 +32502,7 @@ namespace cimg_library_suffixed {
           else if (axis1=='z' && axis2=='z') { // Izz
             valid_axis = true;
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (_width*_height*_depth>=1048576 && _spectrum>=2)
+#pragma omp parallel for cimg_openmp_if(_width*_height*_depth>=1048576 && _spectrum>=2)
 #endif
             cimg_forC(*this,c) {
               Tfloat *ptrd = res[l2].data(0,0,0,c);
@@ -28173,7 +32530,7 @@ namespace cimg_library_suffixed {
       CImg<Tfloat> res(_width,_height,_depth,_spectrum);
       if (_depth>1) { // 3d
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (_width*_height*_depth>=1048576 && _spectrum>=2)
+#pragma omp parallel for cimg_openmp_if(_width*_height*_depth>=1048576 && _spectrum>=2)
 #endif
         cimg_forC(*this,c) {
           Tfloat *ptrd = res.data(0,0,0,c);
@@ -28182,7 +32539,7 @@ namespace cimg_library_suffixed {
         }
       } else if (_height>1) { // 2d
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (_width*_height>=1048576 && _depth*_spectrum>=2)
+#pragma omp parallel for cimg_openmp_if(_width*_height>=1048576 && _depth*_spectrum>=2)
 #endif
         cimg_forC(*this,c) {
           Tfloat *ptrd = res.data(0,0,0,c);
@@ -28191,7 +32548,7 @@ namespace cimg_library_suffixed {
         }
       } else { // 1d
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (_width>=1048576 && _height*_depth*_spectrum>=2)
+#pragma omp parallel for cimg_openmp_if(_width>=1048576 && _height*_depth*_spectrum>=2)
 #endif
         cimg_forC(*this,c) {
           Tfloat *ptrd = res.data(0,0,0,c);
@@ -28204,22 +32561,21 @@ namespace cimg_library_suffixed {
 
     //! Compute the structure tensor field of an image.
     /**
-       \param scheme Numerical scheme. Can be <tt>{ 0=central | 1=fwd/bwd1 | 2=fwd/bwd2 }</tt>
+       \param is_fwbw_scheme scheme. Can be <tt>{ false=centered | true=forward-backward }</tt>
     **/
-    CImg<T>& structure_tensors(const unsigned int scheme=2) {
-      return get_structure_tensors(scheme).move_to(*this);
+    CImg<T>& structure_tensors(const bool is_fwbw_scheme=false) {
+      return get_structure_tensors(is_fwbw_scheme).move_to(*this);
     }
 
     //! Compute the structure tensor field of an image \newinstance.
-    CImg<Tfloat> get_structure_tensors(const unsigned int scheme=2) const {
+    CImg<Tfloat> get_structure_tensors(const bool is_fwbw_scheme=false) const {
       if (is_empty()) return *this;
       CImg<Tfloat> res;
       if (_depth>1) { // 3d
         res.assign(_width,_height,_depth,6,0);
-        switch (scheme) {
-        case 0 : { // classical central finite differences
+        if (!is_fwbw_scheme) { // Classical central finite differences
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (_width*_height*_depth>=1048576 && _spectrum>=2)
+#pragma omp parallel for cimg_openmp_if(_width*_height*_depth>=1048576 && _spectrum>=2)
 #endif
           cimg_forC(*this,c) {
             Tfloat
@@ -28239,33 +32595,9 @@ namespace cimg_library_suffixed {
               *(ptrd5++)+=iz*iz;
             }
           }
-        } break;
-        case 1 : { // Forward/backward finite differences (version 1).
-#ifdef cimg_use_openmp
-#pragma omp parallel for if (_width*_height*_depth>=1048576 && _spectrum>=2)
-#endif
-          cimg_forC(*this,c) {
-            Tfloat
-              *ptrd0 = res.data(0,0,0,0), *ptrd1 = res.data(0,0,0,1), *ptrd2 = res.data(0,0,0,2),
-              *ptrd3 = res.data(0,0,0,3), *ptrd4 = res.data(0,0,0,4), *ptrd5 = res.data(0,0,0,5);
-            CImg_3x3x3(I,Tfloat);
-            cimg_for3x3x3(*this,x,y,z,c,I,Tfloat) {
-              const Tfloat
-                ixf = Incc - Iccc, ixb = Iccc - Ipcc,
-                iyf = Icnc - Iccc, iyb = Iccc - Icpc,
-                izf = Iccn - Iccc, izb = Iccc - Iccp;
-              *(ptrd0++)+=(ixf*ixf + 2*ixf*ixb + ixb*ixb)/4;
-              *(ptrd1++)+=(ixf*iyf + ixf*iyb + ixb*iyf + ixb*iyb)/4;
-              *(ptrd2++)+=(ixf*izf + ixf*izb + ixb*izf + ixb*izb)/4;
-              *(ptrd3++)+=(iyf*iyf + 2*iyf*iyb + iyb*iyb)/4;
-              *(ptrd4++)+=(iyf*izf + iyf*izb + iyb*izf + iyb*izb)/4;
-              *(ptrd5++)+=(izf*izf + 2*izf*izb + izb*izb)/4;
-            }
-          }
-        } break;
-        default : { // Forward/backward finite differences (version 2).
+        } else { // Forward/backward finite differences.
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (_width*_height*_depth>=1048576 && _spectrum>=2)
+#pragma omp parallel for cimg_openmp_if(_width*_height*_depth>=1048576 && _spectrum>=2)
 #endif
           cimg_forC(*this,c) {
             Tfloat
@@ -28285,14 +32617,12 @@ namespace cimg_library_suffixed {
               *(ptrd5++)+=(izf*izf + izb*izb)/2;
             }
           }
-        } break;
         }
       } else { // 2d
         res.assign(_width,_height,_depth,3,0);
-        switch (scheme) {
-        case 0 : { // classical central finite differences
+        if (!is_fwbw_scheme) { // Classical central finite differences
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (_width*_height>=1048576 && _depth*_spectrum>=2)
+#pragma omp parallel for cimg_openmp_if(_width*_height>=1048576 && _depth*_spectrum>=2)
 #endif
           cimg_forC(*this,c) {
             Tfloat *ptrd0 = res.data(0,0,0,0), *ptrd1 = res.data(0,0,0,1), *ptrd2 = res.data(0,0,0,2);
@@ -28306,27 +32636,9 @@ namespace cimg_library_suffixed {
               *(ptrd2++)+=iy*iy;
             }
           }
-        } break;
-        case 1 : { // Forward/backward finite differences (version 1).
+        } else { // Forward/backward finite differences (version 2).
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (_width*_height>=1048576 && _depth*_spectrum>=2)
-#endif
-          cimg_forC(*this,c) {
-            Tfloat *ptrd0 = res.data(0,0,0,0), *ptrd1 = res.data(0,0,0,1), *ptrd2 = res.data(0,0,0,2);
-            CImg_3x3(I,Tfloat);
-            cimg_for3x3(*this,x,y,0,c,I,Tfloat) {
-              const Tfloat
-                ixf = Inc - Icc, ixb = Icc - Ipc,
-                iyf = Icn - Icc, iyb = Icc - Icp;
-              *(ptrd0++)+=(ixf*ixf + 2*ixf*ixb + ixb*ixb)/4;
-              *(ptrd1++)+=(ixf*iyf + ixf*iyb + ixb*iyf + ixb*iyb)/4;
-              *(ptrd2++)+=(iyf*iyf + 2*iyf*iyb + iyb*iyb)/4;
-            }
-          }
-        } break;
-        default : { // Forward/backward finite differences (version 2).
-#ifdef cimg_use_openmp
-#pragma omp parallel for if (_width*_height>=1048576 && _depth*_spectrum>=2)
+#pragma omp parallel for cimg_openmp_if(_width*_height>=1048576 && _depth*_spectrum>=2)
 #endif
           cimg_forC(*this,c) {
             Tfloat *ptrd0 = res.data(0,0,0,0), *ptrd1 = res.data(0,0,0,1), *ptrd2 = res.data(0,0,0,2);
@@ -28340,7 +32652,6 @@ namespace cimg_library_suffixed {
               *(ptrd2++)+=(iyf*iyf + iyb*iyb)/2;
             }
           }
-        } break;
         }
       }
       return res;
@@ -28431,14 +32742,15 @@ namespace cimg_library_suffixed {
        \param nb_scales Number of scales used to estimate the displacement field.
        \param iteration_max Maximum number of iterations allowed for one scale.
        \param is_backward If false, match I2(X + U(X)) = I1(X), else match I2(X) = I1(X - U(X)).
-       \param constraints A list of constrained pixels (as a Nx4 or Nx6 image), i.e defining N points
-         of the estimated flow having a known value.
+       \param guide Image used as the initial correspondence estimate for the algorithm.
+       'guide' may have a last channel with boolean values (0=false | other=true) that
+       tells for each pixel if its correspondence vector is constrained to its initial value (constraint mask).
     **/
     CImg<T>& displacement(const CImg<T>& source, const float smoothness=0.1f, const float precision=5.0f,
                           const unsigned int nb_scales=0, const unsigned int iteration_max=10000,
                           const bool is_backward=false,
-                          const CImg<floatT>& constraints=CImg<floatT>::empty()) {
-      return get_displacement(source,smoothness,precision,nb_scales,iteration_max,is_backward,constraints).
+                          const CImg<floatT>& guide=CImg<floatT>::const_empty()) {
+      return get_displacement(source,smoothness,precision,nb_scales,iteration_max,is_backward,guide).
         move_to(*this);
     }
 
@@ -28447,7 +32759,7 @@ namespace cimg_library_suffixed {
                                   const float smoothness=0.1f, const float precision=5.0f,
                                   const unsigned int nb_scales=0, const unsigned int iteration_max=10000,
                                   const bool is_backward=false,
-                                  const CImg<floatT>& constraints=CImg<floatT>::empty()) const {
+                                  const CImg<floatT>& guide=CImg<floatT>::const_empty()) const {
       if (is_empty() || !source) return +*this;
       if (!is_sameXYZC(source))
         throw CImgArgumentException(_cimg_instance
@@ -28461,7 +32773,18 @@ namespace cimg_library_suffixed {
                                     "(should be >=0)",
                                     cimg_instance,
                                     precision);
+
       const bool is_3d = source._depth>1;
+      const unsigned int constraint = is_3d?3:2;
+
+      if (guide &&
+          (guide._width!=_width || guide._height!=_height || guide._depth!=_depth || guide._spectrum<constraint))
+        throw CImgArgumentException(_cimg_instance
+                                    "displacement(): Specified guide (%u,%u,%u,%u,%p) "
+                                    "has invalid dimensions.",
+                                    cimg_instance,
+                                    guide._width,guide._height,guide._depth,guide._spectrum,guide._data);
+
       const unsigned int
         mins = is_3d?cimg::min(_width,_height,_depth):cimg::min(_width,_height),
         _nb_scales = nb_scales>0?nb_scales:
@@ -28471,14 +32794,7 @@ namespace cimg_library_suffixed {
       float sm, sM = source.max_min(sm), tm, tM = max_min(tm);
       const float sdelta = sm==sM?1:(sM - sm), tdelta = tm==tM?1:(tM - tm);
 
-      if (constraints && (constraints.height()!=4 || is_3d) && (constraints.height()!=6 || !is_3d))
-        throw CImgArgumentException(_cimg_instance
-                                    "displacement(): Invalid specified constraints image (%u,%u,%u,%u,%p) "
-                                    " (should be a Nx4 or Nx6 image).",
-                                    cimg_instance,
-                                    constraints._width,constraints._height,constraints._depth,constraints._spectrum,
-                                    constraints._data);
-      CImg<floatT> U;
+      CImg<floatT> U, V;
       floatT bound = 0;
       for (int scale = (int)_nb_scales - 1; scale>=0; --scale) {
         const float factor = (float)std::pow(1.5,(double)scale);
@@ -28490,29 +32806,12 @@ namespace cimg_library_suffixed {
         const CImg<Tfloat>
           I1 = (source.get_resize(sw,sh,sd,-100,2)-=sm)/=sdelta,
           I2 = (get_resize(I1,2)-=tm)/=tdelta;
+        if (guide._spectrum>constraint) guide.get_resize(I2._width,I2._height,I2._depth,-100,1).move_to(V);
         if (U) (U*=1.5f).resize(I2._width,I2._height,I2._depth,-100,3);
-        else U.assign(I2._width,I2._height,I2._depth,is_3d?3:2,0);
-        if (constraints) {
-          if (is_3d) cimg_forX(constraints,k) {
-              const int
-                cx = (int)(constraints(k,0)*U.width()/width()),
-                cy = (int)(constraints(k,1)*U.height()/height()),
-                cz = (int)(constraints(k,2)*U.depth()/depth());
-              if (U.contains(U(cx,cy,cz))) {
-                U(cx,cy,cz,0) = (float)(constraints(k,3)/factor);
-                U(cx,cy,cz,1) = (float)(constraints(k,4)/factor);
-                U(cx,cy,cz,2) = (float)(constraints(k,5)/factor);
-              }
-            }
-          else cimg_forX(constraints,k) {
-              const int
-                cx = (int)(constraints(k,0)*U.width()/width()),
-                cy = (int)(constraints(k,1)*U.height()/height());
-              if (U.contains(U(cx,cy))) {
-                U(cx,cy,0) = (float)(constraints(k,2)/factor);
-                U(cx,cy,1) = (float)(constraints(k,3)/factor);
-              }
-            }
+        else {
+          if (guide)
+            guide.get_shared_channels(0,is_3d?2:1).get_resize(I2._width,I2._height,I2._depth,-100,2).move_to(U);
+          else U.assign(I2._width,I2._height,I2._depth,is_3d?3:2,0);
         }
 
         float dt = 2, energy = cimg::type<float>::max();
@@ -28521,6 +32820,7 @@ namespace cimg_library_suffixed {
         for (unsigned int iteration = 0; iteration<iteration_max; ++iteration) {
           cimg_test_abort();
           float _energy = 0;
+
           if (is_3d) { // 3d version.
             if (smoothness>=0) // Isotropic regularization.
 #ifdef cimg_use_openmp
@@ -28567,6 +32867,11 @@ namespace cimg_library_suffixed {
                   }
                   _energy+=delta_I*delta_I + smoothness*_energy_regul;
                 }
+                if (V) cimg_forXYZ(V,x,y,z) if (V(x,y,z,3)) { // Apply constraints.
+                    U(x,y,z,0) = V(x,y,z,0)/factor;
+                    U(x,y,z,1) = V(x,y,z,1)/factor;
+                    U(x,y,z,2) = V(x,y,z,2)/factor;
+                  }
               } else { // Anisotropic regularization.
               const float nsmoothness = -smoothness;
 #ifdef cimg_use_openmp
@@ -28628,23 +32933,17 @@ namespace cimg_library_suffixed {
                   }
                   _energy+=delta_I*delta_I + nsmoothness*_energy_regul;
                 }
+                if (V) cimg_forXYZ(V,x,y,z) if (V(x,y,z,3)) { // Apply constraints.
+                    U(x,y,z,0) = V(x,y,z,0)/factor;
+                    U(x,y,z,1) = V(x,y,z,1)/factor;
+                    U(x,y,z,2) = V(x,y,z,2)/factor;
+                  }
               }
             }
-            if (constraints) cimg_forX(constraints,k) {
-                const int
-                  cx = (int)(constraints(k,0)*U.width()/width()),
-                  cy = (int)(constraints(k,1)*U.height()/height()),
-                  cz = (int)(constraints(k,2)*U.depth()/depth());
-                if (U.contains(U(cx,cy,cz))) {
-                  U(cx,cy,cz,0) = (float)(constraints(k,3)/factor);
-                  U(cx,cy,cz,1) = (float)(constraints(k,4)/factor);
-                  U(cx,cy,cz,2) = (float)(constraints(k,5)/factor);
-                }
-              }
           } else { // 2d version.
             if (smoothness>=0) // Isotropic regularization.
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (_height>=8 && _width>=16) reduction(+:_energy)
+#pragma omp parallel for cimg_openmp_if(_height>=8 && _width>=16) reduction(+:_energy)
 #endif
               cimg_forY(U,y) {
                 const int _p1y = y?y - 1:0, _n1y = y<U.height() - 1?y + 1:y;
@@ -28678,10 +32977,14 @@ namespace cimg_library_suffixed {
                   }
                   _energy+=delta_I*delta_I + smoothness*_energy_regul;
                 }
+                if (V) cimg_forX(V,x) if (V(x,y,2)) { // Apply constraints.
+                    U(x,y,0) = V(x,y,0)/factor;
+                    U(x,y,1) = V(x,y,1)/factor;
+                  }
               } else { // Anisotropic regularization.
               const float nsmoothness = -smoothness;
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (_height>=8 && _width>=16) reduction(+:_energy)
+#pragma omp parallel for cimg_openmp_if(_height>=8 && _width>=16) reduction(+:_energy)
 #endif
               cimg_forY(U,y) {
                 const int _p1y = y?y - 1:0, _n1y = y<U.height() - 1?y + 1:y;
@@ -28723,17 +33026,12 @@ namespace cimg_library_suffixed {
                   }
                   _energy+=delta_I*delta_I + nsmoothness*_energy_regul;
                 }
+                if (V) cimg_forX(V,x) if (V(x,y,2)) { // Apply constraints.
+                    U(x,y,0) = V(x,y,0)/factor;
+                    U(x,y,1) = V(x,y,1)/factor;
+                  }
               }
             }
-            if (constraints) cimg_forX(constraints,k) {
-                const int
-                  cx = (int)(constraints(k,0)*U.width()/width()),
-                  cy = (int)(constraints(k,1)*U.height()/height());
-                if (U.contains(U(cx,cy))) {
-                  U(cx,cy,0) = (float)(constraints(k,2)/factor);
-                  U(cx,cy,1) = (float)(constraints(k,3)/factor);
-                }
-              }
           }
           const float d_energy = (_energy - energy)/(sw*sh*sd);
           if (d_energy<=0 && -d_energy<_precision) break;
@@ -28744,6 +33042,481 @@ namespace cimg_library_suffixed {
       return U;
     }
 
+    //! Compute correspondence map between two images, using the patch-match algorithm.
+    /**
+        \param patch_image The image containing the reference patches to match with the instance image.
+        \param patch_width Width of the patch used for matching.
+        \param patch_height Height of the patch used for matching.
+        \param patch_depth Depth of the patch used for matching.
+        \param nb_iterations Number of patch-match iterations.
+        \param nb_randoms Number of randomization attempts (per pixel).
+        \param guide Image used as the initial correspondence estimate for the algorithm.
+          'guide' may have a last channel with boolean values (0=false | other=true) that
+          tells for each pixel if its correspondence vector is constrained to its initial value (constraint mask).
+        \param[out] matching_score Returned as the image of matching scores.
+        \note
+        The patch-match algorithm is described in this paper:
+        Connelly Barnes, Eli Shechtman, Adam Finkelstein, Dan B Goldman(2009),
+        PatchMatch: A Randomized Correspondence Algorithm for Structural Image Editing
+    **/
+    template<typename t1, typename t2>
+    CImg<T>& patchmatch(const CImg<T>& patch_image,
+                        const unsigned int patch_width,
+                        const unsigned int patch_height,
+                        const unsigned int patch_depth,
+                        const unsigned int nb_iterations,
+                        const unsigned int nb_randoms,
+                        const CImg<t1> &guide,
+                        CImg<t2> &matching_score) {
+      return get_patchmatch(patch_image,patch_width,patch_height,patch_depth,
+                            nb_iterations,nb_randoms,guide,matching_score).move_to(*this);
+    }
+
+    //! Compute correspondence map between two images, using the patch-match algorithm \newinstance.
+    template<typename t1, typename t2>
+    CImg<intT> get_patchmatch(const CImg<T>& patch_image,
+                              const unsigned int patch_width,
+                              const unsigned int patch_height,
+                              const unsigned int patch_depth,
+                              const unsigned int nb_iterations,
+                              const unsigned int nb_randoms,
+                              const CImg<t1> &guide,
+                              CImg<t2> &matching_score) const {
+      return _get_patchmatch(patch_image,patch_width,patch_height,patch_depth,
+                             nb_iterations,nb_randoms,
+                             guide,true,matching_score);
+    }
+
+    //! Compute correspondence map between two images, using the patch-match algorithm \overloading.
+    template<typename t>
+    CImg<T>& patchmatch(const CImg<T>& patch_image,
+                        const unsigned int patch_width,
+                        const unsigned int patch_height,
+                        const unsigned int patch_depth,
+                        const unsigned int nb_iterations,
+                        const unsigned int nb_randoms,
+                        const CImg<t> &guide) {
+      return get_patchmatch(patch_image,patch_width,patch_height,patch_depth,
+                            nb_iterations,nb_randoms,guide).move_to(*this);
+    }
+
+    //! Compute correspondence map between two images, using the patch-match algorithm \overloading.
+    template<typename t>
+    CImg<intT> get_patchmatch(const CImg<T>& patch_image,
+                              const unsigned int patch_width,
+                              const unsigned int patch_height,
+                              const unsigned int patch_depth,
+                              const unsigned int nb_iterations,
+                              const unsigned int nb_randoms,
+                              const CImg<t> &guide) const {
+      return _get_patchmatch(patch_image,patch_width,patch_height,patch_depth,
+                             nb_iterations,nb_randoms,
+                             guide,false,CImg<T>::empty());
+    }
+
+    //! Compute correspondence map between two images, using the patch-match algorithm \overloading.
+    CImg<T>& patchmatch(const CImg<T>& patch_image,
+                        const unsigned int patch_width,
+                        const unsigned int patch_height,
+                        const unsigned int patch_depth=1,
+                        const unsigned int nb_iterations=5,
+                        const unsigned int nb_randoms=5) {
+      return get_patchmatch(patch_image,patch_width,patch_height,patch_depth,
+                            nb_iterations,nb_randoms).move_to(*this);
+    }
+
+    //! Compute correspondence map between two images, using the patch-match algorithm \overloading.
+    CImg<intT> get_patchmatch(const CImg<T>& patch_image,
+                              const unsigned int patch_width,
+                              const unsigned int patch_height,
+                              const unsigned int patch_depth=1,
+                              const unsigned int nb_iterations=5,
+                              const unsigned int nb_randoms=5) const {
+      return _get_patchmatch(patch_image,patch_width,patch_height,patch_depth,
+                             nb_iterations,nb_randoms,
+                             CImg<T>::const_empty(),
+                             false,CImg<T>::empty());
+    }
+
+    template<typename t1, typename t2>
+    CImg<intT> _get_patchmatch(const CImg<T>& patch_image,
+                               const unsigned int patch_width,
+                               const unsigned int patch_height,
+                               const unsigned int patch_depth,
+                               const unsigned int nb_iterations,
+                               const unsigned int nb_randoms,
+                               const CImg<t1> &guide,
+                               const bool is_matching_score,
+                               CImg<t2> &matching_score) const {
+      if (is_empty()) return CImg<intT>::const_empty();
+      if (patch_image._spectrum!=_spectrum)
+        throw CImgArgumentException(_cimg_instance
+                                    "patchmatch(): Instance image and specified patch image (%u,%u,%u,%u,%p) "
+                                    "have different spectrums.",
+                                    cimg_instance,
+                                    patch_image._width,patch_image._height,patch_image._depth,patch_image._spectrum,
+                                    patch_image._data);
+      if (patch_width>_width || patch_height>_height || patch_depth>_depth)
+        throw CImgArgumentException(_cimg_instance
+                                    "patchmatch(): Specified patch size %ux%ux%u is bigger than the dimensions "
+                                    "of the instance image.",
+                                    cimg_instance,patch_width,patch_height,patch_depth);
+      if (patch_width>patch_image._width || patch_height>patch_image._height || patch_depth>patch_image._depth)
+        throw CImgArgumentException(_cimg_instance
+                                    "patchmatch(): Specified patch size %ux%ux%u is bigger than the dimensions "
+                                    "of the patch image image (%u,%u,%u,%u,%p).",
+                                    cimg_instance,patch_width,patch_height,patch_depth,
+                                    patch_image._width,patch_image._height,patch_image._depth,patch_image._spectrum,
+                                    patch_image._data);
+      const unsigned int
+        _constraint = patch_image._depth>1?3:2,
+        constraint = guide._spectrum>_constraint?_constraint:0;
+
+      if (guide &&
+          (guide._width!=_width || guide._height!=_height || guide._depth!=_depth || guide._spectrum<_constraint))
+        throw CImgArgumentException(_cimg_instance
+                                    "patchmatch(): Specified guide (%u,%u,%u,%u,%p) has invalid dimensions "
+                                    "considering instance and patch image image (%u,%u,%u,%u,%p).",
+                                    cimg_instance,
+                                    guide._width,guide._height,guide._depth,guide._spectrum,guide._data,
+                                    patch_image._width,patch_image._height,patch_image._depth,patch_image._spectrum,
+                                    patch_image._data);
+
+      CImg<intT> map(_width,_height,_depth,patch_image._depth>1?3:2);
+      CImg<floatT> score(_width,_height,_depth);
+      const int
+        psizew = (int)patch_width, psizew1 = psizew/2, psizew2 = psizew - psizew1 - 1,
+        psizeh = (int)patch_height, psizeh1 = psizeh/2, psizeh2 = psizeh - psizeh1 - 1,
+        psized = (int)patch_depth, psized1 = psized/2, psized2 = psized - psized1 - 1;
+
+      if (_depth>1 || patch_image._depth>1) { // 3d version.
+
+        // Initialize correspondence map.
+        if (guide) cimg_forXYZ(*this,x,y,z) { // User-defined initialization.
+            const int
+              cx1 = x<=psizew1?x:(x<width() - psizew2?psizew1:psizew + x - width()), cx2 = psizew - cx1 - 1,
+              cy1 = y<=psizeh1?y:(y<height() - psizeh2?psizeh1:psizeh + y - height()), cy2 = psizeh - cy1 - 1,
+              cz1 = z<=psized1?z:(z<depth() - psized2?psized1:psized + z - depth()), cz2 = psized - cz1 - 1,
+              u = cimg::min(cimg::max((int)guide(x,y,z,0),cx1),patch_image.width() - 1 - cx2),
+              v = cimg::min(cimg::max((int)guide(x,y,z,1),cy1),patch_image.height() - 1 - cy2),
+              w = cimg::min(cimg::max((int)guide(x,y,z,2),cz1),patch_image.depth() - 1 - cz2);
+            map(x,y,z,0) = u;
+            map(x,y,z,1) = v;
+            map(x,y,z,2) = w;
+            score(x,y,z) = _patchmatch(*this,patch_image,patch_width,patch_height,patch_depth,
+                                       x - cx1,y - cy1,z - cz1,
+                                       u - cx1,v - cy1,w - cz1,cimg::type<float>::inf());
+          } else cimg_forXYZ(*this,x,y,z) { // Random initialization.
+            const int
+              cx1 = x<=psizew1?x:(x<width() - psizew2?psizew1:psizew + x - width()), cx2 = psizew - cx1 - 1,
+              cy1 = y<=psizeh1?y:(y<height() - psizeh2?psizeh1:psizeh + y - height()), cy2 = psizeh - cy1 - 1,
+              cz1 = z<=psized1?z:(z<depth() - psized2?psized1:psized + z - depth()), cz2 = psized - cz1 - 1,
+              u = (int)cimg::round(cimg::rand(cx1,patch_image.width() - 1 - cx2)),
+              v = (int)cimg::round(cimg::rand(cy1,patch_image.height() - 1 - cy2)),
+              w = (int)cimg::round(cimg::rand(cz1,patch_image.depth() - 1 - cz2));
+            map(x,y,z,0) = u;
+            map(x,y,z,1) = v;
+            map(x,y,z,2) = w;
+            score(x,y,z) = _patchmatch(*this,patch_image,patch_width,patch_height,patch_depth,
+                                       x - cx1,y - cy1,z - cz1,
+                                       u - cx1,v - cy1,w - cz1,cimg::type<float>::inf());
+          }
+
+        // Start iteration loop.
+        for (unsigned int iter = 0; iter<nb_iterations; ++iter) {
+          cimg_test_abort();
+          const bool is_even = !(iter%2);
+
+#ifdef cimg_use_openmp
+#pragma omp parallel for collapse(2) if (_width>64 && iter<nb_iterations-2)
+#endif
+          cimg_forXYZ(*this,X,Y,Z) {
+            const int
+              x = is_even?X:width() - 1 - X,
+              y = is_even?Y:height() - 1 - Y,
+              z = is_even?Z:depth() - 1 - Z;
+            if (score(x,y,z)<=1e-5 || (constraint && guide(x,y,z,constraint)!=0)) continue;
+            const int
+              cx1 = x<=psizew1?x:(x<width() - psizew2?psizew1:psizew + x - width()), cx2 = psizew - cx1 - 1,
+              cy1 = y<=psizeh1?y:(y<height() - psizeh2?psizeh1:psizeh + y - height()), cy2 = psizeh - cy1 - 1,
+              cz1 = z<=psized1?z:(z<depth() - psized2?psized1:psized + z - depth()), cz2 = psized - cz1 - 1,
+              xp = x - cx1,
+              yp = y - cy1,
+              zp = z - cz1;
+
+            // Propagation.
+            if (is_even) {
+              if (x>0) { // Compare with left neighbor.
+                const int u = map(x - 1,y,z,0), v = map(x - 1,y,z,1), w = map(x - 1,y,z,2);
+                if (u>=cx1 - 1 && u<patch_image.width() - 1 - cx2 &&
+                    v>=cy1 && v<patch_image.height() - cy2 &&
+                    w>=cz1 && w<patch_image.depth() - cz2) {
+                  const float
+                    current_score = score(x,y,z),
+                    D = _patchmatch(*this,patch_image,patch_width,patch_height,patch_depth,
+                                    xp,yp,zp,u + 1 - cx1,v - cy1,w - cz1,current_score);
+                  if (D<current_score) { score(x,y,z) = D; map(x,y,z,0) = u + 1; map(x,y,z,1) = v; map(x,y,z,2) = w; }
+                }
+              }
+              if (y>0) { // Compare with up neighbor.
+                const int u = map(x,y - 1,z,0), v = map(x,y - 1,z,1), w = map(x,y - 1,z,2);
+                if (u>=cx1 && u<patch_image.width() - cx2 &&
+                    v>=cy1 - 1 && v<patch_image.height() - 1 - cy2 &&
+                    w>=cz1 && w<patch_image.depth() - cx2) {
+                  const float
+                    current_score = score(x,y,z),
+                    D = _patchmatch(*this,patch_image,patch_width,patch_height,patch_depth,
+                                    xp,yp,zp,u - cx1,v + 1 - cy1,w - cz1,current_score);
+                  if (D<current_score) { score(x,y,z) = D; map(x,y,z,0) = u; map(x,y,z,1) = v + 1; map(x,y,z,2) = w; }
+                }
+              }
+              if (z>0) { // Compare with backward neighbor.
+                const int u = map(x,y,z - 1,0), v = map(x,y,z - 1,1), w = map(x,y,z - 1,2);
+                if (u>=cx1 && u<patch_image.width() - cx2 &&
+                    v>=cy1 && v<patch_image.height() - cy2 &&
+                    w>=cz1 - 1 && w<patch_image.depth() - 1 - cz2) {
+                  const float
+                    current_score = score(x,y,z),
+                    D = _patchmatch(*this,patch_image,patch_width,patch_height,patch_depth,
+                                    xp,yp,zp,u - cx1,v - cy1,w + 1 - cz1,current_score);
+                  if (D<current_score) { score(x,y,z) = D; map(x,y,z,0) = u; map(x,y,z,1) = v; map(x,y,z,2) = w + 1; }
+                }
+              }
+            } else {
+              if (x<width() - 1) { // Compare with right neighbor.
+                const int u = map(x + 1,y,z,0), v = map(x + 1,y,z,1), w = map(x + 1,y,z,2);
+                if (u>=cx1 + 1 && u<patch_image.width() + 1 - cx2 &&
+                    v>=cy1 && v<patch_image.height() - cy2 &&
+                    w>=cz1 && w<patch_image.depth() - cz2) {
+                  const float
+                    current_score = score(x,y,z),
+                    D = _patchmatch(*this,patch_image,patch_width,patch_height,patch_depth,
+                                    xp,yp,zp,u - 1 - cx1,v - cy1,w - cz1,current_score);
+                  if (D<current_score) { score(x,y,z) = D; map(x,y,z,0) = u - 1; map(x,y,z,1) = v; map(x,y,z,2) = w; }
+                }
+              }
+              if (y<height() - 1) { // Compare with bottom neighbor.
+                const int u = map(x,y + 1,z,0), v = map(x,y + 1,z,1), w = map(x,y + 1,z,2);
+                if (u>=cx1 && u<patch_image.width() - cx2 &&
+                    v>=cy1 + 1 && v<patch_image.height() + 1 - cy2 &&
+                    w>=cz1 && w<patch_image.depth() - cz2) {
+                  const float
+                    current_score = score(x,y,z),
+                    D = _patchmatch(*this,patch_image,patch_width,patch_height,patch_depth,
+                                    xp,yp,zp,u - cx1,v - 1 - cy1,w - cz1,current_score);
+                  if (D<current_score) { score(x,y,z) = D; map(x,y,z,0) = u; map(x,y,z,1) = v - 1; map(x,y,z,2) = w; }
+                }
+              }
+              if (z<depth() - 1) { // Compare with forward neighbor.
+                const int u = map(x,y,z + 1,0), v = map(x,y,z + 1,1), w = map(x,y,z + 1,2);
+                if (u>=cx1 && u<patch_image.width() - cx2 &&
+                    v>=cy1 && v<patch_image.height() - cy2 &&
+                    w>=cz1 + 1 && w<patch_image.depth() + 1 - cz2) {
+                  const float
+                    current_score = score(x,y,z),
+                    D = _patchmatch(*this,patch_image,patch_width,patch_height,patch_depth,
+                                    xp,yp,zp,u - cx1,v - cy1,w - 1 - cz1,current_score);
+                  if (D<current_score) { score(x,y,z) = D; map(x,y,z,0) = u; map(x,y,z,1) = v; map(x,y,z,2) = w - 1; }
+                }
+              }
+            }
+
+            // Randomization.
+            const int u = map(x,y,z,0), v = map(x,y,z,1), w = map(x,y,z,2);
+            float dw = (float)patch_image.width(), dh = (float)patch_image.height(), dd = (float)patch_image.depth();
+            for (unsigned int i = 0; i<nb_randoms; ++i) {
+              const int
+                ui = (int)cimg::round(cimg::rand(cimg::max(cx1,u - dw),
+                                                 cimg::min(patch_image.width() - 1 - cx2,u + dw))),
+                vi = (int)cimg::round(cimg::rand(cimg::max(cy1,v - dh),
+                                                 cimg::min(patch_image.height() - 1 - cy2,v + dh))),
+                wi = (int)cimg::round(cimg::rand(cimg::max(cz1,w - dd),
+                                                 cimg::min(patch_image.depth() - 1 - cz2,w + dd)));
+              if (ui!=u || vi!=v || wi!=w) {
+                const float
+                  current_score = score(x,y,z),
+                  D = _patchmatch(*this,patch_image,patch_width,patch_height,patch_depth,
+                                  xp,yp,zp,ui - cx1,vi - cy1,wi - cz1,current_score);
+                if (D<current_score) { score(x,y,z) = D; map(x,y,z,0) = ui; map(x,y,z,1) = vi; map(x,y,z,2) = wi; }
+                dw = cimg::max(5.0f,dw*0.5f); dh = cimg::max(5.0f,dh*0.5f); dd = cimg::max(5.0f,dd*0.5f);
+              }
+            }
+          }
+        }
+
+      } else { // 2d version.
+
+        // Initialize correspondence map.
+        if (guide) cimg_forXY(*this,x,y) { // Random initialization.
+            const int
+              cx1 = x<=psizew1?x:(x<width() - psizew2?psizew1:psizew + x - width()), cx2 = psizew - cx1 - 1,
+              cy1 = y<=psizeh1?y:(y<height() - psizeh2?psizeh1:psizeh + y - height()) , cy2 = psizeh - cy1 - 1,
+              u = cimg::min(cimg::max((int)guide(x,y,0),cx1),patch_image.width() - 1 - cx2),
+              v = cimg::min(cimg::max((int)guide(x,y,1),cy1),patch_image.height() - 1 - cy2);
+            map(x,y,0) = u;
+            map(x,y,1) = v;
+            score(x,y) = _patchmatch(*this,patch_image,patch_width,patch_height,
+                                     x - cx1,y - cy1,u - cx1,v - cy1,cimg::type<float>::inf());
+          } else cimg_forXY(*this,x,y) { // Random initialization.
+            const int
+              cx1 = x<=psizew1?x:(x<width() - psizew2?psizew1:psizew + x - width()), cx2 = psizew - cx1 - 1,
+              cy1 = y<=psizeh1?y:(y<height() - psizeh2?psizeh1:psizeh + y - height()) , cy2 = psizeh - cy1 - 1,
+              u = (int)cimg::round(cimg::rand(cx1,patch_image.width() - 1 - cx2)),
+              v = (int)cimg::round(cimg::rand(cy1,patch_image.height() - 1 - cy2));
+            map(x,y,0) = u;
+            map(x,y,1) = v;
+            score(x,y) = _patchmatch(*this,patch_image,patch_width,patch_height,
+                                     x - cx1,y - cy1,u - cx1,v - cy1,cimg::type<float>::inf());
+          }
+
+        // Start iteration loop.
+        for (unsigned int iter = 0; iter<nb_iterations; ++iter) {
+          const bool is_even = !(iter%2);
+
+#ifdef cimg_use_openmp
+#pragma omp parallel for cimg_openmp_if(_width>64 && iter<nb_iterations-2)
+#endif
+          cimg_forXY(*this,X,Y) {
+            const int
+              x = is_even?X:width() - 1 - X,
+              y = is_even?Y:height() - 1 - Y;
+            if (score(x,y)<=1e-5 || (constraint && guide(x,y,constraint)!=0)) continue;
+            const int
+              cx1 = x<=psizew1?x:(x<width() - psizew2?psizew1:psizew + x - width()), cx2 = psizew - cx1 - 1,
+              cy1 = y<=psizeh1?y:(y<height() - psizeh2?psizeh1:psizeh + y - height()) , cy2 = psizeh - cy1 - 1,
+              xp = x - cx1,
+              yp = y - cy1;
+
+            // Propagation.
+            if (is_even) {
+              if (x>0) { // Compare with left neighbor.
+                const int u = map(x - 1,y,0), v = map(x - 1,y,1);
+                if (u>=cx1 - 1 && u<patch_image.width() - 1 - cx2 &&
+                    v>=cy1 && v<patch_image.height() - cy2) {
+                  const float
+                    current_score = score(x,y),
+                    D = _patchmatch(*this,patch_image,patch_width,patch_height,
+                                    xp,yp,u + 1 - cx1,v - cy1,current_score);
+                  if (D<current_score) { score(x,y) = D; map(x,y,0) = u + 1; map(x,y,1) = v; }
+                }
+              }
+              if (y>0) { // Compare with up neighbor.
+                const int u = map(x,y - 1,0), v = map(x,y - 1,1);
+                if (u>=cx1 && u<patch_image.width() - cx2 &&
+                    v>=cy1 - 1 && v<patch_image.height() - 1 - cy2) {
+                  const float
+                    current_score = score(x,y),
+                    D = _patchmatch(*this,patch_image,patch_width,patch_height,
+                                    xp,yp,u - cx1,v + 1 - cy1,current_score);
+                  if (D<current_score) { score(x,y) = D; map(x,y,0) = u; map(x,y,1) = v + 1; }
+                }
+              }
+            } else {
+              if (x<width() - 1) { // Compare with right neighbor.
+                const int u = map(x + 1,y,0), v = map(x + 1,y,1);
+                if (u>=cx1 + 1 && u<patch_image.width() + 1 - cx2 &&
+                    v>=cy1 && v<patch_image.height() - cy2) {
+                  const float
+                    current_score = score(x,y),
+                    D = _patchmatch(*this,patch_image,patch_width,patch_height,
+                                    xp,yp,u - 1 - cx1,v - cy1,current_score);
+                  if (D<current_score) { score(x,y) = D; map(x,y,0) = u - 1; map(x,y,1) = v; }
+                }
+              }
+              if (y<height() - 1) { // Compare with bottom neighbor.
+                const int u = map(x,y + 1,0), v = map(x,y + 1,1);
+                if (u>=cx1 && u<patch_image.width() - cx2 &&
+                    v>=cy1 + 1 && v<patch_image.height() + 1 - cy2) {
+                  const float
+                    current_score = score(x,y),
+                    D = _patchmatch(*this,patch_image,patch_width,patch_height,
+                                    xp,yp,u - cx1,v - 1 - cy1,current_score);
+                  if (D<current_score) { score(x,y) = D; map(x,y,0) = u; map(x,y,1) = v - 1; }
+                }
+              }
+            }
+
+            // Randomization.
+            const int u = map(x,y,0), v = map(x,y,1);
+            float dw = (float)patch_image.width(), dh = (float)patch_image.height();
+            for (unsigned int i = 0; i<nb_randoms; ++i) {
+              const int
+                ui = (int)cimg::round(cimg::rand(cimg::max(cx1,u - dw),
+                                                 cimg::min(patch_image.width() - 1 - cx2,u + dw))),
+                vi = (int)cimg::round(cimg::rand(cimg::max(cy1,v - dh),
+                                                 cimg::min(patch_image.height() - 1 - cy2,v + dh)));
+              if (ui!=u || vi!=v) {
+                const float
+                  current_score = score(x,y),
+                  D = _patchmatch(*this,patch_image,patch_width,patch_height,
+                                  xp,yp,ui - cx1,vi - cy1,current_score);
+                if (D<current_score) { score(x,y) = D; map(x,y,0) = ui; map(x,y,1) = vi; }
+                dw = cimg::max(5.0f,dw*0.5f); dh = cimg::max(5.0f,dh*0.5f);
+              }
+            }
+          }
+        }
+      }
+      if (is_matching_score) score.move_to(matching_score);
+      return map;
+    }
+
+    // Compute SSD between two patches in different images.
+    static float _patchmatch(const CImg<T>& img1, const CImg<T>& img2,
+                             const unsigned int psizew, const unsigned int psizeh,
+                             const int x1, const int y1,
+                             const int x2, const int y2,
+                             const float max_ssd) { // 2d version.
+      const T *p1 = img1.data(x1,y1), *p2 = img2.data(x2,y2);
+      const ulongT
+        offx1 = (ulongT)img1._width - psizew,
+        offx2 = (ulongT)img2._width - psizew,
+        offy1 = (ulongT)img1._width*img1._height - psizeh*img1._width,
+        offy2 = (ulongT)img2._width*img2._height - psizeh*img2._width;
+      float ssd = 0;
+      cimg_forC(img1,c) {
+        for (unsigned int j = 0; j<psizeh; ++j) {
+          for (unsigned int i = 0; i<psizew; ++i)
+            ssd += cimg::sqr(*(p1++) - *(p2++));
+          if (ssd>max_ssd) return max_ssd;
+          p1+=offx1; p2+=offx2;
+        }
+        p1+=offy1; p2+=offy2;
+      }
+      return ssd;
+    }
+
+    static float _patchmatch(const CImg<T>& img1, const CImg<T>& img2,
+                             const unsigned int psizew, const unsigned int psizeh, const unsigned int psized,
+                             const int x1, const int y1, const int z1,
+                             const int x2, const int y2, const int z2,
+                             const float max_ssd) { // 3d version.
+      const T *p1 = img1.data(x1,y1,z1), *p2 = img2.data(x2,y2,z2);
+      const ulongT
+        offx1 = (ulongT)img1._width - psizew,
+        offx2 = (ulongT)img2._width - psizew,
+        offy1 = (ulongT)img1._width*img1._height - psizeh*img1._width - psizew,
+        offy2 = (ulongT)img2._width*img2._height - psizeh*img2._width - psizew,
+        offz1 = (ulongT)img1._width*img1._height*img1._depth - psized*img1._width*img1._height -
+        psizeh*img1._width - psizew,
+        offz2 = (ulongT)img2._width*img2._height*img2._depth - psized*img2._width*img2._height -
+        psizeh*img2._width - psizew;
+      float ssd = 0;
+      cimg_forC(img1,c) {
+        for (unsigned int k = 0; k<psized; ++k) {
+          for (unsigned int j = 0; j<psizeh; ++j) {
+            for (unsigned int i = 0; i<psizew; ++i)
+              ssd += cimg::sqr(*(p1++) - *(p2++));
+            if (ssd>max_ssd) return max_ssd;
+            p1+=offx1; p2+=offx2;
+          }
+          p1+=offy1; p2+=offy2;
+        }
+        p1+=offz1; p2+=offz2;
+      }
+      return ssd;
+    }
+
     //! Compute Euclidean distance function to a specified value.
     /**
         \param value Reference value.
@@ -28778,57 +33551,57 @@ namespace cimg_library_suffixed {
       return CImg<Tfloat>(*this,false).distance((Tfloat)value,metric);
     }
 
-    static long _distance_sep_edt(const long i, const long u, const long *const g) {
+    static longT _distance_sep_edt(const longT i, const longT u, const longT *const g) {
       return (u*u - i*i + g[u] - g[i])/(2*(u - i));
     }
 
-    static long _distance_dist_edt(const long x, const long i, const long *const g) {
+    static longT _distance_dist_edt(const longT x, const longT i, const longT *const g) {
       return (x - i)*(x - i) + g[i];
     }
 
-    static long _distance_sep_mdt(const long i, const long u, const long *const g) {
+    static longT _distance_sep_mdt(const longT i, const longT u, const longT *const g) {
       return (u - i<=g[u] - g[i]?999999999:(g[u] - g[i] + u + i)/2);
     }
 
-    static long _distance_dist_mdt(const long x, const long i, const long *const g) {
+    static longT _distance_dist_mdt(const longT x, const longT i, const longT *const g) {
       return (x<i?i - x:x - i) + g[i];
     }
 
-    static long _distance_sep_cdt(const long i, const long u, const long *const g) {
-      const long h = (i + u)/2;
+    static longT _distance_sep_cdt(const longT i, const longT u, const longT *const g) {
+      const longT h = (i + u)/2;
       if (g[i]<=g[u]) { return h<i + g[u]?i + g[u]:h; }
       return h<u - g[i]?h:u - g[i];
     }
 
-    static long _distance_dist_cdt(const long x, const long i, const long *const g) {
-      const long d = x<i?i - x:x - i;
+    static longT _distance_dist_cdt(const longT x, const longT i, const longT *const g) {
+      const longT d = x<i?i - x:x - i;
       return d<g[i]?g[i]:d;
     }
 
     static void _distance_scan(const unsigned int len,
-                               const long *const g,
-                               long (*const sep)(const long, const long, const long *const),
-                               long (*const f)(const long, const long, const long *const),
-                               long *const s,
-                               long *const t,
-                               long *const dt) {
-      long q = s[0] = t[0] = 0;
+                               const longT *const g,
+                               longT (*const sep)(const longT, const longT, const longT *const),
+                               longT (*const f)(const longT, const longT, const longT *const),
+                               longT *const s,
+                               longT *const t,
+                               longT *const dt) {
+      longT q = s[0] = t[0] = 0;
       for (int u = 1; u<(int)len; ++u) { // Forward scan.
         while ((q>=0) && f(t[q],s[q],g)>f(t[q],u,g)) { --q; }
         if (q<0) { q = 0; s[0] = u; }
-        else { const long w = 1 + sep(s[q], u, g); if (w<(long)len) { ++q; s[q] = u; t[q] = w; }}
+        else { const longT w = 1 + sep(s[q], u, g); if (w<(longT)len) { ++q; s[q] = u; t[q] = w; }}
       }
       for (int u = (int)len - 1; u>=0; --u) { dt[u] = f(u,s[q],g); if (u==t[q]) --q; } // Backward scan.
     }
 
-    CImg<T>& _distance_core(long (*const sep)(const long, const long, const long *const),
-                            long (*const f)(const long, const long, const long *const)) {
+    CImg<T>& _distance_core(longT (*const sep)(const longT, const longT, const longT *const),
+                            longT (*const f)(const longT, const longT, const longT *const)) {
  // Check for g++ 4.9.X, as OpenMP seems to crash for this particular function. I have no clues why.
 #define cimg_is_gcc49x (__GNUC__==4 && __GNUC_MINOR__==9)
 
-      const unsigned long wh = (unsigned long)_width*_height;
+      const ulongT wh = (ulongT)_width*_height;
 #if defined(cimg_use_openmp) && !cimg_is_gcc49x
-#pragma omp parallel for if (_spectrum>=2)
+#pragma omp parallel for cimg_openmp_if(_spectrum>=2)
 #endif
       cimg_forC(*this,c) {
         CImg<longT> g(_width), dt(_width), s(_width), t(_width);
@@ -28837,7 +33610,7 @@ namespace cimg_library_suffixed {
 #pragma omp parallel for collapse(2) if (_width>=512 && _height*_depth>=16) firstprivate(g,dt,s,t)
 #endif
         cimg_forYZ(*this,y,z) { // Over X-direction.
-          cimg_forX(*this,x) g[x] = (long)img(x,y,z,0,wh);
+          cimg_forX(*this,x) g[x] = (longT)img(x,y,z,0,wh);
           _distance_scan(_width,g,sep,f,s,t,dt);
           cimg_forX(*this,x) img(x,y,z,0,wh) = (T)dt[x];
         }
@@ -28847,7 +33620,7 @@ namespace cimg_library_suffixed {
 #pragma omp parallel for collapse(2) if (_height>=512 && _width*_depth>=16) firstprivate(g,dt,s,t)
 #endif
           cimg_forXZ(*this,x,z) { // Over Y-direction.
-            cimg_forY(*this,y) g[y] = (long)img(x,y,z,0,wh);
+            cimg_forY(*this,y) g[y] = (longT)img(x,y,z,0,wh);
             _distance_scan(_height,g,sep,f,s,t,dt);
             cimg_forY(*this,y) img(x,y,z,0,wh) = (T)dt[y];
           }
@@ -28858,7 +33631,7 @@ namespace cimg_library_suffixed {
 #pragma omp parallel for collapse(2) if (_depth>=512 && _width*_height>=16) firstprivate(g,dt,s,t)
 #endif
           cimg_forXY(*this,x,y) { // Over Z-direction.
-            cimg_forZ(*this,z) g[z] = (long)img(x,y,z,0,wh);
+            cimg_forZ(*this,z) g[z] = (longT)img(x,y,z,0,wh);
             _distance_scan(_depth,g,sep,f,s,t,dt);
             cimg_forZ(*this,z) img(x,y,z,0,wh) = (T)dt[z];
           }
@@ -28879,9 +33652,9 @@ namespace cimg_library_suffixed {
       bool is_value = false;
       cimg_for(*this,ptr,T) *ptr = *ptr==value?is_value=true,0:(T)999999999;
       if (!is_value) return fill(cimg::type<T>::max());
-      const unsigned long wh = (unsigned long)_width*_height;
+      const ulongT wh = (ulongT)_width*_height;
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (_spectrum>=2)
+#pragma omp parallel for cimg_openmp_if(_spectrum>=2)
 #endif
       cimg_forC(*this,c) {
         CImg<T> img = get_shared_channel(c);
@@ -28931,7 +33704,7 @@ namespace cimg_library_suffixed {
       return get_distance_dijkstra(value,metric,is_high_connectivity,return_path).move_to(*this);
     }
 
-    //! Compute distance map to a specified value, according to a custom metric (use dijkstra algorithm). \newinstance.
+    //! Compute distance map to a specified value, according to a custom metric (use dijkstra algorithm) \newinstance.
     template<typename t, typename to>
     CImg<typename cimg::superset<t,long>::type>
     get_distance_dijkstra(const T& value, const CImg<t>& metric, const bool is_high_connectivity,
@@ -29135,7 +33908,7 @@ namespace cimg_library_suffixed {
       CImg<charT> state(_width,_height,_depth); // -1=far away, 0=narrow, 1=frozen.
 
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (_spectrum>=2) firstprivate(Q,state)
+#pragma omp parallel for cimg_openmp_if(_spectrum>=2) firstprivate(Q,state)
 #endif
       cimg_forC(*this,c) {
         const CImg<T> img = get_shared_channel(c);
@@ -29692,7 +34465,7 @@ namespace cimg_library_suffixed {
                                                   real._width,real._height,real._depth,real._spectrum);
 
         data_plan = fftw_plan_dft_1d(real._depth,data_in,data_in,is_invert?FFTW_BACKWARD:FFTW_FORWARD,FFTW_ESTIMATE);
-        const unsigned long off = (unsigned long)real._width*real._height;
+        const ulongT off = (ulongT)real._width*real._height;
         cimg_forXYC(real,x,y,c) {
           T *ptrr = real.data(x,y,0,c), *ptri = imag.data(x,y,0,c);
           double *ptrd = (double*)data_in;
@@ -29717,7 +34490,7 @@ namespace cimg_library_suffixed {
 #else
       switch (cimg::uncase(axis)) {
       case 'x' : { // Fourier along X, using built-in functions.
-        const unsigned int N = real._width, N2 = (N>>1);
+        const unsigned int N = real._width, N2 = N>>1;
         if (((N - 1)&N) && N!=1)
           throw CImgInstanceException("CImgList<%s>::FFT(): Specified real and imaginary parts (%u,%u,%u,%u) "
                                       "have non 2^N dimension along the X-axis.",
@@ -29726,21 +34499,24 @@ namespace cimg_library_suffixed {
 
         for (unsigned int i = 0, j = 0; i<N2; ++i) {
           if (j>i) cimg_forYZC(real,y,z,c) {
-            cimg::swap(real(i,y,z,c),real(j,y,z,c)); cimg::swap(imag(i,y,z,c),imag(j,y,z,c));
-            if (j<N2) {
-              const unsigned int ri = N - 1 - i, rj = N - 1 - j;
-              cimg::swap(real(ri,y,z,c),real(rj,y,z,c)); cimg::swap(imag(ri,y,z,c),imag(rj,y,z,c));
+              cimg::swap(real(i,y,z,c),real(j,y,z,c));
+              cimg::swap(imag(i,y,z,c),imag(j,y,z,c));
+              if (j<N2) {
+                const unsigned int ri = N - 1 - i, rj = N - 1 - j;
+                cimg::swap(real(ri,y,z,c),real(rj,y,z,c));
+                cimg::swap(imag(ri,y,z,c),imag(rj,y,z,c));
+              }
             }
-          }
           for (unsigned int m = N, n = N2; (j+=n)>=m; j-=m, m = n, n>>=1) {}
         }
         for (unsigned int delta = 2; delta<=N; delta<<=1) {
-          const unsigned int delta2 = (delta>>1);
+          const unsigned int delta2 = delta>>1;
           for (unsigned int i = 0; i<N; i+=delta) {
             float wr = 1, wi = 0;
-            const float angle = (float)((is_invert?+1:-1)*2*cimg::PI/delta),
-                        ca = (float)std::cos(angle),
-                        sa = (float)std::sin(angle);
+            const float
+              angle = (float)((is_invert?+1:-1)*2*cimg::PI/delta),
+              ca = (float)std::cos(angle),
+              sa = (float)std::sin(angle);
             for (unsigned int k = 0; k<delta2; ++k) {
               const unsigned int j = i + k, nj = j + delta2;
               cimg_forYZC(real,y,z,c) {
@@ -29760,7 +34536,7 @@ namespace cimg_library_suffixed {
         if (is_invert) { real/=N; imag/=N; }
       } break;
       case 'y' : { // Fourier along Y, using built-in functions.
-        const unsigned int N = real._height, N2 = (N>>1);
+        const unsigned int N = real._height, N2 = N>>1;
         if (((N - 1)&N) && N!=1)
           throw CImgInstanceException("CImgList<%s>::FFT(): Specified real and imaginary parts (%u,%u,%u,%u) "
                                       "have non 2^N dimension along the Y-axis.",
@@ -29769,20 +34545,24 @@ namespace cimg_library_suffixed {
 
         for (unsigned int i = 0, j = 0; i<N2; ++i) {
           if (j>i) cimg_forXZC(real,x,z,c) {
-            cimg::swap(real(x,i,z,c),real(x,j,z,c)); cimg::swap(imag(x,i,z,c),imag(x,j,z,c));
-            if (j<N2) {
-              const unsigned int ri = N - 1 - i, rj = N - 1 - j;
-              cimg::swap(real(x,ri,z,c),real(x,rj,z,c)); cimg::swap(imag(x,ri,z,c),imag(x,rj,z,c));
+              cimg::swap(real(x,i,z,c),real(x,j,z,c));
+              cimg::swap(imag(x,i,z,c),imag(x,j,z,c));
+              if (j<N2) {
+                const unsigned int ri = N - 1 - i, rj = N - 1 - j;
+                cimg::swap(real(x,ri,z,c),real(x,rj,z,c));
+                cimg::swap(imag(x,ri,z,c),imag(x,rj,z,c));
+              }
             }
-          }
           for (unsigned int m = N, n = N2; (j+=n)>=m; j-=m, m = n, n>>=1) {}
         }
         for (unsigned int delta = 2; delta<=N; delta<<=1) {
           const unsigned int delta2 = (delta>>1);
           for (unsigned int i = 0; i<N; i+=delta) {
             float wr = 1, wi = 0;
-            const float angle = (float)((is_invert?+1:-1)*2*cimg::PI/delta),
-                        ca = (float)std::cos(angle), sa = (float)std::sin(angle);
+            const float
+              angle = (float)((is_invert?+1:-1)*2*cimg::PI/delta),
+              ca = (float)std::cos(angle),
+              sa = (float)std::sin(angle);
             for (unsigned int k = 0; k<delta2; ++k) {
               const unsigned int j = i + k, nj = j + delta2;
               cimg_forXZC(real,x,z,c) {
@@ -29802,7 +34582,7 @@ namespace cimg_library_suffixed {
         if (is_invert) { real/=N; imag/=N; }
       } break;
       case 'z' : { // Fourier along Z, using built-in functions.
-        const unsigned int N = real._depth, N2 = (N>>1);
+        const unsigned int N = real._depth, N2 = N>>1;
         if (((N - 1)&N) && N!=1)
           throw CImgInstanceException("CImgList<%s>::FFT(): Specified real and imaginary parts (%u,%u,%u,%u) "
                                       "have non 2^N dimension along the Z-axis.",
@@ -29811,20 +34591,24 @@ namespace cimg_library_suffixed {
 
         for (unsigned int i = 0, j = 0; i<N2; ++i) {
           if (j>i) cimg_forXYC(real,x,y,c) {
-            cimg::swap(real(x,y,i,c),real(x,y,j,c)); cimg::swap(imag(x,y,i,c),imag(x,y,j,c));
-            if (j<N2) {
-              const unsigned int ri = N - 1 - i, rj = N - 1 - j;
-              cimg::swap(real(x,y,ri,c),real(x,y,rj,c)); cimg::swap(imag(x,y,ri,c),imag(x,y,rj,c));
+              cimg::swap(real(x,y,i,c),real(x,y,j,c));
+              cimg::swap(imag(x,y,i,c),imag(x,y,j,c));
+              if (j<N2) {
+                const unsigned int ri = N - 1 - i, rj = N - 1 - j;
+                cimg::swap(real(x,y,ri,c),real(x,y,rj,c));
+                cimg::swap(imag(x,y,ri,c),imag(x,y,rj,c));
+              }
             }
-          }
           for (unsigned int m = N, n = N2; (j+=n)>=m; j-=m, m = n, n>>=1) {}
         }
         for (unsigned int delta = 2; delta<=N; delta<<=1) {
           const unsigned int delta2 = (delta>>1);
           for (unsigned int i = 0; i<N; i+=delta) {
             float wr = 1, wi = 0;
-            const float angle = (float)((is_invert?+1:-1)*2*cimg::PI/delta),
-                        ca = (float)std::cos(angle), sa = (float)std::sin(angle);
+            const float
+              angle = (float)((is_invert?+1:-1)*2*cimg::PI/delta),
+              ca = (float)std::cos(angle),
+              sa = (float)std::sin(angle);
             for (unsigned int k = 0; k<delta2; ++k) {
               const unsigned int j = i + k, nj = j + delta2;
               cimg_forXYC(real,x,y,c) {
@@ -29893,7 +34677,7 @@ namespace cimg_library_suffixed {
                                                 real._width,real._height,real._depth,real._spectrum);
 
       fftw_plan data_plan;
-      const unsigned long w = (unsigned long)real._width, wh = w*real._height, whd = wh*real._depth;
+      const ulongT w = (ulongT)real._width, wh = w*real._height, whd = wh*real._depth;
       data_plan = fftw_plan_dft_3d(real._width,real._height,real._depth,data_in,data_in,
                                    is_invert?FFTW_BACKWARD:FFTW_FORWARD,FFTW_ESTIMATE);
       cimg_forC(real,c) {
@@ -30085,7 +34869,7 @@ namespace cimg_library_suffixed {
     **/
     template<typename tp, typename tc, typename tt, typename tx>
     const CImg<T>& texturize_object3d(CImgList<tp>& primitives, CImgList<tc>& colors,
-                                      const CImg<tt>& texture, const CImg<tx>& coords=CImg<tx>::empty()) const {
+                                      const CImg<tt>& texture, const CImg<tx>& coords=CImg<tx>::const_empty()) const {
       if (is_empty()) return *this;
       if (_height!=3)
         throw CImgInstanceException(_cimg_instance
@@ -30992,7 +35776,7 @@ namespace cimg_library_suffixed {
     struct _functor2d_expr {
       _cimg_math_parser *mp;
       _functor2d_expr(const char *const expr):mp(0) {
-        mp = new _cimg_math_parser(CImg<T>::empty(),0,expr,0);
+        mp = new _cimg_math_parser(expr,0,CImg<T>::const_empty(),0);
       }
       ~_functor2d_expr() { delete mp; }
       float operator()(const float x, const float y) const {
@@ -31020,7 +35804,7 @@ namespace cimg_library_suffixed {
       _cimg_math_parser *mp;
       ~_functor3d_expr() { delete mp; }
       _functor3d_expr(const char *const expr):mp(0) {
-        mp = new _cimg_math_parser(CImg<T>::empty(),0,expr,0);
+        mp = new _cimg_math_parser(expr,0,CImg<T>::const_empty(),0);
       }
       float operator()(const float x, const float y, const float z) const {
         return (float)(*mp)(x,y,z,0);
@@ -31592,7 +36376,7 @@ namespace cimg_library_suffixed {
 
 #define cimg_init_scanline(color,opacity) \
     const float _sc_nopacity = cimg::abs((float)opacity), _sc_copacity = 1 - cimg::max((float)opacity,0); \
-  const unsigned long _sc_whd = (unsigned long)_width*_height*_depth
+  const ulongT _sc_whd = (ulongT)_width*_height*_depth
 
 #define cimg_draw_scanline(x0,x1,y,color,opacity,brightness) \
     _draw_scanline(x0,x1,y,color,opacity,brightness,_sc_nopacity,_sc_copacity,_sc_whd)
@@ -31604,12 +36388,12 @@ namespace cimg_library_suffixed {
     CImg<T>& _draw_scanline(const int x0, const int x1, const int y,
                             const tc *const color, const float opacity,
                             const float brightness,
-                            const float nopacity, const float copacity, const unsigned long whd) {
+                            const float nopacity, const float copacity, const ulongT whd) {
       static const T maxval = (T)cimg::min(cimg::type<T>::max(),cimg::type<tc>::max());
       const int nx0 = x0>0?x0:0, nx1 = x1<width()?x1:width() - 1, dx = nx1 - nx0;
       if (dx>=0) {
         const tc *col = color;
-        const unsigned long off = whd - dx - 1;
+        const ulongT off = whd - dx - 1;
         T *ptrd = data(nx0,y);
         if (opacity>=1) { // ** Opaque drawing **
           if (brightness==1) { // Brightness==1
@@ -31693,7 +36477,7 @@ namespace cimg_library_suffixed {
                                     "draw_point(): Specified color is (null).",
                                     cimg_instance);
       if (x0>=0 && y0>=0 && z0>=0 && x0<width() && y0<height() && z0<depth()) {
-        const unsigned long whd = (unsigned long)_width*_height*_depth;
+        const ulongT whd = (ulongT)_width*_height*_depth;
         const float nopacity = cimg::abs(opacity), copacity = 1 - cimg::max(opacity,0);
         T *ptrd = data(x0,y0,z0,0);
         const tc *col = color;
@@ -31791,10 +36575,10 @@ namespace cimg_library_suffixed {
       int dx = xright - xleft, dy = ydown - yup;
       const bool steep = dy>dx;
       if (steep) cimg::swap(nx0,ny0,nx1,ny1,dx,dy);
-      const long
-        offx = (nx0<nx1?1:-1)*(steep?width():1),
-        offy = (ny0<ny1?1:-1)*(steep?1:width());
-      const unsigned long wh = (unsigned long)_width*_height;
+      const longT
+        offx = (longT)(nx0<nx1?1:-1)*(steep?width():1),
+        offy = (longT)(ny0<ny1?1:-1)*(steep?1:width());
+      const ulongT wh = (ulongT)_width*_height;
       if (opacity>=1) {
         if (~pattern) for (int error = dx>>1, x = 0; x<=dx; ++x) {
           if (pattern&hatch) {
@@ -31907,11 +36691,12 @@ namespace cimg_library_suffixed {
       int dx = xright - xleft, dy = ydown - yup;
       const bool steep = dy>dx;
       if (steep) cimg::swap(nx0,ny0,nx1,ny1,dx,dy);
-      const long
-        offx = (nx0<nx1?1:-1)*(steep?width():1),
-        offy = (ny0<ny1?1:-1)*(steep?1:width());
-      const unsigned long wh = (unsigned long)_width*_height,
-        ndx = dx>0?(unsigned long)dx:1;
+      const longT
+        offx = (longT)(nx0<nx1?1:-1)*(steep?width():1),
+        offy = (longT)(ny0<ny1?1:-1)*(steep?1:width());
+      const ulongT
+        wh = (ulongT)_width*_height,
+        ndx = (ulongT)(dx>0?dx:1);
       if (opacity>=1) {
         if (~pattern) for (int error = dx>>1, x = 0; x<=dx; ++x) {
           const tzfloat z = Z0 + x*dz/ndx;
@@ -32028,7 +36813,7 @@ namespace cimg_library_suffixed {
         nz1 = depth() - 1;
       }
       const unsigned int dmax = (unsigned int)cimg::max(cimg::abs(nx1 - nx0),cimg::abs(ny1 - ny0),nz1 - nz0);
-      const unsigned long whd = (unsigned long)_width*_height*_depth;
+      const ulongT whd = (ulongT)_width*_height*_depth;
       const float px = (nx1 - nx0)/(float)dmax, py = (ny1 - ny0)/(float)dmax, pz = (nz1 - nz0)/(float)dmax;
       float x = (float)nx0, y = (float)ny0, z = (float)nz0;
       if (opacity>=1) for (unsigned int t = 0; t<=dmax; ++t) {
@@ -32133,13 +36918,13 @@ namespace cimg_library_suffixed {
       int dx = xright - xleft, dy = ydown - yup;
       const bool steep = dy>dx;
       if (steep) cimg::swap(nx0,ny0,nx1,ny1,dx,dy);
-      const long
-        offx = (nx0<nx1?1:-1)*(steep?width():1),
-        offy = (ny0<ny1?1:-1)*(steep?1:width()),
-        ndx = dx>0?dx:1;
-      const unsigned long
-        whd = (unsigned long)_width*_height*_depth,
-        twh = (unsigned long)texture._width*texture._height;
+      const longT
+        offx = (longT)(nx0<nx1?1:-1)*(steep?width():1),
+        offy = (longT)(ny0<ny1?1:-1)*(steep?1:width()),
+        ndx = (longT)(dx>0?dx:1);
+      const ulongT
+        whd = (ulongT)_width*_height*_depth,
+        twh = (ulongT)texture._width*texture._height;
 
       if (opacity>=1) {
         if (~pattern) for (int error = dx>>1, x = 0; x<=dx; ++x) {
@@ -32274,13 +37059,13 @@ namespace cimg_library_suffixed {
       int dx = xright - xleft, dy = ydown - yup;
       const bool steep = dy>dx;
       if (steep) cimg::swap(nx0,ny0,nx1,ny1,dx,dy);
-      const long
-        offx = (nx0<nx1?1:-1)*(steep?width():1),
-        offy = (ny0<ny1?1:-1)*(steep?1:width()),
-        ndx = dx>0?dx:1;
-      const unsigned long
-        whd = (unsigned long)_width*_height*_depth,
-        twh = (unsigned long)texture._width*texture._height;
+      const longT
+        offx = (longT)(nx0<nx1?1:-1)*(steep?width():1),
+        offy = (longT)(ny0<ny1?1:-1)*(steep?1:width()),
+        ndx = (longT)(dx>0?dx:1);
+      const ulongT
+        whd = (ulongT)_width*_height*_depth,
+        twh = (ulongT)texture._width*texture._height;
 
       if (opacity>=1) {
         if (~pattern) for (int error = dx>>1, x = 0; x<=dx; ++x) {
@@ -32431,13 +37216,13 @@ namespace cimg_library_suffixed {
       int dx = xright - xleft, dy = ydown - yup;
       const bool steep = dy>dx;
       if (steep) cimg::swap(nx0,ny0,nx1,ny1,dx,dy);
-      const long
-        offx = (nx0<nx1?1:-1)*(steep?width():1),
-        offy = (ny0<ny1?1:-1)*(steep?1:width()),
-        ndx = dx>0?dx:1;
-      const unsigned long
-        whd = (unsigned long)_width*_height*_depth,
-        twh = (unsigned long)texture._width*texture._height;
+      const longT
+        offx = (longT)(nx0<nx1?1:-1)*(steep?width():1),
+        offy = (longT)(ny0<ny1?1:-1)*(steep?1:width()),
+        ndx = (longT)(dx>0?dx:1);
+      const ulongT
+        whd = (ulongT)_width*_height*_depth,
+        twh = (ulongT)texture._width*texture._height;
 
       if (opacity>=1) {
         if (~pattern) for (int error = dx>>1, x = 0; x<=dx; ++x) {
@@ -33298,7 +38083,7 @@ namespace cimg_library_suffixed {
       const float
         nopacity = cimg::abs(opacity), copacity = 1 - cimg::max(opacity,0),
         nbrightness = brightness<0?0:(brightness>2?2:brightness);
-      const long whd = width()*height()*depth(), offx = spectrum()*whd;
+      const longT whd = (longT)width()*height()*depth(), offx = spectrum()*whd;
       int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2;
       tzfloat nz0 = 1/(tzfloat)z0, nz1 = 1/(tzfloat)z1, nz2 = 1/(tzfloat)z2;
       if (ny0>ny1) cimg::swap(nx0,nx1,ny0,ny1,nz0,nz1);
@@ -33412,7 +38197,7 @@ namespace cimg_library_suffixed {
                                     cimg_instance);
       static const T maxval = (T)cimg::min(cimg::type<T>::max(),cimg::type<tc>::max());
       const float nopacity = cimg::abs(opacity), copacity = 1 - cimg::max(opacity,0);
-      const long whd = width()*height()*depth(), offx = spectrum()*whd - 1;
+      const longT whd = (longT)width()*height()*depth(), offx = spectrum()*whd - 1;
       int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2,
         nc0 = (int)((brightness0<0.0f?0.0f:(brightness0>2.0f?2.0f:brightness0))*256.0f),
         nc1 = (int)((brightness1<0.0f?0.0f:(brightness1>2.0f?2.0f:brightness1))*256.0f),
@@ -33482,7 +38267,7 @@ namespace cimg_library_suffixed {
                                     zbuffer._width,zbuffer._height,zbuffer._depth,zbuffer._spectrum,zbuffer._data);
       static const T maxval = (T)cimg::min(cimg::type<T>::max(),cimg::type<tc>::max());
       const float nopacity = cimg::abs(opacity), copacity = 1 - cimg::max(opacity,0);
-      const long whd = width()*height()*depth(), offx = spectrum()*whd;
+      const longT whd = (longT)width()*height()*depth(), offx = spectrum()*whd;
       int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2,
         nc0 = (int)((brightness0<0.0f?0.0f:(brightness0>2.0f?2.0f:brightness0))*256.0f),
         nc1 = (int)((brightness1<0.0f?0.0f:(brightness1>2.0f?2.0f:brightness1))*256.0f),
@@ -33617,9 +38402,9 @@ namespace cimg_library_suffixed {
       const float
         nopacity = cimg::abs(opacity), copacity = 1 - cimg::max(opacity,0),
         nbrightness = brightness<0?0:(brightness>2?2:brightness);
-      const unsigned long
-        whd = (unsigned long)_width*_height*_depth,
-        twh = (unsigned long)texture._width*texture._height,
+      const ulongT
+        whd = (ulongT)_width*_height*_depth,
+        twh = (ulongT)texture._width*texture._height,
         offx = _spectrum*whd - 1;
       int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2,
         ntx0 = tx0, nty0 = ty0, ntx1 = tx1, nty1 = ty1, ntx2 = tx2, nty2 = ty2;
@@ -33739,9 +38524,9 @@ namespace cimg_library_suffixed {
       const float
         nopacity = cimg::abs(opacity), copacity = 1 - cimg::max(opacity,0),
         nbrightness = brightness<0?0:(brightness>2?2:brightness);
-      const unsigned long
-        whd = (unsigned long)_width*_height*_depth,
-        twh = (unsigned long)texture._width*texture._height,
+      const ulongT
+        whd = (ulongT)_width*_height*_depth,
+        twh = (ulongT)texture._width*texture._height,
         offx = _spectrum*whd - 1;
       int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2;
       float
@@ -33883,9 +38668,9 @@ namespace cimg_library_suffixed {
       const float
         nopacity = cimg::abs(opacity), copacity = 1 - cimg::max(opacity,0),
         nbrightness = brightness<0?0:(brightness>2?2:brightness);
-      const unsigned long
-        whd = (unsigned long)_width*_height*_depth,
-        twh = (unsigned long)texture._width*texture._height,
+      const ulongT
+        whd = (ulongT)_width*_height*_depth,
+        twh = (ulongT)texture._width*texture._height,
         offx = _spectrum*whd;
       int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2;
       float
@@ -34059,9 +38844,9 @@ namespace cimg_library_suffixed {
       const float nopacity = cimg::abs(opacity), copacity = 1 - cimg::max(opacity,0);
       int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2,
         nlx0 = lx0, nly0 = ly0, nlx1 = lx1, nly1 = ly1, nlx2 = lx2, nly2 = ly2;
-      const unsigned long
-        whd = (unsigned long)_width*_height*_depth,
-        lwh = (unsigned long)light._width*light._height,
+      const ulongT
+        whd = (ulongT)_width*_height*_depth,
+        lwh = (ulongT)light._width*light._height,
         offx = _spectrum*whd - 1;
       if (ny0>ny1) cimg::swap(nx0,nx1,ny0,ny1,nlx0,nlx1,nly0,nly1);
       if (ny0>ny2) cimg::swap(nx0,nx2,ny0,ny2,nlx0,nlx2,nly0,nly2);
@@ -34152,9 +38937,9 @@ namespace cimg_library_suffixed {
                                                      +light,lx0,ly0,lx1,ly1,lx2,ly2,opacity);
       static const T maxval = (T)cimg::min(cimg::type<T>::max(),cimg::type<tc>::max());
       const float nopacity = cimg::abs(opacity), copacity = 1 - cimg::max(opacity,0);
-      const unsigned long
-        whd = (unsigned long)_width*_height*_depth,
-        lwh = (unsigned long)light._width*light._height,
+      const ulongT
+        whd = (ulongT)_width*_height*_depth,
+        lwh = (ulongT)light._width*light._height,
         offx = _spectrum*whd;
       int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2,
         nlx0 = lx0, nly0 = ly0, nlx1 = lx1, nly1 = ly1, nlx2 = lx2, nly2 = ly2;
@@ -34281,9 +39066,9 @@ namespace cimg_library_suffixed {
                              brightness0,brightness1,brightness2,opacity);
       static const T maxval = (T)cimg::min(cimg::type<T>::max(),cimg::type<tc>::max());
       const float nopacity = cimg::abs(opacity), copacity = 1 - cimg::max(opacity,0);
-      const unsigned long
-        whd = (unsigned long)_width*_height*_depth,
-        twh = (unsigned long)texture._width*texture._height,
+      const ulongT
+        whd = (ulongT)_width*_height*_depth,
+        twh = (ulongT)texture._width*texture._height,
         offx = _spectrum*whd - 1;
       int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2,
         ntx0 = tx0, nty0 = ty0, ntx1 = tx1, nty1 = ty1, ntx2 = tx2, nty2 = ty2,
@@ -34374,9 +39159,9 @@ namespace cimg_library_suffixed {
                                                        brightness0,brightness1,brightness2,opacity);
       static const T maxval = (T)cimg::min(cimg::type<T>::max(),cimg::type<tc>::max());
       const float nopacity = cimg::abs(opacity), copacity = 1 - cimg::max(opacity,0);
-      const unsigned long
-        whd = (unsigned long)_width*_height*_depth,
-        twh = (unsigned long)texture._width*texture._height,
+      const ulongT
+        whd = (ulongT)_width*_height*_depth,
+        twh = (ulongT)texture._width*texture._height,
         offx = _spectrum*whd - 1;
       int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2,
         nc0 = (int)((brightness0<0.0f?0.0f:(brightness0>2.0f?2.0f:brightness0))*256.0f),
@@ -34496,9 +39281,9 @@ namespace cimg_library_suffixed {
                                                        brightness0,brightness1,brightness2,opacity);
       static const T maxval = (T)cimg::min(cimg::type<T>::max(),cimg::type<tc>::max());
       const float nopacity = cimg::abs(opacity), copacity = 1 - cimg::max(opacity,0);
-      const unsigned long
-        whd = (unsigned long)_width*_height*_depth,
-        twh = (unsigned long)texture._width*texture._height,
+      const ulongT
+        whd = (ulongT)_width*_height*_depth,
+        twh = (ulongT)texture._width*texture._height,
         offx = _spectrum*whd;
       int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2,
         nc0 = (int)((brightness0<0.0f?0.0f:(brightness0>2.0f?2.0f:brightness0))*256.0f),
@@ -34643,10 +39428,10 @@ namespace cimg_library_suffixed {
         return draw_triangle(x0,y0,x1,y1,x2,y2,texture,tx0,ty0,tx1,ty1,tx2,ty2,+light,lx0,ly0,lx1,ly1,lx2,ly2,opacity);
       static const T maxval = (T)cimg::min(cimg::type<T>::max(),cimg::type<tc>::max());
       const float nopacity = cimg::abs(opacity), copacity = 1 - cimg::max(opacity,0);
-      const unsigned long
-        whd = (unsigned long)_width*_height*_depth,
-        twh = (unsigned long)texture._width*texture._height,
-        lwh = (unsigned long)light._width*light._height,
+      const ulongT
+        whd = (ulongT)_width*_height*_depth,
+        twh = (ulongT)texture._width*texture._height,
+        lwh = (ulongT)light._width*light._height,
         offx = _spectrum*whd - 1;
       int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2,
         ntx0 = tx0, nty0 = ty0, ntx1 = tx1, nty1 = ty1, ntx2 = tx2, nty2 = ty2,
@@ -34756,10 +39541,10 @@ namespace cimg_library_suffixed {
                              +light,lx0,ly0,lx1,ly1,lx2,ly2,opacity);
       static const T maxval = (T)cimg::min(cimg::type<T>::max(),cimg::type<tc>::max());
       const float nopacity = cimg::abs(opacity), copacity = 1 - cimg::max(opacity,0);
-      const unsigned long
-        whd = (unsigned long)_width*_height*_depth,
-        twh = (unsigned long)texture._width*texture._height,
-        lwh = (unsigned long)light._width*light._height,
+      const ulongT
+        whd = (ulongT)_width*_height*_depth,
+        twh = (ulongT)texture._width*texture._height,
+        lwh = (ulongT)light._width*light._height,
         offx = _spectrum*whd - 1;
       int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2,
         nlx0 = lx0, nly0 = ly0, nlx1 = lx1, nly1 = ly1, nlx2 = lx2, nly2 = ly2;
@@ -34899,10 +39684,10 @@ namespace cimg_library_suffixed {
                              texture,tx0,ty0,tx1,ty1,tx2,ty2,+light,lx0,ly0,lx1,ly1,lx2,ly2,opacity);
       static const T maxval = (T)cimg::min(cimg::type<T>::max(),cimg::type<tc>::max());
       const float nopacity = cimg::abs(opacity), copacity = 1 - cimg::max(opacity,0);
-      const unsigned long
-        whd = (unsigned long)_width*_height*_depth,
-        twh = (unsigned long)texture._width*texture._height,
-        lwh = (unsigned long)light._width*light._height,
+      const ulongT
+        whd = (ulongT)_width*_height*_depth,
+        twh = (ulongT)texture._width*texture._height,
+        lwh = (ulongT)light._width*light._height,
         offx = _spectrum*whd;
       int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2,
         nlx0 = lx0, nly0 = ly0, nlx1 = lx1, nly1 = ly1, nlx2 = lx2, nly2 = ly2;
@@ -35036,10 +39821,10 @@ namespace cimg_library_suffixed {
         lY = (1 + ny1 - ny0) + (ny1>=height()?height() - 1 - ny1:0) + (ny0<0?ny0:0),
         lZ = (1 + nz1 - nz0) + (nz1>=depth()?depth() - 1 - nz1:0) + (nz0<0?nz0:0),
         lC = (1 + nc1 - nc0) + (nc1>=spectrum()?spectrum() - 1 - nc1:0) + (nc0<0?nc0:0);
-      const unsigned long
-        offX = (unsigned long)_width - lX,
-        offY = (unsigned long)_width*(_height - lY),
-        offZ = (unsigned long)_width*_height*(_depth - lZ);
+      const ulongT
+        offX = (ulongT)_width - lX,
+        offY = (ulongT)_width*(_height - lY),
+        offZ = (ulongT)_width*_height*(_depth - lZ);
       const float nopacity = cimg::abs(opacity), copacity = 1 - cimg::max(opacity,0);
       T *ptrd = data(nx0<0?0:nx0,ny0<0?0:ny0,nz0<0?0:nz0,nc0<0?0:nc0);
       if (lX>0 && lY>0 && lZ>0 && lC>0)
@@ -35544,18 +40329,18 @@ namespace cimg_library_suffixed {
         lZ = sprite.depth() - (z0 + sprite.depth()>depth()?z0 + sprite.depth() - depth():0) + (bz?z0:0),
         lC = sprite.spectrum() - (c0 + sprite.spectrum()>spectrum()?c0 + sprite.spectrum() - spectrum():0) + (bc?c0:0);
       const t
-        *ptrs = sprite._data -
-        (bx?x0:0) -
-        (by?y0*sprite.width():0) -
-        (bz?z0*sprite.width()*sprite.height():0) -
-        (bc?c0*sprite.width()*sprite.height()*sprite.depth():0);
-      const unsigned long
-        offX = (unsigned long)_width - lX,
-        soffX = (unsigned long)sprite._width - lX,
-        offY = (unsigned long)_width*(_height - lY),
-        soffY = (unsigned long)sprite._width*(sprite._height - lY),
-        offZ = (unsigned long)_width*_height*(_depth - lZ),
-        soffZ = (unsigned long)sprite._width*sprite._height*(sprite._depth - lZ);
+        *ptrs = sprite._data +
+        (bx?-x0:0) +
+        (by?-y0*(ulongT)sprite.width():0) +
+        (bz?-z0*(ulongT)sprite.width()*sprite.height():0) +
+        (bc?-c0*(ulongT)sprite.width()*sprite.height()*sprite.depth():0);
+      const ulongT
+        offX = (ulongT)_width - lX,
+        soffX = (ulongT)sprite._width - lX,
+        offY = (ulongT)_width*(_height - lY),
+        soffY = (ulongT)sprite._width*(sprite._height - lY),
+        offZ = (ulongT)_width*_height*(_depth - lZ),
+        soffZ = (ulongT)sprite._width*sprite._height*(sprite._depth - lZ);
       const float nopacity = cimg::abs(opacity), copacity = 1 - cimg::max(opacity,0);
       if (lX>0 && lY>0 && lZ>0 && lC>0) {
         T *ptrd = data(x0<0?0:x0,y0<0?0:y0,z0<0?0:z0,c0<0?0:c0);
@@ -35588,18 +40373,18 @@ namespace cimg_library_suffixed {
         lZ = sprite.depth() - (z0 + sprite.depth()>depth()?z0 + sprite.depth() - depth():0) + (bz?z0:0),
         lC = sprite.spectrum() - (c0 + sprite.spectrum()>spectrum()?c0 + sprite.spectrum() - spectrum():0) + (bc?c0:0);
       const T
-        *ptrs = sprite._data -
-        (bx?x0:0) -
-        (by?y0*sprite.width():0) -
-        (bz?z0*sprite.width()*sprite.height():0) -
-        (bc?c0*sprite.width()*sprite.height()*sprite.depth():0);
-      const unsigned long
-        offX = (unsigned long)_width - lX,
-        soffX = (unsigned long)sprite._width - lX,
-        offY = (unsigned long)_width*(_height - lY),
-        soffY = (unsigned long)sprite._width*(sprite._height - lY),
-        offZ = (unsigned long)_width*_height*(_depth - lZ),
-        soffZ = (unsigned long)sprite._width*sprite._height*(sprite._depth - lZ),
+        *ptrs = sprite._data +
+        (bx?-x0:0) +
+        (by?-y0*(ulongT)sprite.width():0) +
+        (bz?-z0*(ulongT)sprite.width()*sprite.height():0) +
+        (bc?-c0*(ulongT)sprite.width()*sprite.height()*sprite.depth():0);
+      const ulongT
+        offX = (ulongT)_width - lX,
+        soffX = (ulongT)sprite._width - lX,
+        offY = (ulongT)_width*(_height - lY),
+        soffY = (ulongT)sprite._width*(sprite._height - lY),
+        offZ = (ulongT)_width*_height*(_depth - lZ),
+        soffZ = (ulongT)sprite._width*sprite._height*(sprite._depth - lZ),
         slX = lX*sizeof(T);
       const float nopacity = cimg::abs(opacity), copacity = 1 - cimg::max(opacity,0);
       if (lX>0 && lY>0 && lZ>0 && lC>0) {
@@ -35682,19 +40467,21 @@ namespace cimg_library_suffixed {
         lY = sprite.height() - (y0 + sprite.height()>height()?y0 + sprite.height() - height():0) + (by?y0:0),
         lZ = sprite.depth() - (z0 + sprite.depth()>depth()?z0 + sprite.depth() - depth():0) + (bz?z0:0),
         lC = sprite.spectrum() - (c0 + sprite.spectrum()>spectrum()?c0 + sprite.spectrum() - spectrum():0) + (bc?c0:0);
-      const int
-        coff = -(bx?x0:0) - (by?y0*mask.width():0) - (bz?z0*mask.width()*mask.height():0) -
-          (bc?c0*mask.width()*mask.height()*mask.depth():0),
-        ssize = mask.width()*mask.height()*mask.depth()*mask.spectrum();
+      const ulongT
+        coff = (bx?-x0:0) +
+        (by?-y0*(ulongT)mask.width():0) +
+        (bz?-z0*(ulongT)mask.width()*mask.height():0) +
+        (bc?-c0*(ulongT)mask.width()*mask.height()*mask.depth():0),
+        ssize = (ulongT)mask.width()*mask.height()*mask.depth()*mask.spectrum();
       const ti *ptrs = sprite._data + coff;
-      const tm *ptrm = mask._data   + coff;
-      const unsigned long
-        offX = (unsigned long)_width - lX,
-        soffX = (unsigned long)sprite._width - lX,
-        offY = (unsigned long)_width*(_height - lY),
-        soffY = (unsigned long)sprite._width*(sprite._height - lY),
-        offZ = (unsigned long)_width*_height*(_depth - lZ),
-        soffZ = (unsigned long)sprite._width*sprite._height*(sprite._depth - lZ);
+      const tm *ptrm = mask._data + coff;
+      const ulongT
+        offX = (ulongT)_width - lX,
+        soffX = (ulongT)sprite._width - lX,
+        offY = (ulongT)_width*(_height - lY),
+        soffY = (ulongT)sprite._width*(sprite._height - lY),
+        offZ = (ulongT)_width*_height*(_depth - lZ),
+        soffZ = (ulongT)sprite._width*sprite._height*(sprite._depth - lZ);
       if (lX>0 && lY>0 && lZ>0 && lC>0) {
 	T *ptrd = data(x0<0?0:x0,y0<0?0:y0,z0<0?0:z0,c0<0?0:c0);
         for (int c = 0; c<lC; ++c) {
@@ -36012,32 +40799,32 @@ namespace cimg_library_suffixed {
       if (is_empty()) return *this;
       const int yt = (y + 3 + font_height)<_height?y + 3:y - 2 - (int)font_height;
       const int siz = (int)values_x.size() - 1;
-      char txt[32] = { 0 };
+      CImg<charT> txt(32);
       CImg<T> label;
       if (siz<=0) { // Degenerated case.
         draw_line(0,y,_width - 1,y,color,opacity,pattern);
         if (!siz) {
-          cimg_snprintf(txt,sizeof(txt),"%g",(double)*values_x);
+          cimg_snprintf(txt,txt._width,"%g",(double)*values_x);
           label.assign().draw_text(0,0,txt,color,(tc*)0,opacity,font_height);
           const int
             _xt = (width() - label.width())/2,
             xt = _xt<3?3:_xt + label.width()>=width() - 2?width() - 3 - label.width():_xt;
           draw_point(width()/2,y - 1,color,opacity).draw_point(width()/2,y + 1,color,opacity);
-          if (allow_zero || txt[0]!='0' || txt[1]!=0)
+          if (allow_zero || *txt!='0' || txt[1]!=0)
             draw_text(xt,yt,txt,color,(tc*)0,opacity,font_height);
         }
       } else { // Regular case.
         if (values_x[0]<values_x[siz]) draw_arrow(0,y,_width - 1,y,color,opacity,30,5,pattern);
         else draw_arrow(_width - 1,y,0,y,color,opacity,30,5,pattern);
         cimg_foroff(values_x,x) {
-          cimg_snprintf(txt,sizeof(txt),"%g",(double)values_x(x));
+          cimg_snprintf(txt,txt._width,"%g",(double)values_x(x));
           label.assign().draw_text(0,0,txt,color,(tc*)0,opacity,font_height);
           const int
             xi = (int)(x*(_width - 1)/siz),
             _xt = xi - label.width()/2,
             xt = _xt<3?3:_xt + label.width()>=width() - 2?width() - 3 - label.width():_xt;
           draw_point(xi,y - 1,color,opacity).draw_point(xi,y + 1,color,opacity);
-          if (allow_zero || txt[0]!='0' || txt[1]!=0)
+          if (allow_zero || *txt!='0' || txt[1]!=0)
             draw_text(xt,yt,txt,color,(tc*)0,opacity,font_height);
         }
       }
@@ -36061,12 +40848,12 @@ namespace cimg_library_suffixed {
                        const bool allow_zero=true) {
       if (is_empty()) return *this;
       int siz = (int)values_y.size() - 1;
-      char txt[32] = { 0 };
+      CImg<charT> txt(32);
       CImg<T> label;
       if (siz<=0) { // Degenerated case.
         draw_line(x,0,x,_height - 1,color,opacity,pattern);
         if (!siz) {
-          cimg_snprintf(txt,sizeof(txt),"%g",(double)*values_y);
+          cimg_snprintf(txt,txt._width,"%g",(double)*values_y);
           label.assign().draw_text(0,0,txt,color,(tc*)0,opacity,font_height);
           const int
             _yt = (height() - label.height())/2,
@@ -36074,14 +40861,14 @@ namespace cimg_library_suffixed {
             _xt = x - 2 - label.width(),
             xt = _xt>=0?_xt:x + 3;
           draw_point(x - 1,height()/2,color,opacity).draw_point(x + 1,height()/2,color,opacity);
-          if (allow_zero || txt[0]!='0' || txt[1]!=0)
+          if (allow_zero || *txt!='0' || txt[1]!=0)
             draw_text(xt,yt,txt,color,(tc*)0,opacity,font_height);
         }
       } else { // Regular case.
         if (values_y[0]<values_y[siz]) draw_arrow(x,0,x,_height - 1,color,opacity,30,5,pattern);
         else draw_arrow(x,_height - 1,x,0,color,opacity,30,5,pattern);
         cimg_foroff(values_y,y) {
-          cimg_snprintf(txt,sizeof(txt),"%g",(double)values_y(y));
+          cimg_snprintf(txt,txt._width,"%g",(double)values_y(y));
           label.assign().draw_text(0,0,txt,color,(tc*)0,opacity,font_height);
           const int
             yi = (int)(y*(_height - 1)/siz),
@@ -36090,7 +40877,7 @@ namespace cimg_library_suffixed {
             _xt = x - 2 - label.width(),
             xt = _xt>=0?_xt:x + 3;
           draw_point(x - 1,yi,color,opacity).draw_point(x + 1,yi,color,opacity);
-          if (allow_zero || txt[0]!='0' || txt[1]!=0)
+          if (allow_zero || *txt!='0' || txt[1]!=0)
             draw_text(xt,yt,txt,color,(tc*)0,opacity,font_height);
         }
       }
@@ -36263,7 +41050,7 @@ namespace cimg_library_suffixed {
       }
 
       // Compute min/max and normalization factors.
-      const unsigned long
+      const ulongT
         siz = data.size(),
         _siz1 = siz - (plot_type!=3?1:0),
         siz1 = _siz1?_siz1:1;
@@ -36285,7 +41072,7 @@ namespace cimg_library_suffixed {
           draw_line(0,Y,width() - 1,Y,color,opacity,pattern);
         } else {
           const float fx = (float)_width/siz1;
-          for (unsigned long off = 1; off<siz; ++off) {
+          for (ulongT off = 1; off<siz; ++off) {
             const int
               X = (int)(off*fx) - 1,
               Y = (int)((data[off]-m)/ca);
@@ -36443,7 +41230,7 @@ namespace cimg_library_suffixed {
       region.assign(_width,_height,_depth,1,(t)0);
       if (x>=0 && x<width() && y>=0 && y<height() && z>=0 && z<depth()) {
         const float nopacity = cimg::abs(opacity), copacity = 1 - cimg::max(opacity,0);
-        const unsigned long whd = (unsigned long)_width*_height*_depth, siz = (unsigned long)_spectrum*whd;
+        const ulongT whd = (ulongT)_width*_height*_depth, siz = (ulongT)_spectrum*whd;
         const unsigned int W1 = _width - 1, H1 = _height - 1, D1 = _depth - 1;
         const bool is_3d = (_depth>1);
         const CImg<T> reference_color = get_vector_at(x,y,z);
@@ -36630,7 +41417,8 @@ namespace cimg_library_suffixed {
           for (int y0 = 0; y0<h; y0+=delta)
             for (int x0 = 0; x0<w; x0+=delta) {
               const int x1 = (x0 + delta)%w, y1 = (y0 + delta)%h, xc = (x0 + delta2)%w, yc = (y0 + delta2)%h;
-              const Tfloat val = (Tfloat)(0.25f*(ref(x0,y0) + ref(x0,y1) + ref(x0,y1) + ref(x1,y1)) + r*cimg::crand());
+              const Tfloat val = (Tfloat)(0.25f*(ref(x0,y0) + ref(x0,y1) + ref(x0,y1) + ref(x1,y1)) +
+                                          r*cimg::rand(-1,1));
               ref(xc,yc) = (T)(val<m?m:val>M?M:val);
             }
 
@@ -36639,21 +41427,24 @@ namespace cimg_library_suffixed {
             for (int x0=0; x0<w; x0+=delta) {
               const int y0 = cimg::mod(y,h), x1 = (x0 + delta)%w, y1 = (y + delta)%h,
                 xc = (x0 + delta2)%w, yc = (y + delta2)%h;
-              const Tfloat val = (Tfloat)(0.25f*(ref(xc,y0) + ref(x0,yc) + ref(xc,y1) + ref(x1,yc)) + r*cimg::crand());
+              const Tfloat val = (Tfloat)(0.25f*(ref(xc,y0) + ref(x0,yc) + ref(xc,y1) + ref(x1,yc)) +
+                                          r*cimg::rand(-1,1));
               ref(xc,yc) = (T)(val<m?m:val>M?M:val);
             }
           for (int y0 = 0; y0<h; y0+=delta)
             for (int x = -delta2; x<w; x+=delta) {
               const int x0 = cimg::mod(x,w), x1 = (x + delta)%w, y1 = (y0 + delta)%h,
                 xc = (x + delta2)%w, yc = (y0 + delta2)%h;
-              const Tfloat val = (Tfloat)(0.25f*(ref(xc,y0) + ref(x0,yc) + ref(xc,y1) + ref(x1,yc)) + r*cimg::crand());
+              const Tfloat val = (Tfloat)(0.25f*(ref(xc,y0) + ref(x0,yc) + ref(xc,y1) + ref(x1,yc)) +
+                                          r*cimg::rand(-1,1));
               ref(xc,yc) = (T)(val<m?m:val>M?M:val);
             }
           for (int y = -delta2; y<h; y+=delta)
             for (int x = -delta2; x<w; x+=delta) {
               const int x0 = cimg::mod(x,w), y0 = cimg::mod(y,h), x1 = (x + delta)%w, y1 = (y + delta)%h,
                 xc = (x + delta2)%w, yc = (y + delta2)%h;
-              const Tfloat val = (Tfloat)(0.25f*(ref(xc,y0) + ref(x0,yc) + ref(xc,y1) + ref(x1,yc)) + r*cimg::crand());
+              const Tfloat val = (Tfloat)(0.25f*(ref(xc,y0) + ref(x0,yc) + ref(xc,y1) + ref(x1,yc)) +
+                                          r*cimg::rand(-1,1));
                 ref(xc,yc) = (T)(val<m?m:val>M?M:val);
             }
         }
@@ -36780,7 +41571,7 @@ namespace cimg_library_suffixed {
                                     "draw_gaussian(): Specified color is (null).",
                                     cimg_instance);
       const float sigma2 = 2*sigma*sigma, nopacity = cimg::abs(opacity), copacity = 1 - cimg::max(opacity,0);
-      const unsigned long whd = (unsigned long)_width*_height*_depth;
+      const ulongT whd = (ulongT)_width*_height*_depth;
       const tc *col = color;
       cimg_forX(*this,x) {
         const float dx = (x - xc), val = (float)std::exp(-dx*dx/sigma2);
@@ -36817,7 +41608,7 @@ namespace cimg_library_suffixed {
       const CImg<tfloat> invT = tensor.get_invert(), invT2 = (invT*invT)/(-2.0);
       const tfloat a = invT2(0,0), b = 2*invT2(1,0), c = invT2(1,1);
       const float nopacity = cimg::abs(opacity), copacity = 1 - cimg::max(opacity,0);
-      const unsigned long whd = (unsigned long)_width*_height*_depth;
+      const ulongT whd = (ulongT)_width*_height*_depth;
       const tc *col = color;
       float dy = -yc;
       cimg_forY(*this,y) {
@@ -36869,7 +41660,7 @@ namespace cimg_library_suffixed {
       const CImg<tfloat> invT = tensor.get_invert(), invT2 = (invT*invT)/(-2.0);
       const tfloat a = invT2(0,0), b = 2*invT2(1,0), c = 2*invT2(2,0), d = invT2(1,1), e = 2*invT2(2,1), f = invT2(2,2);
       const float nopacity = cimg::abs(opacity), copacity = 1 - cimg::max(opacity,0);
-      const unsigned long whd = (unsigned long)_width*_height*_depth;
+      const ulongT whd = (ulongT)_width*_height*_depth;
       const tc *col = color;
       cimg_forXYZ(*this,x,y,z) {
         const float
@@ -37036,7 +41827,7 @@ namespace cimg_library_suffixed {
                            const bool is_double_sided=false, const float focale=700,
                            const float lightx=0, const float lighty=0, const float lightz=-5e8,
                            const float specular_lightness=0.2f, const float specular_shininess=0.1f) {
-      return draw_object3d(x0,y0,z0,vertices,primitives,colors,CImg<floatT>::empty(),
+      return draw_object3d(x0,y0,z0,vertices,primitives,colors,CImg<floatT>::const_empty(),
                            render_type,is_double_sided,focale,lightx,lighty,lightz,
                            specular_lightness,specular_shininess,CImg<floatT>::empty());
     }
@@ -37051,7 +41842,7 @@ namespace cimg_library_suffixed {
                            const float lightx, const float lighty, const float lightz,
                            const float specular_lightness, const float specular_shininess,
                            CImg<tz>& zbuffer) {
-      return draw_object3d(x0,y0,z0,vertices,primitives,colors,CImg<floatT>::empty(),
+      return draw_object3d(x0,y0,z0,vertices,primitives,colors,CImg<floatT>::const_empty(),
                            render_type,is_double_sided,focale,lightx,lighty,lightz,
                            specular_lightness,specular_shininess,zbuffer);
     }
@@ -37066,7 +41857,7 @@ namespace cimg_library_suffixed {
                            const bool is_double_sided=false, const float focale=700,
                            const float lightx=0, const float lighty=0, const float lightz=-5e8,
                            const float specular_lightness=0.2f, const float specular_shininess=0.1f) {
-      return draw_object3d(x0,y0,z0,vertices,primitives,colors,CImg<floatT>::empty(),
+      return draw_object3d(x0,y0,z0,vertices,primitives,colors,CImg<floatT>::const_empty(),
                            render_type,is_double_sided,focale,lightx,lighty,lightz,
                            specular_lightness,specular_shininess,CImg<floatT>::empty());
     }
@@ -37081,7 +41872,7 @@ namespace cimg_library_suffixed {
                            const float lightx, const float lighty, const float lightz,
                            const float specular_lightness, const float specular_shininess,
                            CImg<tz>& zbuffer) {
-      return draw_object3d(x0,y0,z0,vertices,primitives,colors,CImg<floatT>::empty(),
+      return draw_object3d(x0,y0,z0,vertices,primitives,colors,CImg<floatT>::const_empty(),
                            render_type,is_double_sided,focale,lightx,lighty,lightz,
                            specular_lightness,specular_shininess,zbuffer);
     }
@@ -37199,7 +41990,7 @@ namespace cimg_library_suffixed {
       const float absfocale = focale?cimg::abs(focale):0;
       if (absfocale) {
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (projections.size()>4096)
+#pragma omp parallel for cimg_openmp_if(projections.size()>4096)
 #endif
         cimg_forX(projections,l) { // Perspective projection
           const tpfloat
@@ -37213,7 +42004,7 @@ namespace cimg_library_suffixed {
 
       } else {
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (projections.size()>4096)
+#pragma omp parallel for cimg_openmp_if(projections.size()>4096)
 #endif
         cimg_forX(projections,l) { // Parallel projection
           const tpfloat
@@ -37236,7 +42027,7 @@ namespace cimg_library_suffixed {
       bool is_forward = zbuffer?true:false;
 
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (primitives.size()>4096)
+#pragma omp parallel for cimg_openmp_if(primitives.size()>4096)
 #endif
       cimglist_for(primitives,l) {
         const CImg<tf>& primitive = primitives[l];
@@ -37387,7 +42178,7 @@ namespace cimg_library_suffixed {
       case 3 : { // Flat Shading
         lightprops.assign(nb_visibles);
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (nb_visibles>4096)
+#pragma omp parallel for cimg_openmp_if(nb_visibles>4096)
 #endif
         cimg_forX(lightprops,l) {
           const CImg<tf>& primitive = primitives(visibles(permutations(l)));
@@ -37421,7 +42212,7 @@ namespace cimg_library_suffixed {
       case 5 : { // Phong-Shading
         CImg<tpfloat> vertices_normals(vertices._width,6,1,1,0);
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (nb_visibles>4096)
+#pragma omp parallel for cimg_openmp_if(nb_visibles>4096)
 #endif
         for (unsigned int l = 0; l<nb_visibles; ++l) {
           const CImg<tf>& primitive = primitives[visibles(l)];
@@ -37474,7 +42265,7 @@ namespace cimg_library_suffixed {
         if (render_type==4) {
           lightprops.assign(vertices._width);
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (nb_visibles>4096)
+#pragma omp parallel for cimg_openmp_if(nb_visibles>4096)
 #endif
           cimg_forX(lightprops,l) {
             const tpfloat
@@ -37495,7 +42286,7 @@ namespace cimg_library_suffixed {
             lh2 = light_texture._height/2 - 1;
           lightprops.assign(vertices._width,2);
 #ifdef cimg_use_openmp
-#pragma omp parallel for if (nb_visibles>4096)
+#pragma omp parallel for cimg_openmp_if(nb_visibles>4096)
 #endif
           cimg_forX(lightprops,l) {
             const tpfloat
@@ -38308,32 +43099,37 @@ namespace cimg_library_suffixed {
        \param XYZ Pointer to 3 values X,Y,Z which tells about the projection point coordinates, for volumetric images.
     **/
     CImg<T>& select(CImgDisplay &disp,
-		    const unsigned int feature_type=2, unsigned int *const XYZ=0) {
-      return get_select(disp,feature_type,XYZ).move_to(*this);
+		    const unsigned int feature_type=2, unsigned int *const XYZ=0,
+                    const bool exit_on_anykey=false) {
+      return get_select(disp,feature_type,XYZ,exit_on_anykey).move_to(*this);
     }
 
     //! Simple interface to select a shape from an image \overloading.
     CImg<T>& select(const char *const title,
-		    const unsigned int feature_type=2, unsigned int *const XYZ=0) {
-      return get_select(title,feature_type,XYZ).move_to(*this);
+		    const unsigned int feature_type=2, unsigned int *const XYZ=0,
+                    const bool exit_on_anykey=false) {
+      return get_select(title,feature_type,XYZ,exit_on_anykey).move_to(*this);
     }
 
     //! Simple interface to select a shape from an image \newinstance.
     CImg<intT> get_select(CImgDisplay &disp,
-		          const unsigned int feature_type=2, unsigned int *const XYZ=0) const {
-      return _get_select(disp,0,feature_type,XYZ,0,0,0,true,false);
+		          const unsigned int feature_type=2, unsigned int *const XYZ=0,
+                          const bool exit_on_anykey=false) const {
+      return _get_select(disp,0,feature_type,XYZ,0,0,0,exit_on_anykey,true,false);
     }
 
     //! Simple interface to select a shape from an image \newinstance.
     CImg<intT> get_select(const char *const title,
-    			  const unsigned int feature_type=2, unsigned int *const XYZ=0) const {
+    			  const unsigned int feature_type=2, unsigned int *const XYZ=0,
+                          const bool exit_on_anykey=false) const {
       CImgDisplay disp;
-      return _get_select(disp,title,feature_type,XYZ,0,0,0,true,false);
+      return _get_select(disp,title,feature_type,XYZ,0,0,0,exit_on_anykey,true,false);
     }
 
     CImg<intT> _get_select(CImgDisplay &disp, const char *const title,
 			   const unsigned int feature_type, unsigned int *const XYZ,
 			   const int origX, const int origY, const int origZ,
+                           const bool exit_on_anykey,
                            const bool reset_view3d,
                            const bool force_display_z_coord) const {
       if (is_empty()) return CImg<intT>(1,feature_type==0?3:6,1,1,-1);
@@ -38342,13 +43138,16 @@ namespace cimg_library_suffixed {
         if (!title) disp.set_title("CImg<%s> (%ux%ux%ux%u)",pixel_type(),_width,_height,_depth,_spectrum);
       } else if (title) disp.set_title("%s",title);
 
+      CImg<T> thumb;
+      if (width()>disp.screen_width() || height()>disp.screen_height())
+        get_resize(cimg_fitscreen(width(),height(),1),1,-100).move_to(thumb);
+
       const unsigned int old_normalization = disp.normalization();
       bool old_is_resized = disp.is_resized();
       disp._normalization = 0;
       disp.show().set_key(0).set_wheel().show_mouse();
-      disp._mouse_x = disp._mouse_y = -1;
 
-      unsigned char foreground_color[] = { 255,255,255 }, background_color[] = { 0,0,0 };
+      static const unsigned char foreground_color[] = { 255,255,255 }, background_color[] = { 0,0,0 };
 
       int area = 0, starting_area = 0, clicked_area = 0, phase = 0,
         X0 = (int)((XYZ?XYZ[0]:(_width - 1)/2)%_width),
@@ -38389,6 +43188,8 @@ namespace cimg_library_suffixed {
         if (mX>=width() && mY>=height()) area = 4;
         if (disp.button()) { if (!clicked_area) clicked_area = area; } else clicked_area = 0;
 
+        CImg<charT> filename(32);
+
         switch (key = disp.key()) {
 #if cimg_OS!=2
         case cimg::keyCTRLRIGHT :
@@ -38426,35 +43227,33 @@ namespace cimg_library_suffixed {
           } break;
         case cimg::keyS : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
             static unsigned int snap_number = 0;
-            char filename[32] = { 0 };
             std::FILE *file;
             do {
-              cimg_snprintf(filename,sizeof(filename),cimg_appname "_%.4u.bmp",snap_number++);
+              cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.bmp",snap_number++);
               if ((file=std::fopen(filename,"r"))!=0) cimg::fclose(file);
             } while (file);
             if (visu0) {
               (+visu0).draw_text(0,0," Saving snapshot... ",foreground_color,background_color,0.7f,13).display(disp);
               visu0.save(filename);
-              (+visu0).draw_text(0,0," Snapshot '%s' saved. ",foreground_color,background_color,0.7f,13,filename).
+              (+visu0).draw_text(0,0," Snapshot '%s' saved. ",foreground_color,background_color,0.7f,13,filename._data).
                 display(disp);
             }
             disp.set_key(key,false); key = 0;
           } break;
         case cimg::keyO : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
             static unsigned int snap_number = 0;
-            char filename[32] = { 0 };
             std::FILE *file;
             do {
 #ifdef cimg_use_zlib
-              cimg_snprintf(filename,sizeof(filename),cimg_appname "_%.4u.cimgz",snap_number++);
+              cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.cimgz",snap_number++);
 #else
-              cimg_snprintf(filename,sizeof(filename),cimg_appname "_%.4u.cimg",snap_number++);
+              cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.cimg",snap_number++);
 #endif
               if ((file=std::fopen(filename,"r"))!=0) cimg::fclose(file);
             } while (file);
             (+visu0).draw_text(0,0," Saving instance... ",foreground_color,background_color,0.7f,13).display(disp);
             save(filename);
-            (+visu0).draw_text(0,0," Instance '%s' saved. ",foreground_color,background_color,0.7f,13,filename).
+            (+visu0).draw_text(0,0," Instance '%s' saved. ",foreground_color,background_color,0.7f,13,filename._data).
               display(disp);
             disp.set_key(key,false); key = 0;
           } break;
@@ -38487,7 +43286,7 @@ namespace cimg_library_suffixed {
               X0 = (int)X; Y0 = (int)Y; Z0 = (int)Z;
             }
           }
-          if (disp.button()&4) { // Reset positions.
+          if (disp.button()&4) {
             X = (float)X0; Y = (float)Y0; Z = (float)Z0; phase = area = clicked_area = starting_area = 0;
             visu0.assign();
           }
@@ -38590,7 +43389,9 @@ namespace cimg_library_suffixed {
         if (mx!=omx || my!=omy || !visu0 || (_depth>1 && !view3d)) {
 
           if (!visu0) { // Create image of projected planes.
-            __get_select(disp,old_normalization,phase?X1:X0,phase?Y1:Y0,phase?Z1:Z0).move_to(visu0).resize(disp);
+            if (thumb) thumb.__get_select(disp,old_normalization,phase?X1:X0,phase?Y1:Y0,phase?Z1:Z0).move_to(visu0);
+            else __get_select(disp,old_normalization,phase?X1:X0,phase?Y1:Y0,phase?Z1:Z0).move_to(visu0);
+            visu0.resize(disp);
             view3d.assign();
             points3d.assign();
           }
@@ -38853,6 +43654,10 @@ namespace cimg_library_suffixed {
         } else if (!shape_selected) disp.wait();
         if (disp.is_resized()) { disp.resize(false)._is_resized = false; old_is_resized = true; visu0.assign(); }
         omx = mx; omy = my;
+        if (!exit_on_anykey && key && key!=cimg::keyESC &&
+            (key!=cimg::keyW || (!disp.is_keyCTRLLEFT() && !disp.is_keyCTRLRIGHT()))) {
+          key = 0;
+        }
       }
 
       // Return result.
@@ -38872,7 +43677,7 @@ namespace cimg_library_suffixed {
 	default : res[0] = X0; res[1] = Y0; res[2] = Z0;
 	}
       }
-      disp.set_button();
+      if (!exit_on_anykey || !(disp.button()&4)) disp.set_button();
       if (!visible_cursor) disp.show_mouse();
       disp._normalization = old_normalization;
       disp._is_resized = old_is_resized;
@@ -38889,9 +43694,8 @@ namespace cimg_library_suffixed {
       if (_depth>1) crop.get_projections2d(x,y,z).move_to(img2d);
       else CImg<Tuchar>(crop,false).move_to(img2d);
 
-      // Check for inf and nan values.
-      if (cimg::type<T>::is_float() && disp._normalization &&
-          (disp._normalization!=3 || cimg::type<T>::string()!=cimg::type<unsigned char>::string())) {
+      // Check for inf and NaN values.
+      if (cimg::type<T>::is_float() && normalization) {
         bool is_inf = false, is_nan = false;
         cimg_for(img2d,ptr,Tuchar)
           if (cimg::type<T>::is_inf(*ptr)) { is_inf = true; break; }
@@ -38911,7 +43715,7 @@ namespace cimg_library_suffixed {
             val_pinf = (T)(normalization==1 || normalization==3?M0 + (M0 - m0)*20 + 1:M0);
           if (is_nan)
             cimg_for(img2d,ptr,Tuchar)
-              if (cimg::type<T>::is_nan(*ptr)) *ptr = val_minf; // Replace nan values.
+              if (cimg::type<T>::is_nan(*ptr)) *ptr = val_minf; // Replace NaN values.
           if (is_inf)
             cimg_for(img2d,ptr,Tuchar)
               if (cimg::type<T>::is_inf(*ptr)) *ptr = (float)*ptr<0?val_minf:val_pinf; // Replace +-inf values.
@@ -38940,14 +43744,15 @@ namespace cimg_library_suffixed {
     CImg<intT> get_select_graph(CImgDisplay &disp,
                                 const unsigned int plot_type=1, const unsigned int vertex_type=1,
                                 const char *const labelx=0, const double xmin=0, const double xmax=0,
-                                const char *const labely=0, const double ymin=0, const double ymax=0) const {
+                                const char *const labely=0, const double ymin=0, const double ymax=0,
+                                const bool exit_on_anykey=false) const {
       if (is_empty())
         throw CImgInstanceException(_cimg_instance
                                     "select_graph(): Empty instance.",
                                     cimg_instance);
       if (!disp) disp.assign(cimg_fitscreen(CImgDisplay::screen_width()/2,CImgDisplay::screen_height()/2,1),0,0).
                    set_title("CImg<%s>",pixel_type());
-      const unsigned long siz = (unsigned long)_width*_height*_depth;
+      const ulongT siz = (ulongT)_width*_height*_depth;
       const unsigned int old_normalization = disp.normalization();
       disp.show().set_button().set_wheel()._normalization = 0;
 
@@ -38956,8 +43761,8 @@ namespace cimg_library_suffixed {
       if (nymin==nymax) { --nymin; ++nymax; }
       if (nxmin==nxmax && nxmin==0) { nxmin = 0; nxmax = siz - 1.0; }
 
-      const unsigned char black[] = { 0, 0, 0 }, white[] = { 255, 255, 255 }, gray[] = { 220, 220, 220 };
-      const unsigned char gray2[] = { 110, 110, 110 }, ngray[] = { 35, 35, 35 };
+      static const unsigned char black[] = { 0, 0, 0 }, white[] = { 255, 255, 255 }, gray[] = { 220, 220, 220 };
+      static const unsigned char gray2[] = { 110, 110, 110 }, ngray[] = { 35, 35, 35 };
       static unsigned int odimv = 0;
       static CImg<ucharT> colormap;
       if (odimv!=_spectrum) {
@@ -39091,6 +43896,7 @@ namespace cimg_library_suffixed {
         }
 
         // Test keys.
+        CImg<charT> filename(32);
         switch (okey = key) {
 #if cimg_OS!=2
         case cimg::keyCTRLRIGHT : case cimg::keySHIFTRIGHT :
@@ -39122,15 +43928,14 @@ namespace cimg_library_suffixed {
             static unsigned int snap_number = 0;
             if (visu || visu0) {
               CImg<ucharT> &screen = visu?visu:visu0;
-              char filename[32] = { 0 };
               std::FILE *file;
               do {
-                cimg_snprintf(filename,sizeof(filename),cimg_appname "_%.4u.bmp",snap_number++);
+                cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.bmp",snap_number++);
                 if ((file=std::fopen(filename,"r"))!=0) cimg::fclose(file);
               } while (file);
               (+screen).draw_text(0,0," Saving snapshot... ",black,gray,1,13).display(disp);
               screen.save(filename);
-              (+screen).draw_text(0,0," Snapshot '%s' saved. ",black,gray,1,13,filename).display(disp);
+              (+screen).draw_text(0,0," Snapshot '%s' saved. ",black,gray,1,13,filename._data).display(disp);
             }
             disp.set_key(key,false); okey = 0;
           } break;
@@ -39138,19 +43943,18 @@ namespace cimg_library_suffixed {
             static unsigned int snap_number = 0;
             if (visu || visu0) {
               CImg<ucharT> &screen = visu?visu:visu0;
-              char filename[32] = { 0 };
               std::FILE *file;
               do {
 #ifdef cimg_use_zlib
-                cimg_snprintf(filename,sizeof(filename),cimg_appname "_%.4u.cimgz",snap_number++);
+                cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.cimgz",snap_number++);
 #else
-                cimg_snprintf(filename,sizeof(filename),cimg_appname "_%.4u.cimg",snap_number++);
+                cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.cimg",snap_number++);
 #endif
                 if ((file=std::fopen(filename,"r"))!=0) cimg::fclose(file);
               } while (file);
               (+screen).draw_text(0,0," Saving instance... ",black,gray,1,13).display(disp);
               save(filename);
-              (+screen).draw_text(0,0," Instance '%s' saved. ",black,gray,1,13,filename).display(disp);
+              (+screen).draw_text(0,0," Instance '%s' saved. ",black,gray,1,13,filename._data).display(disp);
             }
             disp.set_key(key,false); okey = 0;
           } break;
@@ -39177,6 +43981,11 @@ namespace cimg_library_suffixed {
         }
         if (disp.is_resized()) { disp.resize(false); visu0.assign(); }
         if (visu && visu0) disp.wait();
+        if (!exit_on_anykey && okey && okey!=cimg::keyESC &&
+            (okey!=cimg::keyW || (!disp.is_keyCTRLLEFT() && !disp.is_keyCTRLRIGHT()))) {
+          disp.set_key(key,false);
+          okey = 0;
+        }
       }
 
       disp._normalization = old_normalization;
@@ -39405,8 +44214,8 @@ namespace cimg_library_suffixed {
                               filename?filename:"(FILE*)",dx,dy,dz,dc);
       }
       assign(dx,dy,dz,dc);
-      const unsigned long siz = size();
-      unsigned long off = 0;
+      const ulongT siz = size();
+      ulongT off = 0;
       double val;
       T *ptr = _data;
       for (err = 1, off = 0; off<siz && err==1; ++off) {
@@ -39457,7 +44266,7 @@ namespace cimg_library_suffixed {
       unsigned int cdx = 0, dx = 0, dy = 0;
       int err = 0;
       double val;
-      assign(256,256);
+      assign(256,256,1,1,0);
       while ((err = std::fscanf(nfile,"%lf%255[^0-9eEinfa.+-]",&val,delimiter._data))>0) {
         if (err>0) (*this)(cdx++,dy) = (T)val;
         if (cdx>=_width) resize(3*_width/2,_height,1,1,0);
@@ -39511,8 +44320,8 @@ namespace cimg_library_suffixed {
                                     cimg_instance);
 
       std::FILE *const nfile = file?file:cimg::fopen(filename,"rb");
-      unsigned char header[64] = { 0 };
-      cimg::fread(header,54,nfile);
+      CImg<ucharT> header(54);
+      cimg::fread(header._data,54,nfile);
       if (*header!='B' || header[1]!='M') {
         if (!file) cimg::fclose(nfile);
         throw CImgIOException(_cimg_instance
@@ -39533,11 +44342,11 @@ namespace cimg_library_suffixed {
         bpp = header[0x1C] + (header[0x1D]<<8);
 
       if (!file_size || file_size==offset) {
-        std::fseek(nfile,0,SEEK_END);
-        file_size = (int)std::ftell(nfile);
-        std::fseek(nfile,54,SEEK_SET);
+        cimg::fseek(nfile,0,SEEK_END);
+        file_size = (int)cimg::ftell(nfile);
+        cimg::fseek(nfile,54,SEEK_SET);
       }
-      if (header_size>40) std::fseek(nfile, header_size - 40, SEEK_CUR);
+      if (header_size>40) cimg::fseek(nfile,header_size - 40,SEEK_CUR);
 
       const int
         cimg_iobuffer = 24*1024*1024,
@@ -39549,7 +44358,7 @@ namespace cimg_library_suffixed {
       if (bpp<16) { if (!nb_colors) nb_colors = 1<<bpp; } else nb_colors = 0;
       if (nb_colors) { colormap.assign(nb_colors); cimg::fread(colormap._data,nb_colors,nfile); }
       const int xoffset = offset - 14 - header_size - 4*nb_colors;
-      if (xoffset>0) std::fseek(nfile,xoffset,SEEK_CUR);
+      if (xoffset>0) cimg::fseek(nfile,xoffset,SEEK_CUR);
 
       CImg<ucharT> buffer;
       if (buf_size<cimg_iobuffer) { buffer.assign(buf_size); cimg::fread(buffer._data,buf_size,nfile); }
@@ -39575,7 +44384,7 @@ namespace cimg_library_suffixed {
         for (int y = height() - 1; y>=0; --y) {
           if (buf_size>=cimg_iobuffer) {
             cimg::fread(ptrs=buffer._data,dx_bytes,nfile);
-            std::fseek(nfile,align_bytes,SEEK_CUR);
+            cimg::fseek(nfile,align_bytes,SEEK_CUR);
           }
           unsigned char mask = 0x80, val = 0;
           cimg_forX(*this,x) {
@@ -39593,7 +44402,7 @@ namespace cimg_library_suffixed {
         for (int y = height() - 1; y>=0; --y) {
           if (buf_size>=cimg_iobuffer) {
             cimg::fread(ptrs=buffer._data,dx_bytes,nfile);
-            std::fseek(nfile,align_bytes,SEEK_CUR);
+            cimg::fseek(nfile,align_bytes,SEEK_CUR);
           }
           unsigned char mask = 0xF0, val = 0;
           cimg_forX(*this,x) {
@@ -39612,7 +44421,7 @@ namespace cimg_library_suffixed {
         for (int y = height() - 1; y>=0; --y) {
           if (buf_size>=cimg_iobuffer) {
             cimg::fread(ptrs=buffer._data,dx_bytes,nfile);
-            std::fseek(nfile,align_bytes,SEEK_CUR);
+            cimg::fseek(nfile,align_bytes,SEEK_CUR);
           }
           cimg_forX(*this,x) {
             const unsigned char *col = (unsigned char*)(colormap._data + *(ptrs++));
@@ -39627,7 +44436,7 @@ namespace cimg_library_suffixed {
         for (int y = height() - 1; y>=0; --y) {
           if (buf_size>=cimg_iobuffer) {
             cimg::fread(ptrs=buffer._data,dx_bytes,nfile);
-            std::fseek(nfile,align_bytes,SEEK_CUR);
+            cimg::fseek(nfile,align_bytes,SEEK_CUR);
           }
           cimg_forX(*this,x) {
             const unsigned char c1 = *(ptrs++), c2 = *(ptrs++);
@@ -39643,7 +44452,7 @@ namespace cimg_library_suffixed {
         for (int y = height() - 1; y>=0; --y) {
           if (buf_size>=cimg_iobuffer) {
             cimg::fread(ptrs=buffer._data,dx_bytes,nfile);
-            std::fseek(nfile,align_bytes,SEEK_CUR);
+            cimg::fseek(nfile,align_bytes,SEEK_CUR);
           }
           cimg_forX(*this,x) {
             (*this)(x,y,2) = (T)*(ptrs++);
@@ -39657,7 +44466,7 @@ namespace cimg_library_suffixed {
         for (int y = height() - 1; y>=0; --y) {
           if (buf_size>=cimg_iobuffer) {
             cimg::fread(ptrs=buffer._data,dx_bytes,nfile);
-            std::fseek(nfile,align_bytes,SEEK_CUR);
+            cimg::fseek(nfile,align_bytes,SEEK_CUR);
           }
           cimg_forX(*this,x) {
             (*this)(x,y,2) = (T)*(ptrs++);
@@ -39729,18 +44538,18 @@ namespace cimg_library_suffixed {
       else return load_other(filename);
 #else
 
+      std::FILE *const nfile = file?file:cimg::fopen(filename,"rb");
       struct jpeg_decompress_struct cinfo;
       struct _cimg_error_mgr jerr;
       cinfo.err = jpeg_std_error(&jerr.original);
       jerr.original.error_exit = _cimg_jpeg_error_exit;
-
       if (setjmp(jerr.setjmp_buffer)) { // JPEG error
+        if (!file) cimg::fclose(nfile);
         throw CImgIOException(_cimg_instance
                              "load_jpeg(): Error message returned by libjpeg: %s.",
                              cimg_instance,jerr.message);
       }
 
-      std::FILE *const nfile = file?file:cimg::fopen(filename,"rb");
       jpeg_create_decompress(&cinfo);
       jpeg_stdio_src(&cinfo,nfile);
       jpeg_read_header(&cinfo,TRUE);
@@ -39757,7 +44566,8 @@ namespace cimg_library_suffixed {
       }
       CImg<ucharT> buffer(cinfo.output_width*cinfo.output_components);
       JSAMPROW row_pointer[1];
-      assign(cinfo.output_width,cinfo.output_height,1,cinfo.output_components);
+      try { assign(cinfo.output_width,cinfo.output_height,1,cinfo.output_components); }
+      catch (...) { if (!file) cimg::fclose(nfile); throw; }
       T *ptr_r = _data, *ptr_g = _data + 1UL*_width*_height, *ptr_b = _data + 2UL*_width*_height,
         *ptr_a = _data + 3UL*_width*_height;
       while (cinfo.output_scanline<cinfo.output_height) {
@@ -39818,7 +44628,7 @@ namespace cimg_library_suffixed {
         assign(W,H,1,4);
         T *ptr_r = data(0,0,0,0), *ptr_g = data(0,0,0,1), *ptr_b = data(0,0,0,2), *ptr_a = data(0,0,0,3);
         Magick::PixelPacket *pixels = image.getPixels(0,0,W,H);
-        for (unsigned long off = (unsigned long)W*H; off; --off) {
+        for (ulongT off = (ulongT)W*H; off; --off) {
           *(ptr_r++) = (T)(pixels->red);
           *(ptr_g++) = (T)(pixels->green);
           *(ptr_b++) = (T)(pixels->blue);
@@ -39831,7 +44641,7 @@ namespace cimg_library_suffixed {
         assign(W,H,1,3);
         T *ptr_r = data(0,0,0,0), *ptr_g = data(0,0,0,1), *ptr_b = data(0,0,0,2);
         Magick::PixelPacket *pixels = image.getPixels(0,0,W,H);
-        for (unsigned long off = (unsigned long)W*H; off; --off) {
+        for (ulongT off = (ulongT)W*H; off; --off) {
           *(ptr_r++) = (T)(pixels->red);
           *(ptr_g++) = (T)(pixels->green);
           *(ptr_b++) = (T)(pixels->blue);
@@ -39842,7 +44652,7 @@ namespace cimg_library_suffixed {
         assign(W,H,1,2);
         T *ptr_r = data(0,0,0,0), *ptr_a = data(0,0,0,1);
         Magick::PixelPacket *pixels = image.getPixels(0,0,W,H);
-        for (unsigned long off = (unsigned long)W*H; off; --off) {
+        for (ulongT off = (ulongT)W*H; off; --off) {
           *(ptr_r++) = (T)(pixels->red);
           *(ptr_a++) = (T)(pixels->opacity);
           ++pixels;
@@ -39852,7 +44662,7 @@ namespace cimg_library_suffixed {
         assign(W,H,1,1);
         T *ptr_r = data(0,0,0,0);
         Magick::PixelPacket *pixels = image.getPixels(0,0,W,H);
-        for (unsigned long off = (unsigned long)W*H; off; --off) {
+        for (ulongT off = (ulongT)W*H; off; --off) {
           *(ptr_r++) = (T)(pixels->red);
           ++pixels;
         }
@@ -40009,7 +44819,7 @@ namespace cimg_library_suffixed {
 
       // Allocate Memory for Image Read
       png_bytep *const imgData = new png_bytep[H];
-      for (unsigned int row = 0; row<H; ++row) imgData[row] = new png_byte[byte_depth*4*W];
+      for (unsigned int row = 0; row<H; ++row) imgData[row] = new png_byte[(size_t)byte_depth*4*W];
       png_read_image(png_ptr,imgData);
       png_read_end(png_ptr,end_info);
 
@@ -40023,7 +44833,8 @@ namespace cimg_library_suffixed {
                               color_type,nfilename?nfilename:"(FILE*)");
       }
       const bool is_alpha = (color_type==PNG_COLOR_TYPE_RGBA);
-      assign(W,H,1,(is_gray?1:3) + (is_alpha?1:0));
+      try { assign(W,H,1,(is_gray?1:3) + (is_alpha?1:0)); }
+      catch (...) { if (!file) cimg::fclose(nfile); throw; }
       T
         *ptr_r = data(0,0,0,0),
         *ptr_g = is_gray?0:data(0,0,0,1),
@@ -40097,7 +44908,7 @@ namespace cimg_library_suffixed {
       unsigned int ppm_type, W, H, D = 1, colormax = 255;
       CImg<charT> item(16384,1,1,1,0);
       int err, rval, gval, bval;
-      const long cimg_iobuffer = 24*1024*1024;
+      const longT cimg_iobuffer = (longT)24*1024*1024;
       while ((err=std::fscanf(nfile,"%16383[^\n]",item.data()))!=EOF && (*item=='#' || !err)) std::fgetc(nfile);
       if (cimg_sscanf(item," P%u",&ppm_type)!=1) {
         if (!file) cimg::fclose(nfile);
@@ -40151,13 +44962,13 @@ namespace cimg_library_suffixed {
         assign(W,H,D,1);
         T *ptrd = data(0,0,0,0);
         unsigned int w = 0, h = 0, d = 0;
-        for (long to_read = (long)((W/8 + (W%8?1:0))*H*D); to_read>0; ) {
+        for (longT to_read = (longT)((W/8 + (W%8?1:0))*H*D); to_read>0; ) {
           raw.assign(cimg::min(to_read,cimg_iobuffer));
           cimg::fread(raw._data,raw._width,nfile);
           to_read-=raw._width;
           const unsigned char *ptrs = raw._data;
           unsigned char mask = 0, val = 0;
-          for (unsigned long off = (unsigned long)raw._width; off || mask; mask>>=1) {
+          for (ulongT off = (ulongT)raw._width; off || mask; mask>>=1) {
             if (!mask) { if (off--) val = *(ptrs++); mask = 128; }
             *(ptrd++) = (T)((val&mask)?0:255);
             if (++w==W) { w = 0; mask = 0; if (++h==H) { h = 0; if (++d==D) break; }}
@@ -40169,24 +44980,24 @@ namespace cimg_library_suffixed {
           CImg<ucharT> raw;
           assign(W,H,D,1);
           T *ptrd = data(0,0,0,0);
-          for (long to_read = (long)size(); to_read>0; ) {
+          for (longT to_read = (longT)size(); to_read>0; ) {
             raw.assign(cimg::min(to_read,cimg_iobuffer));
             cimg::fread(raw._data,raw._width,nfile);
             to_read-=raw._width;
             const unsigned char *ptrs = raw._data;
-            for (unsigned long off = (unsigned long)raw._width; off; --off) *(ptrd++) = (T)*(ptrs++);
+            for (ulongT off = (ulongT)raw._width; off; --off) *(ptrd++) = (T)*(ptrs++);
           }
         } else { // 16 bits.
           CImg<ushortT> raw;
           assign(W,H,D,1);
           T *ptrd = data(0,0,0,0);
-          for (long to_read = (long)size(); to_read>0; ) {
+          for (longT to_read = (longT)size(); to_read>0; ) {
             raw.assign(cimg::min(to_read,cimg_iobuffer/2));
             cimg::fread(raw._data,raw._width,nfile);
 	    if (!cimg::endianness()) cimg::invert_endianness(raw._data,raw._width);
             to_read-=raw._width;
             const unsigned short *ptrs = raw._data;
-            for (unsigned long off = (unsigned long)raw._width; off; --off) *(ptrd++) = (T)*(ptrs++);
+            for (ulongT off = (ulongT)raw._width; off; --off) *(ptrd++) = (T)*(ptrs++);
           }
         }
       } break;
@@ -40198,12 +45009,12 @@ namespace cimg_library_suffixed {
             *ptr_r = data(0,0,0,0),
             *ptr_g = data(0,0,0,1),
             *ptr_b = data(0,0,0,2);
-          for (long to_read = (long)size(); to_read>0; ) {
+          for (longT to_read = (longT)size(); to_read>0; ) {
             raw.assign(cimg::min(to_read,cimg_iobuffer));
             cimg::fread(raw._data,raw._width,nfile);
             to_read-=raw._width;
             const unsigned char *ptrs = raw._data;
-            for (unsigned long off = (unsigned long)raw._width/3; off; --off) {
+            for (ulongT off = (ulongT)raw._width/3; off; --off) {
               *(ptr_r++) = (T)*(ptrs++);
               *(ptr_g++) = (T)*(ptrs++);
               *(ptr_b++) = (T)*(ptrs++);
@@ -40216,13 +45027,13 @@ namespace cimg_library_suffixed {
             *ptr_r = data(0,0,0,0),
             *ptr_g = data(0,0,0,1),
             *ptr_b = data(0,0,0,2);
-          for (long to_read = (int)size(); to_read>0; ) {
+          for (longT to_read = (longT)size(); to_read>0; ) {
             raw.assign(cimg::min(to_read,cimg_iobuffer/2));
             cimg::fread(raw._data,raw._width,nfile);
             if (!cimg::endianness()) cimg::invert_endianness(raw._data,raw._width);
             to_read-=raw._width;
             const unsigned short *ptrs = raw._data;
-            for (unsigned long off = (unsigned long)raw._width/3; off; --off) {
+            for (ulongT off = (ulongT)raw._width/3; off; --off) {
               *(ptr_r++) = (T)*(ptrs++);
               *(ptr_g++) = (T)*(ptrs++);
               *(ptr_b++) = (T)*(ptrs++);
@@ -40234,24 +45045,24 @@ namespace cimg_library_suffixed {
         CImg<intT> raw;
         assign(W,H,D,1);
         T *ptrd = data(0,0,0,0);
-        for (long to_read = (long)size(); to_read>0; ) {
+        for (longT to_read = (longT)size(); to_read>0; ) {
           raw.assign(cimg::min(to_read,cimg_iobuffer));
           cimg::fread(raw._data,raw._width,nfile);
           to_read-=raw._width;
           const int *ptrs = raw._data;
-          for (unsigned long off = (unsigned long)raw._width; off; --off) *(ptrd++) = (T)*(ptrs++);
+          for (ulongT off = (ulongT)raw._width; off; --off) *(ptrd++) = (T)*(ptrs++);
         }
       } break;
       case 9 : { // 2d/3d grey binary with float values (PINK extension).
         CImg<floatT> raw;
         assign(W,H,D,1);
         T *ptrd = data(0,0,0,0);
-        for (long to_read = (long)size(); to_read>0; ) {
+        for (longT to_read = (longT)size(); to_read>0; ) {
           raw.assign(cimg::min(to_read,cimg_iobuffer));
           cimg::fread(raw._data,raw._width,nfile);
           to_read-=raw._width;
           const float *ptrs = raw._data;
-          for (unsigned long off = (unsigned long)raw._width; off; --off) *(ptrd++) = (T)*(ptrs++);
+          for (ulongT off = (ulongT)raw._width; off; --off) *(ptrd++) = (T)*(ptrs++);
         }
       } break;
       default :
@@ -40388,7 +45199,7 @@ namespace cimg_library_suffixed {
                                     cimg_instance);
 
       if (!dimw || !dimh) return assign();
-      const long cimg_iobuffer = 24*1024*1024;
+      const longT cimg_iobuffer = (longT)24*1024*1024;
       std::FILE *const nfile = file?file:cimg::fopen(filename,"rb");
       CImg<ucharT> raw;
       assign(dimw,dimh,1,3);
@@ -40396,12 +45207,12 @@ namespace cimg_library_suffixed {
         *ptr_r = data(0,0,0,0),
         *ptr_g = data(0,0,0,1),
         *ptr_b = data(0,0,0,2);
-      for (long to_read = (long)size(); to_read>0; ) {
+      for (longT to_read = (longT)size(); to_read>0; ) {
         raw.assign(cimg::min(to_read,cimg_iobuffer));
         cimg::fread(raw._data,raw._width,nfile);
         to_read-=raw._width;
         const unsigned char *ptrs = raw._data;
-        for (unsigned long off = raw._width/3UL; off; --off) {
+        for (ulongT off = raw._width/3UL; off; --off) {
           *(ptr_r++) = (T)*(ptrs++);
           *(ptr_g++) = (T)*(ptrs++);
           *(ptr_b++) = (T)*(ptrs++);
@@ -40444,7 +45255,7 @@ namespace cimg_library_suffixed {
                                     cimg_instance);
 
       if (!dimw || !dimh) return assign();
-      const long cimg_iobuffer = 24*1024*1024;
+      const longT cimg_iobuffer = (longT)24*1024*1024;
       std::FILE *const nfile = file?file:cimg::fopen(filename,"rb");
       CImg<ucharT> raw;
       assign(dimw,dimh,1,4);
@@ -40453,12 +45264,12 @@ namespace cimg_library_suffixed {
         *ptr_g = data(0,0,0,1),
         *ptr_b = data(0,0,0,2),
         *ptr_a = data(0,0,0,3);
-      for (long to_read = (long)size(); to_read>0; ) {
+      for (longT to_read = (longT)size(); to_read>0; ) {
         raw.assign(cimg::min(to_read,cimg_iobuffer));
         cimg::fread(raw._data,raw._width,nfile);
         to_read-=raw._width;
         const unsigned char *ptrs = raw._data;
-        for (unsigned long off = raw._width/4UL; off; --off) {
+        for (ulongT off = raw._width/4UL; off; --off) {
           *(ptr_r++) = (T)*(ptrs++);
           *(ptr_g++) = (T)*(ptrs++);
           *(ptr_b++) = (T)*(ptrs++);
@@ -40481,7 +45292,7 @@ namespace cimg_library_suffixed {
        - When libtiff is enabled, 2D and 3D (multipage) several
         channel per pixel are supported for
         <tt>char,uchar,short,ushort,float</tt> and \c double pixel types.
-       - If \c cimg_use_tif is not defined at compilation time the
+       - If \c cimg_use_tif is not defined at compile time the
         function uses CImg<T>& load_other(const char*).
      **/
     CImg<T>& load_tiff(const char *const filename,
@@ -40687,10 +45498,13 @@ namespace cimg_library_suffixed {
         if (TIFFGetField(tif,TIFFTAG_IMAGEDESCRIPTION,&s_description) && s_description)
           CImg<charT>::string(s_description).move_to(*description);
       }
-      const unsigned int spectrum = is_spp?samplesperpixel:photo==3?3:1;
+      const unsigned int spectrum = !is_spp || photo>=3?(photo>1?3:1):samplesperpixel;
       assign(nx,ny,1,spectrum);
 
-      if (photo>=3 && sampleformat==1 && bitspersample==8 && (samplesperpixel==3 || samplesperpixel==4)) {
+      if ((photo>=3 && sampleformat==1 &&
+           (bitspersample==4 || bitspersample==8) &&
+           (samplesperpixel==1 || samplesperpixel==3 || samplesperpixel==4)) ||
+          (bitspersample==1 && samplesperpixel==1)) {
         // Special case for unsigned color images.
         uint32 *const raster = (uint32*)_TIFFmalloc(nx*ny*sizeof(uint32));
         if (!raster) {
@@ -40702,24 +45516,25 @@ namespace cimg_library_suffixed {
         }
         TIFFReadRGBAImage(tif,nx,ny,raster,0);
         switch (spectrum) {
-        case 1 : {
-          cimg_forXY(*this,x,y) (*this)(x,y) = (T)(float)((raster[nx*(ny - 1 - y) + x] + 128)/257);
-        } break;
-        case 3 : {
+        case 1 :
+          cimg_forXY(*this,x,y)
+            (*this)(x,y,0) = (T)(float)TIFFGetR(raster[nx*(ny - 1 -y) + x]);
+          break;
+        case 3 :
           cimg_forXY(*this,x,y) {
             (*this)(x,y,0) = (T)(float)TIFFGetR(raster[nx*(ny - 1 -y) + x]);
             (*this)(x,y,1) = (T)(float)TIFFGetG(raster[nx*(ny - 1 -y) + x]);
             (*this)(x,y,2) = (T)(float)TIFFGetB(raster[nx*(ny - 1 -y) + x]);
           }
-        } break;
-        case 4 : {
+          break;
+        case 4 :
           cimg_forXY(*this,x,y) {
             (*this)(x,y,0) = (T)(float)TIFFGetR(raster[nx*(ny - 1 - y) + x]);
             (*this)(x,y,1) = (T)(float)TIFFGetG(raster[nx*(ny - 1 - y) + x]);
             (*this)(x,y,2) = (T)(float)TIFFGetB(raster[nx*(ny - 1 - y) + x]);
             (*this)(x,y,3) = (T)(float)TIFFGetA(raster[nx*(ny - 1 - y) + x]);
           }
-        } break;
+          break;
         }
         _TIFFfree(raster);
       } else { // Other cases.
@@ -40896,7 +45711,7 @@ namespace cimg_library_suffixed {
       cimg::fread(&header_size,1,nfile_header);
       if (!header_size)
         throw CImgIOException(_cimg_instance
-                              "load_analyze(): Invalid zero-sized header in file '%s'.",
+                              "load_analyze(): Invalid zero-size header in file '%s'.",
                               cimg_instance,
                               filename?filename:"(FILE*)");
 
@@ -40940,34 +45755,34 @@ namespace cimg_library_suffixed {
       assign(dimx,dimy,dimz,dimv);
       switch (datatype) {
       case 2 : {
-        unsigned char *const buffer = new unsigned char[(unsigned int)dimx*dimy*dimz*dimv];
+        unsigned char *const buffer = new unsigned char[(size_t)dimx*dimy*dimz*dimv];
         cimg::fread(buffer,dimx*dimy*dimz*dimv,nfile);
         cimg_foroff(*this,off) _data[off] = (T)(buffer[off]*scalefactor);
         delete[] buffer;
       } break;
       case 4 : {
-        short *const buffer = new short[(unsigned int)dimx*dimy*dimz*dimv];
+        short *const buffer = new short[(size_t)dimx*dimy*dimz*dimv];
         cimg::fread(buffer,dimx*dimy*dimz*dimv,nfile);
         if (endian) cimg::invert_endianness(buffer,dimx*dimy*dimz*dimv);
         cimg_foroff(*this,off) _data[off] = (T)(buffer[off]*scalefactor);
         delete[] buffer;
       } break;
       case 8 : {
-        int *const buffer = new int[(unsigned int)dimx*dimy*dimz*dimv];
+        int *const buffer = new int[(size_t)dimx*dimy*dimz*dimv];
         cimg::fread(buffer,dimx*dimy*dimz*dimv,nfile);
         if (endian) cimg::invert_endianness(buffer,dimx*dimy*dimz*dimv);
         cimg_foroff(*this,off) _data[off] = (T)(buffer[off]*scalefactor);
         delete[] buffer;
       } break;
       case 16 : {
-        float *const buffer = new float[(unsigned int)dimx*dimy*dimz*dimv];
+        float *const buffer = new float[(size_t)dimx*dimy*dimz*dimv];
         cimg::fread(buffer,dimx*dimy*dimz*dimv,nfile);
         if (endian) cimg::invert_endianness(buffer,dimx*dimy*dimz*dimv);
         cimg_foroff(*this,off) _data[off] = (T)(buffer[off]*scalefactor);
         delete[] buffer;
       } break;
       case 64 : {
-        double *const buffer = new double[(unsigned int)dimx*dimy*dimz*dimv];
+        double *const buffer = new double[(size_t)dimx*dimy*dimz*dimv];
         cimg::fread(buffer,dimx*dimy*dimz*dimv,nfile);
         if (endian) cimg::invert_endianness(buffer,dimx*dimy*dimz*dimv);
         cimg_foroff(*this,off) _data[off] = (T)(buffer[off]*scalefactor);
@@ -41105,8 +45920,8 @@ namespace cimg_library_suffixed {
     }
 
     static void _load_inr_header(std::FILE *file, int out[8], float *const voxel_size) {
-      CImg<charT> item(1024); *item = 0;
-      char tmp1[64] = { 0 }, tmp2[64] = { 0 };
+      CImg<charT> item(1024), tmp1(64), tmp2(64);
+      *item = *tmp1 = *tmp2 = 0;
       out[0] = std::fscanf(file,"%63s",item._data);
       out[0] = out[1] = out[2] = out[3] = out[5] = 1; out[4] = out[6] = out[7] = -1;
       if(cimg::strncasecmp(item,"#INRIMAGE-4#{",13)!=0)
@@ -41124,19 +45939,19 @@ namespace cimg_library_suffixed {
           cimg_sscanf(item," VY%*[^0-9.+-]%f",voxel_size + 1);
           cimg_sscanf(item," VZ%*[^0-9.+-]%f",voxel_size + 2);
         }
-        if (cimg_sscanf(item," CPU%*[ =]%s",tmp1)) out[7]=cimg::strncasecmp(tmp1,"sun",3)?0:1;
-        switch (cimg_sscanf(item," TYPE%*[ =]%s %s",tmp1,tmp2)) {
+        if (cimg_sscanf(item," CPU%*[ =]%s",tmp1._data)) out[7] = cimg::strncasecmp(tmp1,"sun",3)?0:1;
+        switch (cimg_sscanf(item," TYPE%*[ =]%s %s",tmp1._data,tmp2._data)) {
         case 0 : break;
-        case 2 : out[5] = cimg::strncasecmp(tmp1,"unsigned",8)?1:0; std::strncpy(tmp1,tmp2,sizeof(tmp1) - 1);
+        case 2 : out[5] = cimg::strncasecmp(tmp1,"unsigned",8)?1:0; std::strncpy(tmp1,tmp2,tmp1._width - 1);
         case 1 :
-          if (!cimg::strncasecmp(tmp1,"int",3)   || !cimg::strncasecmp(tmp1,"fixed",5))  out[4] = 0;
+          if (!cimg::strncasecmp(tmp1,"int",3) || !cimg::strncasecmp(tmp1,"fixed",5))  out[4] = 0;
           if (!cimg::strncasecmp(tmp1,"float",5) || !cimg::strncasecmp(tmp1,"double",6)) out[4] = 1;
-          if (!cimg::strncasecmp(tmp1,"packed",6))                                       out[4] = 2;
+          if (!cimg::strncasecmp(tmp1,"packed",6)) out[4] = 2;
           if (out[4]>=0) break;
         default :
           throw CImgIOException("CImg<%s>::load_inr(): Invalid pixel type '%s' defined in header.",
                                 pixel_type(),
-                                tmp2);
+                                tmp2._data);
         }
       }
       if(out[0]<0 || out[1]<0 || out[2]<0 || out[3]<0)
@@ -41157,7 +45972,7 @@ namespace cimg_library_suffixed {
     CImg<T>& _load_inr(std::FILE *const file, const char *const filename, float *const voxel_size) {
 #define _cimg_load_inr_case(Tf,sign,pixsize,Ts) \
      if (!loaded && fopt[6]==pixsize && fopt[4]==Tf && fopt[5]==sign) { \
-        Ts *xval, *const val = new Ts[(unsigned int)fopt[0]*fopt[3]]; \
+        Ts *xval, *const val = new Ts[(size_t)fopt[0]*fopt[3]]; \
         cimg_forYZ(*this,y,z) { \
             cimg::fread(val,fopt[0]*fopt[3],nfile); \
             if (fopt[7]!=endian) cimg::invert_endianness(val,fopt[0]*fopt[3]); \
@@ -41266,7 +46081,7 @@ namespace cimg_library_suffixed {
         cimg::fread(dims,nbdim,nfile); \
         if (endian) cimg::invert_endianness(dims,nbdim); \
         assign(nwidth,nheight,ndepth,ndim); \
-        const unsigned int siz = size(); \
+        const size_t siz = size(); \
         stype *buffer = new stype[siz]; \
         cimg::fread(buffer,siz,nfile); \
         if (endian) cimg::invert_endianness(buffer,siz); \
@@ -41290,8 +46105,8 @@ namespace cimg_library_suffixed {
                                     cimg_instance);
 
       std::FILE *const nfile = file?file:cimg::fopen(filename,"rb");
-      char header[32] = { 0 };
-      cimg::fread(header,12,nfile);
+      CImg<charT> header(32);
+      cimg::fread(header._data,12,nfile);
       if (cimg::strncasecmp("PANDORE",header,7)) {
         if (!file) cimg::fclose(nfile);
         throw CImgIOException(_cimg_instance
@@ -41300,10 +46115,11 @@ namespace cimg_library_suffixed {
                               filename?filename:"(FILE*)");
       }
       unsigned int imageid, dims[8] = { 0 };
+      int ptbuf[4] = { 0 };
       cimg::fread(&imageid,1,nfile);
       const bool endian = imageid>255;
       if (endian) cimg::invert_endianness(imageid);
-      cimg::fread(header,20,nfile);
+      cimg::fread(header._data,20,nfile);
 
       switch (imageid) {
       case 2 : _cimg_load_pandore_case(2,dims[1],1,1,1,unsigned char,unsigned char,unsigned char,1); break;
@@ -41352,7 +46168,7 @@ namespace cimg_library_suffixed {
         cimg::fread(dims,4,nfile);
         if (endian) cimg::invert_endianness(dims,4);
         assign(dims[2],dims[1],1,1);
-        const unsigned int siz = size();
+        const size_t siz = size();
         if (dims[3]<256) {
           unsigned char *buffer = new unsigned char[siz];
           cimg::fread(buffer,siz,nfile);
@@ -41370,7 +46186,7 @@ namespace cimg_library_suffixed {
             buffer-=siz;
             delete[] buffer;
           } else {
-            unsigned long *buffer = new unsigned long[siz];
+            unsigned int *buffer = new unsigned int[siz];
             cimg::fread(buffer,siz,nfile);
             if (endian) cimg::invert_endianness(buffer,siz);
             T *ptrd = _data;
@@ -41385,7 +46201,7 @@ namespace cimg_library_suffixed {
         cimg::fread(dims,5,nfile);
         if (endian) cimg::invert_endianness(dims,5);
         assign(dims[3],dims[2],dims[1],1);
-        const unsigned int siz = size();
+        const size_t siz = size();
         if (dims[4]<256) {
           unsigned char *buffer = new unsigned char[siz];
           cimg::fread(buffer,siz,nfile);
@@ -41435,19 +46251,16 @@ namespace cimg_library_suffixed {
         break;
       case 33 : _cimg_load_pandore_case(4,dims[3],dims[2],dims[1],dims[0],double,float,float,4); break;
       case 34 : { // Points 1d
-        int ptbuf[4] = { 0 };
         cimg::fread(ptbuf,1,nfile);
         if (endian) cimg::invert_endianness(ptbuf,1);
         assign(1); (*this)(0) = (T)ptbuf[0];
       } break;
       case 35 : { // Points 2d
-        int ptbuf[4] = { 0 };
         cimg::fread(ptbuf,2,nfile);
         if (endian) cimg::invert_endianness(ptbuf,2);
         assign(2); (*this)(0) = (T)ptbuf[1]; (*this)(1) = (T)ptbuf[0];
       } break;
       case 36 : { // Points 3d
-        int ptbuf[4] = { 0 };
         cimg::fread(ptbuf,3,nfile);
         if (endian) cimg::invert_endianness(ptbuf,3);
         assign(3); (*this)(0) = (T)ptbuf[2]; (*this)(1) = (T)ptbuf[1]; (*this)(2) = (T)ptbuf[0];
@@ -41496,7 +46309,7 @@ namespace cimg_library_suffixed {
                       const unsigned int size_x=0, const unsigned int size_y=1,
                       const unsigned int size_z=1, const unsigned int size_c=1,
                       const bool is_multiplexed=false, const bool invert_endianness=false,
-                      const unsigned long offset=0) {
+                      const ulongT offset=0) {
       return _load_raw(0,filename,size_x,size_y,size_z,size_c,is_multiplexed,invert_endianness,offset);
     }
 
@@ -41505,7 +46318,7 @@ namespace cimg_library_suffixed {
                                 const unsigned int size_x=0, const unsigned int size_y=1,
                                 const unsigned int size_z=1, const unsigned int size_c=1,
                                 const bool is_multiplexed=false, const bool invert_endianness=false,
-                                const unsigned long offset=0) {
+                                const ulongT offset=0) {
       return CImg<T>().load_raw(filename,size_x,size_y,size_z,size_c,is_multiplexed,invert_endianness,offset);
     }
 
@@ -41514,7 +46327,7 @@ namespace cimg_library_suffixed {
                       const unsigned int size_x=0, const unsigned int size_y=1,
                       const unsigned int size_z=1, const unsigned int size_c=1,
                       const bool is_multiplexed=false, const bool invert_endianness=false,
-                      const unsigned long offset=0) {
+                      const ulongT offset=0) {
       return _load_raw(file,0,size_x,size_y,size_z,size_c,is_multiplexed,invert_endianness,offset);
     }
 
@@ -41523,7 +46336,7 @@ namespace cimg_library_suffixed {
                                 const unsigned int size_x=0, const unsigned int size_y=1,
                                 const unsigned int size_z=1, const unsigned int size_c=1,
                                 const bool is_multiplexed=false, const bool invert_endianness=false,
-                                const unsigned long offset=0) {
+                                const ulongT offset=0) {
       return CImg<T>().load_raw(file,size_x,size_y,size_z,size_c,is_multiplexed,invert_endianness,offset);
     }
 
@@ -41531,7 +46344,7 @@ namespace cimg_library_suffixed {
 		       const unsigned int size_x, const unsigned int size_y,
 		       const unsigned int size_z, const unsigned int size_c,
 		       const bool is_multiplexed, const bool invert_endianness,
-                       const unsigned long offset) {
+                       const ulongT offset) {
       if (!file && !filename)
         throw CImgArgumentException(_cimg_instance
                                     "load_raw(): Specified filename is (null).",
@@ -41541,20 +46354,25 @@ namespace cimg_library_suffixed {
                                     "load_raw(): Specified filename '%s' is a directory.",
                                     cimg_instance,filename);
 
-      unsigned int siz = size_x*size_y*size_z*size_c,
-        _size_x = size_x, _size_y = size_y, _size_z = size_z, _size_c = size_c;
+      ulongT siz = (ulongT)size_x*size_y*size_z*size_c;
+      unsigned int
+        _size_x = size_x,
+        _size_y = size_y,
+        _size_z = size_z,
+        _size_c = size_c;
       std::FILE *const nfile = file?file:cimg::fopen(filename,"rb");
       if (!siz) {  // Retrieve file size.
-        const long fpos = std::ftell(nfile);
+        const longT fpos = cimg::ftell(nfile);
         if (fpos<0) throw CImgArgumentException(_cimg_instance
                                                 "load_raw(): Cannot determine size of input file '%s'.",
                                                 cimg_instance,filename?filename:"(FILE*)");
-        std::fseek(nfile,0,SEEK_END);
-        siz = _size_y = (unsigned int)std::ftell(nfile)/sizeof(T);
+        cimg::fseek(nfile,0,SEEK_END);
+        siz = cimg::ftell(nfile)/sizeof(T);
+		_size_y = (unsigned int)siz;
         _size_x = _size_z = _size_c = 1;
-        std::fseek(nfile,fpos,SEEK_SET);
+        cimg::fseek(nfile,fpos,SEEK_SET);
       }
-      std::fseek(nfile,(long)offset,SEEK_SET);
+      cimg::fseek(nfile,offset,SEEK_SET);
       assign(_size_x,_size_y,_size_z,_size_c,0);
       if (siz && (!is_multiplexed || size_c==1)) {
         cimg::fread(_data,siz,nfile);
@@ -42238,7 +47056,7 @@ namespace cimg_library_suffixed {
         if (step>0) cimg_forY(*this,y) {
             cimg_forX(*this,x) { *(ptr_b++) = (T)*(ptrs++); *(ptr_g++) = (T)*(ptrs++); *(ptr_r++) = (T)*(ptrs++); }
             ptrs+=step;
-          } else for (unsigned long siz = (unsigned long)img->width*img->height; siz; --siz) {
+          } else for (ulongT siz = (ulongT)img->width*img->height; siz; --siz) {
             *(ptr_b++) = (T)*(ptrs++); *(ptr_g++) = (T)*(ptrs++); *(ptr_r++) = (T)*(ptrs++);
           }
       }
@@ -42327,14 +47145,14 @@ namespace cimg_library_suffixed {
         xm = (int)st[4]; ym = (int)st[5], zm = (int)st[6], vm = (int)st[7];
         xM = (int)st[8]; yM = (int)st[9], zM = (int)st[10], vM = (int)st[11];
       }
-      const unsigned long siz = size(), msiz = siz*sizeof(T), siz1 = siz - 1,
+      const ulongT siz = size(), msiz = siz*sizeof(T), siz1 = siz - 1,
         mdisp = msiz<8*1024?0U:msiz<8*1024*1024?1U:2U, width1 = _width - 1;
 
-      char _title[64] = { 0 };
-      if (!title) cimg_snprintf(_title,sizeof(_title),"CImg<%s>",pixel_type());
+      CImg<charT> _title(64);
+      if (!title) cimg_snprintf(_title,_title._width,"CImg<%s>",pixel_type());
 
       std::fprintf(cimg::output(),"%s%s%s%s: %sthis%s = %p, %ssize%s = (%u,%u,%u,%u) [%lu %s], %sdata%s = (%s*)%p",
-                   cimg::t_magenta,cimg::t_bold,title?title:_title,cimg::t_normal,
+                   cimg::t_magenta,cimg::t_bold,title?title:_title._data,cimg::t_normal,
                    cimg::t_bold,cimg::t_normal,(void*)this,
                    cimg::t_bold,cimg::t_normal,_width,_height,_depth,_spectrum,
                    mdisp==0?msiz:(mdisp==1?(msiz>>10):(msiz>>20)),
@@ -42378,8 +47196,9 @@ namespace cimg_library_suffixed {
         \param disp Display window.
         \param display_info Tells if image information are displayed on the standard output.
     **/
-    const CImg<T>& display(CImgDisplay &disp, const bool display_info, unsigned int *const XYZ=0) const {
-      return _display(disp,0,display_info,XYZ,false);
+    const CImg<T>& display(CImgDisplay &disp, const bool display_info, unsigned int *const XYZ=0,
+                           const bool exit_on_anykey=false) const {
+      return _display(disp,0,display_info,XYZ,exit_on_anykey,false);
     }
 
     //! Display image into an interactive window.
@@ -42387,16 +47206,18 @@ namespace cimg_library_suffixed {
         \param title Window title
         \param display_info Tells if image information are displayed on the standard output.
     **/
-    const CImg<T>& display(const char *const title=0, const bool display_info=true, unsigned int *const XYZ=0) const {
+    const CImg<T>& display(const char *const title=0, const bool display_info=true, unsigned int *const XYZ=0,
+                           const bool exit_on_anykey=false) const {
       CImgDisplay disp;
-      return _display(disp,title,display_info,XYZ,false);
+      return _display(disp,title,display_info,XYZ,exit_on_anykey,false);
     }
 
-    const CImg<T>& _display(CImgDisplay &disp, const char *const title,
-                            const bool display_info, unsigned int *const XYZ,
+    const CImg<T>& _display(CImgDisplay &disp, const char *const title, const bool display_info,
+                            unsigned int *const XYZ, const bool exit_on_anykey,
                             const bool exit_on_simpleclick) const {
       unsigned int oldw = 0, oldh = 0, _XYZ[3] = { 0 }, key = 0;
-      int x0 = 0, y0 = 0, z0 = 0, x1 = width() - 1, y1 = height() - 1, z1 = depth() - 1;
+      int x0 = 0, y0 = 0, z0 = 0, x1 = width() - 1, y1 = height() - 1, z1 = depth() - 1,
+        old_mouse_x = -1, old_mouse_y = -1;
 
       if (!disp) {
         disp.assign(cimg_fitscreen(_width,_height,_depth),title?title:0,1);
@@ -42454,14 +47275,21 @@ namespace cimg_library_suffixed {
           _XYZ[1] = (unsigned int)(y1 - y0)/2;
           _XYZ[2] = (unsigned int)(z1 - z0)/2;
         }
-        const CImg<intT> selection = visu._get_select(disp,0,2,_XYZ,x0,y0,z0,is_first_select,_depth>1);
+
+        disp._mouse_x = old_mouse_x; disp._mouse_y = old_mouse_y;
+        const CImg<intT> selection = visu._get_select(disp,0,2,_XYZ,x0,y0,z0,true,is_first_select,_depth>1);
+        old_mouse_x = disp._mouse_x; old_mouse_y = disp._mouse_y;
         is_first_select = false;
 
         if (disp.wheel()) {
           if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
+            go_down = !(go_up = disp.wheel()>0);
+          } else if (disp.is_keySHIFTLEFT() || disp.is_keySHIFTRIGHT()) {
+            go_left = !(go_right = disp.wheel()>0);
+          }
+          else if (disp.is_keyALT() || disp.is_keyALTGR() || _depth==1) {
             go_out = !(go_in = disp.wheel()>0); go_in_center = false;
-          } else if (disp.is_keySHIFTLEFT() || disp.is_keySHIFTRIGHT()) { go_left = !(go_right = disp.wheel()>0); }
-          else if (disp.is_keyALT() || disp.is_keyALTGR() || _depth==1) { go_down = !(go_up = disp.wheel()>0); }
+          }
           disp.set_wheel();
         }
 
@@ -42619,6 +47447,10 @@ namespace cimg_library_suffixed {
           else { z0+=(depth() - 1 - z1); z1 = depth() - 1; }
         }
         disp.wait(100);
+        if (!exit_on_anykey && key && key!=cimg::keyESC &&
+            (key!=cimg::keyW || (!disp.is_keyCTRLLEFT() && !disp.is_keyCTRLRIGHT()))) {
+          key = 0;
+        }
       }
       disp.set_key(key);
       if (XYZ) { XYZ[0] = _XYZ[0]; XYZ[1] = _XYZ[1]; XYZ[2] = _XYZ[2]; }
@@ -42656,11 +47488,12 @@ namespace cimg_library_suffixed {
                                     const bool is_double_sided=true, const float focale=700,
                                     const float light_x=0, const float light_y=0, const float light_z=-5e8f,
                                     const float specular_lightness=0.2f, const float specular_shininess=0.1f,
-                                    const bool display_axes=true, float *const pose_matrix=0) const {
+                                    const bool display_axes=true, float *const pose_matrix=0,
+                                    const bool exit_on_anykey=false) const {
       return _display_object3d(disp,0,vertices,primitives,colors,opacities,centering,render_static,
 			       render_motion,is_double_sided,focale,
                                light_x,light_y,light_z,specular_lightness,specular_shininess,
-			       display_axes,pose_matrix);
+			       display_axes,pose_matrix,exit_on_anykey);
     }
 
     //! Display object 3d in an interactive window \simplification.
@@ -42675,12 +47508,13 @@ namespace cimg_library_suffixed {
                                     const bool is_double_sided=true, const float focale=700,
                                     const float light_x=0, const float light_y=0, const float light_z=-5e8f,
                                     const float specular_lightness=0.2f, const float specular_shininess=0.1f,
-                                    const bool display_axes=true, float *const pose_matrix=0) const {
+                                    const bool display_axes=true, float *const pose_matrix=0,
+                                    const bool exit_on_anykey=false) const {
       CImgDisplay disp;
       return _display_object3d(disp,title,vertices,primitives,colors,opacities,centering,render_static,
 			       render_motion,is_double_sided,focale,
                                light_x,light_y,light_z,specular_lightness,specular_shininess,
-			       display_axes,pose_matrix);
+			       display_axes,pose_matrix,exit_on_anykey);
     }
 
     //! Display object 3d in an interactive window \simplification.
@@ -42694,11 +47528,12 @@ namespace cimg_library_suffixed {
                                     const bool is_double_sided=true, const float focale=700,
                                     const float light_x=0, const float light_y=0, const float light_z=-5e8f,
                                     const float specular_lightness=0.2f, const float specular_shininess=0.1f,
-                                    const bool display_axes=true, float *const pose_matrix=0) const {
+                                    const bool display_axes=true, float *const pose_matrix=0,
+                                    const bool exit_on_anykey=false) const {
       return display_object3d(disp,vertices,primitives,colors,CImgList<floatT>(),centering,
 			      render_static,render_motion,is_double_sided,focale,
                               light_x,light_y,light_z,specular_lightness,specular_shininess,
-			      display_axes,pose_matrix);
+			      display_axes,pose_matrix,exit_on_anykey);
     }
 
     //! Display object 3d in an interactive window \simplification.
@@ -42712,11 +47547,12 @@ namespace cimg_library_suffixed {
                                     const bool is_double_sided=true, const float focale=700,
                                     const float light_x=0, const float light_y=0, const float light_z=-5e8f,
                                     const float specular_lightness=0.2f, const float specular_shininess=0.1f,
-                                    const bool display_axes=true, float *const pose_matrix=0) const {
+                                    const bool display_axes=true, float *const pose_matrix=0,
+                                    const bool exit_on_anykey=false) const {
       return display_object3d(title,vertices,primitives,colors,CImgList<floatT>(),centering,
                               render_static,render_motion,is_double_sided,focale,
                               light_x,light_y,light_z,specular_lightness,specular_shininess,
-                              display_axes,pose_matrix);
+                              display_axes,pose_matrix,exit_on_anykey);
     }
 
     //! Display object 3d in an interactive window \simplification.
@@ -42729,11 +47565,12 @@ namespace cimg_library_suffixed {
                                     const bool is_double_sided=true, const float focale=700,
                                     const float light_x=0, const float light_y=0, const float light_z=-5e8f,
                                     const float specular_lightness=0.2f, const float specular_shininess=0.1f,
-                                    const bool display_axes=true, float *const pose_matrix=0) const {
+                                    const bool display_axes=true, float *const pose_matrix=0,
+                                    const bool exit_on_anykey=false) const {
       return display_object3d(disp,vertices,primitives,CImgList<T>(),centering,
                               render_static,render_motion,is_double_sided,focale,
                               light_x,light_y,light_z,specular_lightness,specular_shininess,
-                              display_axes,pose_matrix);
+                              display_axes,pose_matrix,exit_on_anykey);
     }
 
 
@@ -42747,11 +47584,12 @@ namespace cimg_library_suffixed {
                                     const bool is_double_sided=true, const float focale=700,
                                     const float light_x=0, const float light_y=0, const float light_z=-5e8f,
                                     const float specular_lightness=0.2f, const float specular_shininess=0.1f,
-                                    const bool display_axes=true, float *const pose_matrix=0) const {
+                                    const bool display_axes=true, float *const pose_matrix=0,
+                                    const bool exit_on_anykey=false) const {
       return display_object3d(title,vertices,primitives,CImgList<T>(),centering,
                               render_static,render_motion,is_double_sided,focale,
                               light_x,light_y,light_z,specular_lightness,specular_shininess,
-                              display_axes,pose_matrix);
+                              display_axes,pose_matrix,exit_on_anykey);
     }
 
     //! Display object 3d in an interactive window \simplification.
@@ -42763,11 +47601,12 @@ namespace cimg_library_suffixed {
                                     const bool is_double_sided=true, const float focale=700,
                                     const float light_x=0, const float light_y=0, const float light_z=-5e8f,
                                     const float specular_lightness=0.2f, const float specular_shininess=0.1f,
-                                    const bool display_axes=true, float *const pose_matrix=0) const {
+                                    const bool display_axes=true, float *const pose_matrix=0,
+                                    const bool exit_on_anykey=false) const {
       return display_object3d(disp,vertices,CImgList<uintT>(),centering,
                               render_static,render_motion,is_double_sided,focale,
                               light_x,light_y,light_z,specular_lightness,specular_shininess,
-                              display_axes,pose_matrix);
+                              display_axes,pose_matrix,exit_on_anykey);
     }
 
     //! Display object 3d in an interactive window \simplification.
@@ -42779,11 +47618,12 @@ namespace cimg_library_suffixed {
                                     const bool is_double_sided=true, const float focale=700,
                                     const float light_x=0, const float light_y=0, const float light_z=-5e8f,
                                     const float specular_lightness=0.2f, const float specular_shininess=0.1f,
-                                    const bool display_axes=true, float *const pose_matrix=0) const {
+                                    const bool display_axes=true, float *const pose_matrix=0,
+                                    const bool exit_on_anykey=false) const {
       return display_object3d(title,vertices,CImgList<uintT>(),centering,
                               render_static,render_motion,is_double_sided,focale,
                               light_x,light_y,light_z,specular_lightness,specular_shininess,
-                              display_axes,pose_matrix);
+                              display_axes,pose_matrix,exit_on_anykey);
     }
 
     template<typename tp, typename tf, typename tc, typename to>
@@ -42797,7 +47637,8 @@ namespace cimg_library_suffixed {
 				     const bool is_double_sided, const float focale,
                                      const float light_x, const float light_y, const float light_z,
 				     const float specular_lightness, const float specular_shininess,
-				     const bool display_axes, float *const pose_matrix) const {
+				     const bool display_axes, float *const pose_matrix,
+                                     const bool exit_on_anykey) const {
       typedef typename cimg::superset<tp,float>::type tpfloat;
 
       // Check input arguments
@@ -42806,14 +47647,14 @@ namespace cimg_library_suffixed {
 		    _display_object3d(disp,title,vertices,primitives,colors,opacities,centering,
                                       render_static,render_motion,is_double_sided,focale,
                                       light_x,light_y,light_z,specular_lightness,specular_shininess,
-                                      display_axes,pose_matrix);
+                                      display_axes,pose_matrix,exit_on_anykey);
 	else return CImg<T>(1,2,1,1,64,128).resize(cimg_fitscreen(CImgDisplay::screen_width()/2,
                                                                   CImgDisplay::screen_height()/2,1),
                                                    1,(colors && colors[0].size()==1)?1:3,3).
                _display_object3d(disp,title,vertices,primitives,colors,opacities,centering,
 				 render_static,render_motion,is_double_sided,focale,
                                  light_x,light_y,light_z,specular_lightness,specular_shininess,
-				 display_axes,pose_matrix);
+				 display_axes,pose_matrix,exit_on_anykey);
       } else { if (disp) disp.resize(*this,false); }
       CImg<charT> error_message(1024);
       if (!vertices.is_object3d(primitives,colors,opacities,true,error_message))
@@ -42826,7 +47667,7 @@ namespace cimg_library_suffixed {
         return _display_object3d(disp,title,vertices,nprimitives,colors,opacities,centering,
 				 render_static,render_motion,is_double_sided,focale,
                                  light_x,light_y,light_z,specular_lightness,specular_shininess,
-				 display_axes,pose_matrix);
+				 display_axes,pose_matrix,exit_on_anykey);
       }
       if (!disp) {
 	disp.assign(cimg_fitscreen(_width,_height,_depth),title?title:0,3);
@@ -43027,6 +47868,7 @@ namespace cimg_library_suffixed {
           }
         } else if (clicked) { x0 = x1; y0 = y1; clicked = false; redraw = true; }
 
+        CImg<charT> filename(32);
         switch (key = disp.key()) {
 #if cimg_OS!=2
         case cimg::keyCTRLRIGHT :
@@ -43105,43 +47947,40 @@ namespace cimg_library_suffixed {
           } break;
         case cimg::keyS : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Save snapshot
             static unsigned int snap_number = 0;
-            char filename[32] = { 0 };
             std::FILE *file;
             do {
-              cimg_snprintf(filename,sizeof(filename),cimg_appname "_%.4u.bmp",snap_number++);
+              cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.bmp",snap_number++);
               if ((file=std::fopen(filename,"r"))!=0) cimg::fclose(file);
             } while (file);
             (+visu).draw_text(0,0," Saving snapshot... ",
                               foreground_color._data,background_color._data,0.7f,13).display(disp);
             visu.save(filename);
             (+visu).draw_text(0,0," Snapshot '%s' saved. ",
-                              foreground_color._data,background_color._data,0.7f,13,filename).display(disp);
+                              foreground_color._data,background_color._data,0.7f,13,filename._data).display(disp);
             disp.set_key(key,false); key = 0;
           } break;
         case cimg::keyG : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Save object as a .off file
             static unsigned int snap_number = 0;
-            char filename[32] = { 0 };
             std::FILE *file;
             do {
-              cimg_snprintf(filename,sizeof(filename),cimg_appname "_%.4u.off",snap_number++);
+              cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.off",snap_number++);
               if ((file=std::fopen(filename,"r"))!=0) cimg::fclose(file);
             } while (file);
             (+visu).draw_text(0,0," Saving object... ",
                               foreground_color._data,background_color._data,0.7f,13).display(disp);
             vertices.save_off(reverse_primitives?reverse_primitives:primitives,colors,filename);
             (+visu).draw_text(0,0," Object '%s' saved. ",
-                              foreground_color._data,background_color._data,0.7f,13,filename).display(disp);
+                              foreground_color._data,background_color._data,0.7f,13,filename._data).display(disp);
             disp.set_key(key,false); key = 0;
           } break;
         case cimg::keyO : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Save object as a .cimg file
             static unsigned int snap_number = 0;
-            char filename[32] = { 0 };
             std::FILE *file;
             do {
 #ifdef cimg_use_zlib
-              cimg_snprintf(filename,sizeof(filename),cimg_appname "_%.4u.cimgz",snap_number++);
+              cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.cimgz",snap_number++);
 #else
-              cimg_snprintf(filename,sizeof(filename),cimg_appname "_%.4u.cimg",snap_number++);
+              cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.cimg",snap_number++);
 #endif
               if ((file=std::fopen(filename,"r"))!=0) cimg::fclose(file);
             } while (file);
@@ -43150,16 +47989,15 @@ namespace cimg_library_suffixed {
             vertices.get_object3dtoCImg3d(reverse_primitives?reverse_primitives:primitives,colors,opacities).
               save(filename);
             (+visu).draw_text(0,0," Object '%s' saved. ",
-                              foreground_color._data,background_color._data,0.7f,13,filename).display(disp);
+                              foreground_color._data,background_color._data,0.7f,13,filename._data).display(disp);
             disp.set_key(key,false); key = 0;
           } break;
 #ifdef cimg_use_board
         case cimg::keyP : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Save object as a .EPS file
             static unsigned int snap_number = 0;
-            char filename[32] = { 0 };
             std::FILE *file;
             do {
-              cimg_snprintf(filename,sizeof(filename),cimg_appname "_%.4u.eps",snap_number++);
+              cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.eps",snap_number++);
               if ((file=std::fopen(filename,"r"))!=0) cimg::fclose(file);
             } while (file);
             (+visu).draw_text(0,0," Saving EPS snapshot... ",
@@ -43175,15 +48013,14 @@ namespace cimg_library_suffixed {
                                    sprite_scale);
             board.saveEPS(filename);
             (+visu).draw_text(0,0," Object '%s' saved. ",
-                              foreground_color._data,background_color._data,0.7f,13,filename).display(disp);
+                              foreground_color._data,background_color._data,0.7f,13,filename._data).display(disp);
             disp.set_key(key,false); key = 0;
           } break;
         case cimg::keyV : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Save object as a .SVG file
             static unsigned int snap_number = 0;
-            char filename[32] = { 0 };
             std::FILE *file;
             do {
-              cimg_snprintf(filename,sizeof(filename),cimg_appname "_%.4u.svg",snap_number++);
+              cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.svg",snap_number++);
               if ((file=std::fopen(filename,"r"))!=0) cimg::fclose(file);
             } while (file);
             (+visu).draw_text(0,0," Saving SVG snapshot... ",
@@ -43199,7 +48036,7 @@ namespace cimg_library_suffixed {
                                    sprite_scale);
             board.saveSVG(filename);
             (+visu).draw_text(0,0," Object '%s' saved. ",
-                              foreground_color._data,background_color._data,0.7f,13,filename).display(disp);
+                              foreground_color._data,background_color._data,0.7f,13,filename._data).display(disp);
             disp.set_key(key,false); key = 0;
           } break;
 #endif
@@ -43209,6 +48046,10 @@ namespace cimg_library_suffixed {
           if (zbuffer) zbuffer.assign(disp.width(),disp.height());
           redraw = true;
         }
+        if (!exit_on_anykey && key && key!=cimg::keyESC &&
+            (key!=cimg::keyW || (!disp.is_keyCTRLLEFT() && !disp.is_keyCTRLRIGHT()))) {
+          key = 0;
+        }
       }
       if (pose_matrix) {
         std::memcpy(pose_matrix,pose._data,12*sizeof(float));
@@ -43233,30 +48074,33 @@ namespace cimg_library_suffixed {
     const CImg<T>& display_graph(CImgDisplay &disp,
                                  const unsigned int plot_type=1, const unsigned int vertex_type=1,
                                  const char *const labelx=0, const double xmin=0, const double xmax=0,
-                                 const char *const labely=0, const double ymin=0, const double ymax=0) const {
-      return _display_graph(disp,0,plot_type,vertex_type,labelx,xmin,xmax,labely,ymin,ymax);
+                                 const char *const labely=0, const double ymin=0, const double ymax=0,
+                                 const bool exit_on_anykey=false) const {
+      return _display_graph(disp,0,plot_type,vertex_type,labelx,xmin,xmax,labely,ymin,ymax,exit_on_anykey);
     }
 
     //! Display 1d graph in an interactive window \overloading.
     const CImg<T>& display_graph(const char *const title=0,
                                  const unsigned int plot_type=1, const unsigned int vertex_type=1,
                                  const char *const labelx=0, const double xmin=0, const double xmax=0,
-                                 const char *const labely=0, const double ymin=0, const double ymax=0) const {
+                                 const char *const labely=0, const double ymin=0, const double ymax=0,
+                                 const bool exit_on_anykey=false) const {
       CImgDisplay disp;
-      return _display_graph(disp,title,plot_type,vertex_type,labelx,xmin,xmax,labely,ymin,ymax);
+      return _display_graph(disp,title,plot_type,vertex_type,labelx,xmin,xmax,labely,ymin,ymax,exit_on_anykey);
     }
 
     const CImg<T>& _display_graph(CImgDisplay &disp, const char *const title=0,
-                                 const unsigned int plot_type=1, const unsigned int vertex_type=1,
-                                 const char *const labelx=0, const double xmin=0, const double xmax=0,
-                                 const char *const labely=0, const double ymin=0, const double ymax=0) const {
+                                  const unsigned int plot_type=1, const unsigned int vertex_type=1,
+                                  const char *const labelx=0, const double xmin=0, const double xmax=0,
+                                  const char *const labely=0, const double ymin=0, const double ymax=0,
+                                  const bool exit_on_anykey=false) const {
       if (is_empty())
         throw CImgInstanceException(_cimg_instance
                                     "display_graph(): Empty instance.",
                                     cimg_instance);
       if (!disp) disp.assign(cimg_fitscreen(CImgDisplay::screen_width()/2,CImgDisplay::screen_height()/2,1),0,0).
                    set_title(title?"%s":"CImg<%s>",title?title:pixel_type());
-      const unsigned long siz = (unsigned long)_width*_height*_depth, siz1 = cimg::max(1U,siz - 1);
+      const ulongT siz = (ulongT)_width*_height*_depth, siz1 = cimg::max(1U,siz - 1);
       const unsigned int old_normalization = disp.normalization();
       disp.show().flush()._normalization = 0;
 
@@ -43275,7 +48119,7 @@ namespace cimg_library_suffixed {
         					           labelx,
                                                            nxmin + x0*(nxmax - nxmin)/siz1,
                                                            nxmin + x1*(nxmax - nxmin)/siz1,
-                                                           labely,y0,y1);
+                                                           labely,y0,y1,true);
 	const int mouse_x = disp.mouse_x(), mouse_y = disp.mouse_y();
         if (selection[0]>=0) {
           if (selection[2]<0) reset_view = true;
@@ -43304,9 +48148,9 @@ namespace cimg_library_suffixed {
           case cimg::keyPAD3 : go_right = true; go_down = true; key = 0; disp.set_key(); break;
           }
           if (disp.wheel()) {
-            if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) go_out = !(go_in = disp.wheel()>0);
+            if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) go_up = !(go_down = disp.wheel()<0);
             else if (disp.is_keySHIFTLEFT() || disp.is_keySHIFTRIGHT()) go_left = !(go_right = disp.wheel()>0);
-            else go_up = !(go_down = disp.wheel()<0);
+            else go_out = !(go_in = disp.wheel()>0);
             key = 0;
           }
 
@@ -43359,6 +48203,11 @@ namespace cimg_library_suffixed {
             go_down = false;
           }
         }
+        if (!exit_on_anykey && key && key!=(int)cimg::keyESC &&
+            (key!=(int)cimg::keyW || (!disp.is_keyCTRLLEFT() && !disp.is_keyCTRLRIGHT()))) {
+          disp.set_key(key,false);
+          key = 0;
+        }
       }
       disp._normalization = old_normalization;
       return *this;
@@ -43539,7 +48388,7 @@ namespace cimg_library_suffixed {
                    "%s data_%s[] = { %s\n  ",
                    varname._data,_width,_height,_depth,_spectrum,pixel_type(),pixel_type(),varname._data,
                    is_empty()?"};":"");
-      if (!is_empty()) for (unsigned long off = 0, siz = size() - 1; off<=siz; ++off) {
+      if (!is_empty()) for (ulongT off = 0, siz = size() - 1; off<=siz; ++off) {
         std::fprintf(nfile,cimg::type<T>::format(),cimg::type<T>::format((*this)[off]));
         if (off==siz) std::fprintf(nfile," };\n");
         else if (!((off + 1)%16)) std::fprintf(nfile,",\n  ");
@@ -43620,7 +48469,8 @@ namespace cimg_library_suffixed {
                    filename?filename:"(FILE*)");
 
       std::FILE *const nfile = file?file:cimg::fopen(filename,"wb");
-      unsigned char header[54] = { 0 }, align_buf[4] = { 0 };
+      CImg<ucharT> header(54,1,1,1,0);
+      unsigned char align_buf[4] = { 0 };
       const unsigned int
         align = (4 - (3*_width)%4)%4,
         buf_size = (3*_width + align)*height(),
@@ -43650,7 +48500,7 @@ namespace cimg_library_suffixed {
       header[0x25] = (buf_size>>24)&0xFF;
       header[0x27] = 0x1;
       header[0x2B] = 0x1;
-      cimg::fwrite(header,54,nfile);
+      cimg::fwrite(header._data,54,nfile);
 
       const T
         *ptr_r = data(0,_height - 1,0,0),
@@ -43730,7 +48580,7 @@ namespace cimg_library_suffixed {
       unsigned int dimbuf = 0;
       J_COLOR_SPACE colortype = JCS_RGB;
 
-      switch(_spectrum) {
+      switch (_spectrum) {
       case 1 : dimbuf = 1; colortype = JCS_GRAYSCALE; break;
       case 2 : dimbuf = 3; colortype = JCS_RGB; break;
       case 3 : dimbuf = 3; colortype = JCS_RGB; break;
@@ -43753,7 +48603,7 @@ namespace cimg_library_suffixed {
       jpeg_start_compress(&cinfo,TRUE);
 
       JSAMPROW row_pointer[1];
-      CImg<ucharT> buffer((unsigned long)_width*dimbuf);
+      CImg<ucharT> buffer(_width*dimbuf);
 
       while (cinfo.next_scanline<cinfo.image_height) {
         unsigned char *ptrd = buffer._data;
@@ -43762,13 +48612,13 @@ namespace cimg_library_suffixed {
         switch (_spectrum) {
         case 1 : { // Greyscale images
           const T *ptr_g = data(0, cinfo.next_scanline);
-          for(unsigned int b = 0; b < cinfo.image_width; b++)
+          for (unsigned int b = 0; b<cinfo.image_width; b++)
             *(ptrd++) = (unsigned char)*(ptr_g++);
         } break;
         case 2 : { // RG images
           const T *ptr_r = data(0,cinfo.next_scanline,0,0),
             *ptr_g = data(0,cinfo.next_scanline,0,1);
-          for(unsigned int b = 0; b < cinfo.image_width; ++b) {
+          for (unsigned int b = 0; b<cinfo.image_width; ++b) {
             *(ptrd++) = (unsigned char)*(ptr_r++);
             *(ptrd++) = (unsigned char)*(ptr_g++);
             *(ptrd++) = 0;
@@ -43778,7 +48628,7 @@ namespace cimg_library_suffixed {
           const T *ptr_r = data(0,cinfo.next_scanline,0,0),
             *ptr_g = data(0,cinfo.next_scanline,0,1),
             *ptr_b = data(0,cinfo.next_scanline,0,2);
-          for(unsigned int b = 0; b < cinfo.image_width; ++b) {
+          for (unsigned int b = 0; b<cinfo.image_width; ++b) {
             *(ptrd++) = (unsigned char)*(ptr_r++);
             *(ptrd++) = (unsigned char)*(ptr_g++);
             *(ptrd++) = (unsigned char)*(ptr_b++);
@@ -43789,7 +48639,7 @@ namespace cimg_library_suffixed {
             *ptr_g = data(0,cinfo.next_scanline,0,1),
             *ptr_b = data(0,cinfo.next_scanline,0,2),
             *ptr_a = data(0,cinfo.next_scanline,0,3);
-          for(unsigned int b = 0; b < cinfo.image_width; ++b) {
+          for (unsigned int b = 0; b<cinfo.image_width; ++b) {
             *(ptrd++) = (unsigned char)*(ptr_r++);
             *(ptrd++) = (unsigned char)*(ptr_g++);
             *(ptrd++) = (unsigned char)*(ptr_b++);
@@ -43850,20 +48700,20 @@ namespace cimg_library_suffixed {
       Magick::PixelPacket *pixels = image.getPixels(0,0,_width,_height);
       switch (_spectrum) {
       case 1 : // Scalar images
-        for (unsigned long off = (unsigned long)_width*_height; off; --off) {
+        for (ulongT off = (ulongT)_width*_height; off; --off) {
           pixels->red = pixels->green = pixels->blue = (Magick::Quantum)*(ptr_r++);
           ++pixels;
         }
         break;
       case 2 : // RG images
-        for (unsigned long off = (unsigned long)_width*_height; off; --off) {
+        for (ulongT off = (ulongT)_width*_height; off; --off) {
           pixels->red = (Magick::Quantum)*(ptr_r++);
           pixels->green = (Magick::Quantum)*(ptr_g++);
           pixels->blue = 0; ++pixels;
         }
         break;
       default : // RGB images
-        for (unsigned long off = (unsigned long)_width*_height; off; --off) {
+        for (ulongT off = (ulongT)_width*_height; off; --off) {
           pixels->red = (Magick::Quantum)*(ptr_r++);
           pixels->green = (Magick::Quantum)*(ptr_g++);
           pixels->blue = (Magick::Quantum)*(ptr_b++);
@@ -44133,7 +48983,7 @@ namespace cimg_library_suffixed {
         *ptr_r = data(0,0,0,0),
         *ptr_g = (_spectrum>=2)?data(0,0,0,1):0,
         *ptr_b = (_spectrum>=3)?data(0,0,0,2):0;
-      const unsigned long buf_size = cimg::min(1024*1024UL,_width*_height*(_spectrum==1?1UL:3UL));
+      const ulongT buf_size = cimg::min((ulongT)1024*1024,(ulongT)_width*_height*(_spectrum==1?1UL:3UL));
 
       std::fprintf(nfile,"P%c\n%u %u\n%u\n",
                    (_spectrum==1?'5':'6'),_width,_height,stmax<256?255:(stmax<4096?4095:65535));
@@ -44142,19 +48992,19 @@ namespace cimg_library_suffixed {
       case 1 : { // Scalar image
         if (bytes_per_pixel==1 || (!bytes_per_pixel && stmax<256)) { // Binary PGM 8 bits
           CImg<ucharT> buf(buf_size);
-          for (long to_write = width()*height(); to_write>0; ) {
-            const unsigned long N = cimg::min((unsigned long)to_write,buf_size);
+          for (longT to_write = (longT)width()*height(); to_write>0; ) {
+            const ulongT N = cimg::min((ulongT)to_write,buf_size);
             unsigned char *ptrd = buf._data;
-            for (unsigned long i = N; i>0; --i) *(ptrd++) = (unsigned char)*(ptr_r++);
+            for (ulongT i = N; i>0; --i) *(ptrd++) = (unsigned char)*(ptr_r++);
             cimg::fwrite(buf._data,N,nfile);
             to_write-=N;
           }
         } else { // Binary PGM 16 bits
           CImg<ushortT> buf(buf_size);
-          for (long to_write = width()*height(); to_write>0; ) {
-            const unsigned long N = cimg::min((unsigned long)to_write,buf_size);
+          for (longT to_write = (longT)width()*height(); to_write>0; ) {
+            const ulongT N = cimg::min((ulongT)to_write,buf_size);
             unsigned short *ptrd = buf._data;
-            for (unsigned long i = N; i>0; --i) *(ptrd++) = (unsigned short)*(ptr_r++);
+            for (ulongT i = N; i>0; --i) *(ptrd++) = (unsigned short)*(ptr_r++);
             if (!cimg::endianness()) cimg::invert_endianness(buf._data,buf_size);
             cimg::fwrite(buf._data,N,nfile);
             to_write-=N;
@@ -44164,10 +49014,10 @@ namespace cimg_library_suffixed {
       case 2 : { // RG image
         if (bytes_per_pixel==1 || (!bytes_per_pixel && stmax<256)) { // Binary PPM 8 bits
           CImg<ucharT> buf(buf_size);
-          for (long to_write = width()*height(); to_write>0; ) {
-            const unsigned long N = cimg::min((unsigned long)to_write,buf_size/3);
+          for (longT to_write = (longT)width()*height(); to_write>0; ) {
+            const ulongT N = cimg::min((ulongT)to_write,buf_size/3);
             unsigned char *ptrd = buf._data;
-            for (unsigned long i = N; i>0; --i) {
+            for (ulongT i = N; i>0; --i) {
               *(ptrd++) = (unsigned char)*(ptr_r++);
               *(ptrd++) = (unsigned char)*(ptr_g++);
               *(ptrd++) = 0;
@@ -44177,10 +49027,10 @@ namespace cimg_library_suffixed {
           }
         } else {             // Binary PPM 16 bits
           CImg<ushortT> buf(buf_size);
-          for (long to_write = width()*height(); to_write>0; ) {
-            const unsigned long N = cimg::min((unsigned long)to_write,buf_size/3);
+          for (longT to_write = (longT)width()*height(); to_write>0; ) {
+            const ulongT N = cimg::min((ulongT)to_write,buf_size/3);
             unsigned short *ptrd = buf._data;
-            for (unsigned long i = N; i>0; --i) {
+            for (ulongT i = N; i>0; --i) {
               *(ptrd++) = (unsigned short)*(ptr_r++);
               *(ptrd++) = (unsigned short)*(ptr_g++);
               *(ptrd++) = 0;
@@ -44194,10 +49044,10 @@ namespace cimg_library_suffixed {
       default : { // RGB image
         if (bytes_per_pixel==1 || (!bytes_per_pixel && stmax<256)) { // Binary PPM 8 bits
           CImg<ucharT> buf(buf_size);
-          for (long to_write = width()*height(); to_write>0; ) {
-            const unsigned long N = cimg::min((unsigned long)to_write,buf_size/3);
+          for (longT to_write = (longT)width()*height(); to_write>0; ) {
+            const ulongT N = cimg::min((ulongT)to_write,buf_size/3);
             unsigned char *ptrd = buf._data;
-            for (unsigned long i = N; i>0; --i) {
+            for (ulongT i = N; i>0; --i) {
               *(ptrd++) = (unsigned char)*(ptr_r++);
               *(ptrd++) = (unsigned char)*(ptr_g++);
               *(ptrd++) = (unsigned char)*(ptr_b++);
@@ -44207,10 +49057,10 @@ namespace cimg_library_suffixed {
           }
         } else {             // Binary PPM 16 bits
           CImg<ushortT> buf(buf_size);
-          for (long to_write = width()*height(); to_write>0; ) {
-            const unsigned long N = cimg::min((unsigned long)to_write,buf_size/3);
+          for (longT to_write = (longT)width()*height(); to_write>0; ) {
+            const ulongT N = cimg::min((ulongT)to_write,buf_size/3);
             unsigned short *ptrd = buf._data;
-            for (unsigned long i = N; i>0; --i) {
+            for (ulongT i = N; i>0; --i) {
               *(ptrd++) = (unsigned short)*(ptr_r++);
               *(ptrd++) = (unsigned short)*(ptr_g++);
               *(ptrd++) = (unsigned short)*(ptr_b++);
@@ -44251,7 +49101,7 @@ namespace cimg_library_suffixed {
                    cimg_instance,
                    filename?filename:"(FILE*)");
 
-      const unsigned long buf_size = cimg::min(1024*1024LU,_width*_height*_depth);
+      const ulongT buf_size = cimg::min((ulongT)1024*1024,(ulongT)_width*_height*_depth);
       std::FILE *const nfile = file?file:cimg::fopen(filename,"wb");
       const T *ptr = data(0,0,0,0);
 
@@ -44260,10 +49110,10 @@ namespace cimg_library_suffixed {
       else if (!cimg::type<T>::is_float() && sizeof(T)==1) { // Save as extended P5 file: Binary byte-valued 3d.
         std::fprintf(nfile,"P5\n%u %u %u\n255\n",_width,_height,_depth);
         CImg<ucharT> buf(buf_size);
-        for (long to_write = width()*height()*depth(); to_write>0; ) {
-          const unsigned long N = cimg::min((unsigned long)to_write,buf_size);
+        for (longT to_write = (longT)width()*height()*depth(); to_write>0; ) {
+          const ulongT N = cimg::min((ulongT)to_write,buf_size);
           unsigned char *ptrd = buf._data;
-          for (unsigned long i = N; i>0; --i) *(ptrd++) = (unsigned char)*(ptr++);
+          for (ulongT i = N; i>0; --i) *(ptrd++) = (unsigned char)*(ptr++);
           cimg::fwrite(buf._data,N,nfile);
           to_write-=N;
         }
@@ -44271,10 +49121,10 @@ namespace cimg_library_suffixed {
         if (_depth>1) std::fprintf(nfile,"P8\n%u %u %u\n%d\n",_width,_height,_depth,(int)max());
         else std::fprintf(nfile,"P8\n%u %u\n%d\n",_width,_height,(int)max());
         CImg<intT> buf(buf_size);
-        for (long to_write = width()*height()*depth(); to_write>0; ) {
-          const unsigned long N = cimg::min((unsigned long)to_write,buf_size);
+        for (longT to_write = (longT)width()*height()*depth(); to_write>0; ) {
+          const ulongT N = cimg::min((ulongT)to_write,buf_size);
           int *ptrd = buf._data;
-          for (unsigned long i = N; i>0; --i) *(ptrd++) = (int)*(ptr++);
+          for (ulongT i = N; i>0; --i) *(ptrd++) = (int)*(ptr++);
           cimg::fwrite(buf._data,N,nfile);
           to_write-=N;
         }
@@ -44282,10 +49132,10 @@ namespace cimg_library_suffixed {
         if (_depth>1) std::fprintf(nfile,"P9\n%u %u %u\n%g\n",_width,_height,_depth,(double)max());
         else std::fprintf(nfile,"P9\n%u %u\n%g\n",_width,_height,(double)max());
         CImg<floatT> buf(buf_size);
-        for (long to_write = width()*height()*depth(); to_write>0; ) {
-          const unsigned long N = cimg::min((unsigned long)to_write,buf_size);
+        for (longT to_write = (longT)width()*height()*depth(); to_write>0; ) {
+          const ulongT N = cimg::min((ulongT)to_write,buf_size);
           float *ptrd = buf._data;
-          for (unsigned long i = N; i>0; --i) *(ptrd++) = (float)*(ptr++);
+          for (ulongT i = N; i>0; --i) *(ptrd++) = (float)*(ptr++);
           cimg::fwrite(buf._data,N,nfile);
           to_write-=N;
         }
@@ -44341,10 +49191,10 @@ namespace cimg_library_suffixed {
       switch (_spectrum) {
       case 1 : { // Scalar image
         CImg<floatT> buf(buf_size);
-        for (long to_write = width()*height(); to_write>0; ) {
-          const unsigned long N = cimg::min((unsigned long)to_write,buf_size);
+        for (longT to_write = (longT)width()*height(); to_write>0; ) {
+          const ulongT N = cimg::min((ulongT)to_write,buf_size);
           float *ptrd = buf._data;
-          for (unsigned long i = N; i>0; --i) *(ptrd++) = (float)*(ptr_r++);
+          for (ulongT i = N; i>0; --i) *(ptrd++) = (float)*(ptr_r++);
           if (!cimg::endianness()) cimg::invert_endianness(buf._data,buf_size);
           cimg::fwrite(buf._data,N,nfile);
           to_write-=N;
@@ -44352,10 +49202,10 @@ namespace cimg_library_suffixed {
       } break;
       case 2 : { // RG image
         CImg<floatT> buf(buf_size);
-        for (long to_write = width()*height(); to_write>0; ) {
+        for (longT to_write = (longT)width()*height(); to_write>0; ) {
           const unsigned int N = cimg::min((unsigned int)to_write,buf_size/3);
           float *ptrd = buf._data;
-          for (unsigned long i = N; i>0; --i) {
+          for (ulongT i = N; i>0; --i) {
             *(ptrd++) = (float)*(ptr_r++);
             *(ptrd++) = (float)*(ptr_g++);
             *(ptrd++) = 0;
@@ -44367,10 +49217,10 @@ namespace cimg_library_suffixed {
       } break;
       default : { // RGB image
         CImg<floatT> buf(buf_size);
-        for (long to_write = width()*height(); to_write>0; ) {
+        for (longT to_write = (longT)width()*height(); to_write>0; ) {
           const unsigned int N = cimg::min((unsigned int)to_write,buf_size/3);
           float *ptrd = buf._data;
-          for (unsigned long i = N; i>0; --i) {
+          for (ulongT i = N; i>0; --i) {
             *(ptrd++) = (float)*(ptr_r++);
             *(ptrd++) = (float)*(ptr_g++);
             *(ptrd++) = (float)*(ptr_b++);
@@ -44411,7 +49261,7 @@ namespace cimg_library_suffixed {
                    filename?filename:"(FILE*)");
 
       std::FILE *const nfile = file?file:cimg::fopen(filename,"wb");
-      const unsigned long wh = (unsigned long)_width*_height;
+      const ulongT wh = (ulongT)_width*_height;
       unsigned char *const buffer = new unsigned char[3*wh], *nbuffer = buffer;
       const T
         *ptr1 = data(0,0,0,0),
@@ -44419,7 +49269,7 @@ namespace cimg_library_suffixed {
         *ptr3 = _spectrum>2?data(0,0,0,2):0;
       switch (_spectrum) {
       case 1 : { // Scalar image
-        for (unsigned long k = 0; k<wh; ++k) {
+        for (ulongT k = 0; k<wh; ++k) {
           const unsigned char val = (unsigned char)*(ptr1++);
           *(nbuffer++) = val;
           *(nbuffer++) = val;
@@ -44427,14 +49277,14 @@ namespace cimg_library_suffixed {
         }
       } break;
       case 2 : { // RG image
-        for (unsigned long k = 0; k<wh; ++k) {
+        for (ulongT k = 0; k<wh; ++k) {
           *(nbuffer++) = (unsigned char)(*(ptr1++));
           *(nbuffer++) = (unsigned char)(*(ptr2++));
           *(nbuffer++) = 0;
         }
       } break;
       default : { // RGB image
-        for (unsigned long k = 0; k<wh; ++k) {
+        for (ulongT k = 0; k<wh; ++k) {
           *(nbuffer++) = (unsigned char)(*(ptr1++));
           *(nbuffer++) = (unsigned char)(*(ptr2++));
           *(nbuffer++) = (unsigned char)(*(ptr3++));
@@ -44473,7 +49323,7 @@ namespace cimg_library_suffixed {
                    filename?filename:"(FILE*)");
 
       std::FILE *const nfile = file?file:cimg::fopen(filename,"wb");
-      const unsigned long wh = (unsigned long)_width*_height;
+      const ulongT wh = (ulongT)_width*_height;
       unsigned char *const buffer = new unsigned char[4*wh], *nbuffer = buffer;
       const T
         *ptr1 = data(0,0,0,0),
@@ -44482,7 +49332,7 @@ namespace cimg_library_suffixed {
         *ptr4 = _spectrum>3?data(0,0,0,3):0;
       switch (_spectrum) {
       case 1 : { // Scalar images
-        for (unsigned long k = 0; k<wh; ++k) {
+        for (ulongT k = 0; k<wh; ++k) {
           const unsigned char val = (unsigned char)*(ptr1++);
           *(nbuffer++) = val;
           *(nbuffer++) = val;
@@ -44491,7 +49341,7 @@ namespace cimg_library_suffixed {
         }
       } break;
       case 2 : { // RG images
-        for (unsigned long k = 0; k<wh; ++k) {
+        for (ulongT k = 0; k<wh; ++k) {
           *(nbuffer++) = (unsigned char)(*(ptr1++));
           *(nbuffer++) = (unsigned char)(*(ptr2++));
           *(nbuffer++) = 0;
@@ -44499,7 +49349,7 @@ namespace cimg_library_suffixed {
         }
       } break;
       case 3 : { // RGB images
-        for (unsigned long k = 0; k<wh; ++k) {
+        for (ulongT k = 0; k<wh; ++k) {
           *(nbuffer++) = (unsigned char)(*(ptr1++));
           *(nbuffer++) = (unsigned char)(*(ptr2++));
           *(nbuffer++) = (unsigned char)(*(ptr3++));
@@ -44507,7 +49357,7 @@ namespace cimg_library_suffixed {
         }
       } break;
       default : { // RGBA images
-        for (unsigned long k = 0; k<wh; ++k) {
+        for (ulongT k = 0; k<wh; ++k) {
           *(nbuffer++) = (unsigned char)(*(ptr1++));
           *(nbuffer++) = (unsigned char)(*(ptr2++));
           *(nbuffer++) = (unsigned char)(*(ptr3++));
@@ -44531,11 +49381,12 @@ namespace cimg_library_suffixed {
        - When libtiff is enabled, 2D and 3D (multipage) several
         channel per pixel are supported for
         <tt>char,uchar,short,ushort,float</tt> and \c double pixel types.
-       - If \c cimg_use_tif is not defined at compilation time the
+       - If \c cimg_use_tif is not defined at compile time the
         function uses CImg<T>&save_other(const char*).
      **/
     const CImg<T>& save_tiff(const char *const filename, const unsigned int compression_type=0,
-                             const float *const voxel_size=0, const char *const description=0) const {
+                             const float *const voxel_size=0, const char *const description=0,
+                             const bool use_bigtiff=true) const {
       if (!filename)
         throw CImgArgumentException(_cimg_instance
                                     "save_tiff(): Specified filename is (null).",
@@ -44543,9 +49394,11 @@ namespace cimg_library_suffixed {
       if (is_empty()) { cimg::fempty(0,filename); return *this; }
 
 #ifdef cimg_use_tiff
-      TIFF *tif = TIFFOpen(filename,"w");
+      const bool
+        _use_bigtiff = use_bigtiff && sizeof(ulongT)>=8 && size()*sizeof(T)>=1UL<<31; // No bigtiff for small images.
+      TIFF *tif = TIFFOpen(filename,_use_bigtiff?"w8":"w4");
       if (tif) {
-        cimg_forZ(*this,z) get_slice(z)._save_tiff(tif,z,compression_type,voxel_size,description);
+        cimg_forZ(*this,z) _save_tiff(tif,z,z,compression_type,voxel_size,description);
         TIFFClose(tif);
       } else throw CImgIOException(_cimg_instance
                                    "save_tiff(): Failed to open file '%s' for writing.",
@@ -44553,7 +49406,7 @@ namespace cimg_library_suffixed {
                                    filename);
       return *this;
 #else
-      cimg::unused(compression_type,voxel_size,description);
+      cimg::unused(compression_type,voxel_size,description,use_bigtiff);
       return save_other(filename);
 #endif
     }
@@ -44561,13 +49414,13 @@ namespace cimg_library_suffixed {
 #ifdef cimg_use_tiff
 
 #define _cimg_save_tiff(types,typed,compression_type) if (!std::strcmp(types,pixel_type())) { \
-      const typed foo = (typed)0; return _save_tiff(tif,directory,foo,compression_type,voxel_size,description); }
+      const typed foo = (typed)0; return _save_tiff(tif,directory,z,foo,compression_type,voxel_size,description); }
 
     // [internal] Save a plane into a tiff file
     template<typename t>
-    const CImg<T>& _save_tiff(TIFF *tif, const unsigned int directory, const t& pixel_t,
-                              const unsigned int compression_type,
-                              const float *const voxel_size, const char *const description) const {
+    const CImg<T>& _save_tiff(TIFF *tif, const unsigned int directory, const unsigned int z, const t& pixel_t,
+                              const unsigned int compression_type, const float *const voxel_size,
+                              const char *const description) const {
       if (is_empty() || !tif || pixel_t) return *this;
       const char *const filename = TIFFFileName(tif);
       uint32 rowsperstrip = (uint32)-1;
@@ -44610,7 +49463,7 @@ namespace cimg_library_suffixed {
           for (unsigned int rr = 0; rr<nrow; ++rr)
             for (unsigned int cc = 0; cc<_width; ++cc)
               for (unsigned int vv = 0; vv<spp; ++vv)
-                buf[i++] = (t)(*this)(cc,row + rr,0,vv);
+                buf[i++] = (t)(*this)(cc,row + rr,z,vv);
           if (TIFFWriteEncodedStrip(tif,strip,buf,i*sizeof(t))<0)
             throw CImgIOException(_cimg_instance
                                   "save_tiff(): Invalid strip writing when saving file '%s'.",
@@ -44623,17 +49476,18 @@ namespace cimg_library_suffixed {
       return (*this);
     }
 
-    const CImg<T>& _save_tiff(TIFF *tif, const unsigned int directory, const unsigned int compression_type,
-                              const float *const voxel_size, const char *const description) const {
+    const CImg<T>& _save_tiff(TIFF *tif, const unsigned int directory, const unsigned int z,
+                              const unsigned int compression_type, const float *const voxel_size,
+                              const char *const description) const {
       _cimg_save_tiff("bool",unsigned char,compression_type);
-      _cimg_save_tiff("char",char,compression_type);
       _cimg_save_tiff("unsigned char",unsigned char,compression_type);
-      _cimg_save_tiff("short",short,compression_type);
+      _cimg_save_tiff("char",char,compression_type);
       _cimg_save_tiff("unsigned short",unsigned short,compression_type);
-      _cimg_save_tiff("int",int,compression_type);
+      _cimg_save_tiff("short",short,compression_type);
       _cimg_save_tiff("unsigned int",unsigned int,compression_type);
-      _cimg_save_tiff("long",int,compression_type);
-      _cimg_save_tiff("unsigned long",unsigned int,compression_type);
+      _cimg_save_tiff("int",int,compression_type);
+      _cimg_save_tiff("unsigned int64",unsigned int,compression_type);
+      _cimg_save_tiff("int64",int,compression_type);
       _cimg_save_tiff("float",float,compression_type);
       _cimg_save_tiff("double",float,compression_type);
       const char *const filename = TIFFFileName(tif);
@@ -44699,11 +49553,9 @@ namespace cimg_library_suffixed {
       if (is_empty()) { cimg::fempty(0,filename); return *this; }
 
       std::FILE *file;
-      char header[348] = { 0 };
-      CImg<charT> hname(1024), iname(1024);
+      CImg<charT> header(348,1,1,1,0), hname(1024), iname(1024);
       const char *const ext = cimg::split_filename(filename);
       short datatype = -1;
-      std::memset(header,0,348);
       if (!*ext) {
         cimg_snprintf(hname,hname._width,"%s.hdr",filename);
         cimg_snprintf(iname,iname._width,"%s.img",filename);
@@ -44721,17 +49573,17 @@ namespace cimg_library_suffixed {
       if (!cimg::strncasecmp(ext,"nii",3)) {
         std::strncpy(hname,filename,hname._width - 1); *iname = 0;
       }
-      int *const iheader = (int*)header;
+      int *const iheader = (int*)header._data;
       *iheader = 348;
-      std::strcpy(header + 4,"CImg");
-      std::strcpy(header + 14," ");
-      ((short*)(header + 36))[0] = 4096;
-      ((char*)(header + 38))[0] = 114;
-      ((short*)(header + 40))[0] = 4;
-      ((short*)(header + 40))[1] = (short)_width;
-      ((short*)(header + 40))[2] = (short)_height;
-      ((short*)(header + 40))[3] = (short)_depth;
-      ((short*)(header + 40))[4] = (short)_spectrum;
+      std::strcpy(header._data + 4,"CImg");
+      std::strcpy(header._data + 14," ");
+      ((short*)&(header[36]))[0] = 4096;
+      ((char*)&(header[38]))[0] = 114;
+      ((short*)&(header[40]))[0] = 4;
+      ((short*)&(header[40]))[1] = (short)_width;
+      ((short*)&(header[40]))[2] = (short)_height;
+      ((short*)&(header[40]))[3] = (short)_depth;
+      ((short*)&(header[40]))[4] = (short)_spectrum;
       if (!cimg::strcasecmp(pixel_type(),"bool")) datatype = 2;
       if (!cimg::strcasecmp(pixel_type(),"unsigned char")) datatype = 2;
       if (!cimg::strcasecmp(pixel_type(),"char")) datatype = 2;
@@ -44739,8 +49591,8 @@ namespace cimg_library_suffixed {
       if (!cimg::strcasecmp(pixel_type(),"short")) datatype = 4;
       if (!cimg::strcasecmp(pixel_type(),"unsigned int")) datatype = 8;
       if (!cimg::strcasecmp(pixel_type(),"int")) datatype = 8;
-      if (!cimg::strcasecmp(pixel_type(),"unsigned long")) datatype = 8;
-      if (!cimg::strcasecmp(pixel_type(),"long")) datatype = 8;
+      if (!cimg::strcasecmp(pixel_type(),"unsigned int64")) datatype = 8;
+      if (!cimg::strcasecmp(pixel_type(),"int64")) datatype = 8;
       if (!cimg::strcasecmp(pixel_type(),"float")) datatype = 16;
       if (!cimg::strcasecmp(pixel_type(),"double")) datatype = 64;
       if (datatype<0)
@@ -44749,17 +49601,17 @@ namespace cimg_library_suffixed {
                               cimg_instance,
                               pixel_type(),filename);
 
-      ((short*)(header + 70))[0] = datatype;
-      ((short*)(header + 72))[0] = sizeof(T);
-      ((float*)(header + 112))[0] = 1;
-      ((float*)(header + 76))[0] = 0;
+      ((short*)&(header[70]))[0] = datatype;
+      ((short*)&(header[72]))[0] = sizeof(T);
+      ((float*)&(header[112]))[0] = 1;
+      ((float*)&(header[76]))[0] = 0;
       if (voxel_size) {
-        ((float*)(header + 76))[1] = voxel_size[0];
-        ((float*)(header + 76))[2] = voxel_size[1];
-        ((float*)(header + 76))[3] = voxel_size[2];
-      } else ((float*)(header + 76))[1] = ((float*)(header + 76))[2] = ((float*)(header + 76))[3] = 1;
+        ((float*)&(header[76]))[1] = voxel_size[0];
+        ((float*)&(header[76]))[2] = voxel_size[1];
+        ((float*)&(header[76]))[3] = voxel_size[2];
+      } else ((float*)&(header[76]))[1] = ((float*)&(header[76]))[2] = ((float*)&(header[76]))[3] = 1;
       file = cimg::fopen(hname,"wb");
-      cimg::fwrite(header,348,file);
+      cimg::fwrite(header._data,348,file);
       if (*iname) { cimg::fclose(file); file = cimg::fopen(iname,"wb"); }
       cimg::fwrite(_data,size(),file);
       cimg::fclose(file);
@@ -44890,14 +49742,15 @@ namespace cimg_library_suffixed {
                               pixel_type(),filename?filename:"(FILE*)");
 
       std::FILE *const nfile = file?file:cimg::fopen(filename,"wb");
-      char header[257] = { 0 };
-      int err = cimg_snprintf(header,sizeof(header),"#INRIMAGE-4#{\nXDIM=%u\nYDIM=%u\nZDIM=%u\nVDIM=%u\n",
+      CImg<charT> header(257);
+      int err = cimg_snprintf(header,header._width,"#INRIMAGE-4#{\nXDIM=%u\nYDIM=%u\nZDIM=%u\nVDIM=%u\n",
                               _width,_height,_depth,_spectrum);
-      if (voxel_size) err+=cimg_sprintf(header + err,"VX=%g\nVY=%g\nVZ=%g\n",voxel_size[0],voxel_size[1],voxel_size[2]);
-      err+=cimg_sprintf(header + err,"TYPE=%s\nCPU=%s\n",inrtype,cimg::endianness()?"sun":"decm");
-      std::memset(header + err,'\n',252 - err);
-      std::memcpy(header + 252,"##}\n",4);
-      cimg::fwrite(header,256,nfile);
+      if (voxel_size) err+=cimg_sprintf(header._data + err,"VX=%g\nVY=%g\nVZ=%g\n",
+                                        voxel_size[0],voxel_size[1],voxel_size[2]);
+      err+=cimg_sprintf(header._data + err,"TYPE=%s\nCPU=%s\n",inrtype,cimg::endianness()?"sun":"decm");
+      std::memset(header._data + err,'\n',252 - err);
+      std::memcpy(header._data + 252,"##}\n",4);
+      cimg::fwrite(header._data,256,nfile);
       cimg_forXYZ(*this,x,y,z) cimg_forC(*this,c) cimg::fwrite(&((*this)(x,y,z,c)),1,nfile);
       if (!file) cimg::fclose(nfile);
       return *this;
@@ -44923,10 +49776,10 @@ namespace cimg_library_suffixed {
 #ifndef cimg_use_openexr
       return save_other(filename);
 #else
-      Imf::Rgba *const ptrd0 = new Imf::Rgba[(unsigned long)_width*_height], *ptrd = ptrd0, rgba;
+      Imf::Rgba *const ptrd0 = new Imf::Rgba[(size_t)_width*_height], *ptrd = ptrd0, rgba;
       switch (_spectrum) {
       case 1 : { // Grayscale image.
-        for (const T *ptr_r = data(), *const ptr_e = ptr_r + (unsigned long)_width*_height; ptr_r<ptr_e;) {
+        for (const T *ptr_r = data(), *const ptr_e = ptr_r + (ulongT)_width*_height; ptr_r<ptr_e;) {
           rgba.r = rgba.g = rgba.b = (half)(*(ptr_r++));
           rgba.a = (half)1;
           *(ptrd++) = rgba;
@@ -44934,7 +49787,7 @@ namespace cimg_library_suffixed {
       } break;
       case 2 : { // RG image.
         for (const T *ptr_r = data(), *ptr_g = data(0,0,0,1),
-               *const ptr_e = ptr_r + (unsigned long)_width*_height; ptr_r<ptr_e; ) {
+               *const ptr_e = ptr_r + (ulongT)_width*_height; ptr_r<ptr_e; ) {
           rgba.r = (half)(*(ptr_r++));
           rgba.g = (half)(*(ptr_g++));
           rgba.b = (half)0;
@@ -44944,7 +49797,7 @@ namespace cimg_library_suffixed {
       } break;
       case 3 : { // RGB image.
         for (const T *ptr_r = data(), *ptr_g = data(0,0,0,1), *ptr_b = data(0,0,0,2),
-               *const ptr_e = ptr_r + (unsigned long)_width*_height; ptr_r<ptr_e;) {
+               *const ptr_e = ptr_r + (ulongT)_width*_height; ptr_r<ptr_e;) {
           rgba.r = (half)(*(ptr_r++));
           rgba.g = (half)(*(ptr_g++));
           rgba.b = (half)(*(ptr_b++));
@@ -44954,7 +49807,7 @@ namespace cimg_library_suffixed {
       } break;
       default : { // RGBA image.
         for (const T *ptr_r = data(), *ptr_g = data(0,0,0,1), *ptr_b = data(0,0,0,2), *ptr_a = data(0,0,0,3),
-               *const ptr_e = ptr_r + (unsigned long)_width*_height; ptr_r<ptr_e;) {
+               *const ptr_e = ptr_r + (ulongT)_width*_height; ptr_r<ptr_e;) {
           rgba.r = (half)(*(ptr_r++));
           rgba.g = (half)(*(ptr_g++));
           rgba.b = (half)(*(ptr_b++));
@@ -45084,89 +49937,89 @@ namespace cimg_library_suffixed {
       bool saved = false;
       _cimg_save_pandore_case(1,1,1,"unsigned char",2);
       _cimg_save_pandore_case(1,1,1,"char",3);
-      _cimg_save_pandore_case(1,1,1,"short",3);
       _cimg_save_pandore_case(1,1,1,"unsigned short",3);
+      _cimg_save_pandore_case(1,1,1,"short",3);
       _cimg_save_pandore_case(1,1,1,"unsigned int",3);
       _cimg_save_pandore_case(1,1,1,"int",3);
-      _cimg_save_pandore_case(1,1,1,"unsigned long",4);
-      _cimg_save_pandore_case(1,1,1,"long",3);
+      _cimg_save_pandore_case(1,1,1,"unsigned int64",3);
+      _cimg_save_pandore_case(1,1,1,"int64",3);
       _cimg_save_pandore_case(1,1,1,"float",4);
       _cimg_save_pandore_case(1,1,1,"double",4);
 
       _cimg_save_pandore_case(0,1,1,"unsigned char",5);
       _cimg_save_pandore_case(0,1,1,"char",6);
-      _cimg_save_pandore_case(0,1,1,"short",6);
       _cimg_save_pandore_case(0,1,1,"unsigned short",6);
+      _cimg_save_pandore_case(0,1,1,"short",6);
       _cimg_save_pandore_case(0,1,1,"unsigned int",6);
       _cimg_save_pandore_case(0,1,1,"int",6);
-      _cimg_save_pandore_case(0,1,1,"unsigned long",7);
-      _cimg_save_pandore_case(0,1,1,"long",6);
+      _cimg_save_pandore_case(0,1,1,"unsigned int64",6);
+      _cimg_save_pandore_case(0,1,1,"int64",6);
       _cimg_save_pandore_case(0,1,1,"float",7);
       _cimg_save_pandore_case(0,1,1,"double",7);
 
       _cimg_save_pandore_case(0,0,1,"unsigned char",8);
       _cimg_save_pandore_case(0,0,1,"char",9);
-      _cimg_save_pandore_case(0,0,1,"short",9);
       _cimg_save_pandore_case(0,0,1,"unsigned short",9);
+      _cimg_save_pandore_case(0,0,1,"short",9);
       _cimg_save_pandore_case(0,0,1,"unsigned int",9);
       _cimg_save_pandore_case(0,0,1,"int",9);
-      _cimg_save_pandore_case(0,0,1,"unsigned long",10);
-      _cimg_save_pandore_case(0,0,1,"long",9);
+      _cimg_save_pandore_case(0,0,1,"unsigned int64",9);
+      _cimg_save_pandore_case(0,0,1,"int64",9);
       _cimg_save_pandore_case(0,0,1,"float",10);
       _cimg_save_pandore_case(0,0,1,"double",10);
 
       _cimg_save_pandore_case(0,1,3,"unsigned char",16);
       _cimg_save_pandore_case(0,1,3,"char",17);
-      _cimg_save_pandore_case(0,1,3,"short",17);
       _cimg_save_pandore_case(0,1,3,"unsigned short",17);
+      _cimg_save_pandore_case(0,1,3,"short",17);
       _cimg_save_pandore_case(0,1,3,"unsigned int",17);
       _cimg_save_pandore_case(0,1,3,"int",17);
-      _cimg_save_pandore_case(0,1,3,"unsigned long",18);
-      _cimg_save_pandore_case(0,1,3,"long",17);
+      _cimg_save_pandore_case(0,1,3,"unsigned int64",17);
+      _cimg_save_pandore_case(0,1,3,"int64",17);
       _cimg_save_pandore_case(0,1,3,"float",18);
       _cimg_save_pandore_case(0,1,3,"double",18);
 
       _cimg_save_pandore_case(0,0,3,"unsigned char",19);
       _cimg_save_pandore_case(0,0,3,"char",20);
-      _cimg_save_pandore_case(0,0,3,"short",20);
       _cimg_save_pandore_case(0,0,3,"unsigned short",20);
+      _cimg_save_pandore_case(0,0,3,"short",20);
       _cimg_save_pandore_case(0,0,3,"unsigned int",20);
       _cimg_save_pandore_case(0,0,3,"int",20);
-      _cimg_save_pandore_case(0,0,3,"unsigned long",21);
-      _cimg_save_pandore_case(0,0,3,"long",20);
+      _cimg_save_pandore_case(0,0,3,"unsigned int64",20);
+      _cimg_save_pandore_case(0,0,3,"int64",20);
       _cimg_save_pandore_case(0,0,3,"float",21);
       _cimg_save_pandore_case(0,0,3,"double",21);
 
       _cimg_save_pandore_case(1,1,0,"unsigned char",22);
       _cimg_save_pandore_case(1,1,0,"char",23);
-      _cimg_save_pandore_case(1,1,0,"short",23);
       _cimg_save_pandore_case(1,1,0,"unsigned short",23);
+      _cimg_save_pandore_case(1,1,0,"short",23);
       _cimg_save_pandore_case(1,1,0,"unsigned int",23);
       _cimg_save_pandore_case(1,1,0,"int",23);
-      _cimg_save_pandore_case(1,1,0,"unsigned long",25);
-      _cimg_save_pandore_case(1,1,0,"long",23);
+      _cimg_save_pandore_case(1,1,0,"unsigned int64",23);
+      _cimg_save_pandore_case(1,1,0,"int64",23);
       _cimg_save_pandore_case(1,1,0,"float",25);
       _cimg_save_pandore_case(1,1,0,"double",25);
 
       _cimg_save_pandore_case(0,1,0,"unsigned char",26);
       _cimg_save_pandore_case(0,1,0,"char",27);
-      _cimg_save_pandore_case(0,1,0,"short",27);
       _cimg_save_pandore_case(0,1,0,"unsigned short",27);
+      _cimg_save_pandore_case(0,1,0,"short",27);
       _cimg_save_pandore_case(0,1,0,"unsigned int",27);
       _cimg_save_pandore_case(0,1,0,"int",27);
-      _cimg_save_pandore_case(0,1,0,"unsigned long",29);
-      _cimg_save_pandore_case(0,1,0,"long",27);
+      _cimg_save_pandore_case(0,1,0,"unsigned int64",27);
+      _cimg_save_pandore_case(0,1,0,"int64",27);
       _cimg_save_pandore_case(0,1,0,"float",29);
       _cimg_save_pandore_case(0,1,0,"double",29);
 
       _cimg_save_pandore_case(0,0,0,"unsigned char",30);
       _cimg_save_pandore_case(0,0,0,"char",31);
-      _cimg_save_pandore_case(0,0,0,"short",31);
       _cimg_save_pandore_case(0,0,0,"unsigned short",31);
+      _cimg_save_pandore_case(0,0,0,"short",31);
       _cimg_save_pandore_case(0,0,0,"unsigned int",31);
       _cimg_save_pandore_case(0,0,0,"int",31);
-      _cimg_save_pandore_case(0,0,0,"unsigned long",33);
-      _cimg_save_pandore_case(0,0,0,"long",31);
+      _cimg_save_pandore_case(0,0,0,"unsigned int64",31);
+      _cimg_save_pandore_case(0,0,0,"int64",31);
       _cimg_save_pandore_case(0,0,0,"float",33);
       _cimg_save_pandore_case(0,0,0,"double",33);
 
@@ -45451,6 +50304,11 @@ namespace cimg_library_suffixed {
                                     "save_graphicsmagick_external(): Specified filename is (null).",
                                     cimg_instance);
       if (is_empty()) { cimg::fempty(0,filename); return *this; }
+      if (_depth>1)
+        cimg::warn(_cimg_instance
+                   "save_other(): File '%s', saving a volumetric image with an external call to "
+                   "GraphicsMagick only writes the first image slice.",
+                   cimg_instance,filename);
 
 #ifdef cimg_use_png
 #define _cimg_sge_ext1 "png"
@@ -45503,7 +50361,11 @@ namespace cimg_library_suffixed {
                                     "save_imagemagick_external(): Specified filename is (null).",
                                     cimg_instance);
       if (is_empty()) { cimg::fempty(0,filename); return *this; }
-
+      if (_depth>1)
+        cimg::warn(_cimg_instance
+                   "save_other(): File '%s', saving a volumetric image with an external call to "
+                   "ImageMagick only writes the first image slice.",
+                   cimg_instance,filename);
 #ifdef cimg_use_png
 #define _cimg_sie_ext1 "png"
 #define _cimg_sie_ext2 "png"
@@ -45607,6 +50469,11 @@ namespace cimg_library_suffixed {
                                     "save_other(): Specified filename is (null).",
                                     cimg_instance);
       if (is_empty()) { cimg::fempty(0,filename); return *this; }
+      if (_depth>1)
+        cimg::warn(_cimg_instance
+                   "save_other(): File '%s', saving a volumetric image with an external call to "
+                   "ImageMagick or GraphicsMagick only writes the first image slice.",
+                   cimg_instance,filename);
 
       const unsigned int omode = cimg::exception_mode();
       bool is_saved = true;
@@ -45645,7 +50512,7 @@ namespace cimg_library_suffixed {
       CImg<T> res(40,38,1,3);
       const unsigned char *ptrs = cimg::logo40x38;
       T *ptr1 = res.data(0,0,0,0), *ptr2 = res.data(0,0,0,1), *ptr3 = res.data(0,0,0,2);
-      for (unsigned long off = 0; off<(unsigned long)res._width*res._height;) {
+      for (ulongT off = 0; off<(ulongT)res._width*res._height;) {
         const unsigned char n = *(ptrs++), r = *(ptrs++), g = *(ptrs++), b = *(ptrs++);
         for (unsigned int l = 0; l<n; ++off, ++l) { *(ptr1++) = (T)r; *(ptr2++) = (T)g; *(ptr3++) = (T)b; }
       }
@@ -45707,7 +50574,7 @@ namespace cimg_library_suffixed {
     **/
     typedef T value_type;
 
-    // Define common T-dependant types.
+    // Define common types related to template type T.
     typedef typename cimg::superset<T,bool>::type Tbool;
     typedef typename cimg::superset<T,unsigned char>::type Tuchar;
     typedef typename cimg::superset<T,char>::type Tchar;
@@ -45715,8 +50582,8 @@ namespace cimg_library_suffixed {
     typedef typename cimg::superset<T,short>::type Tshort;
     typedef typename cimg::superset<T,unsigned int>::type Tuint;
     typedef typename cimg::superset<T,int>::type Tint;
-    typedef typename cimg::superset<T,unsigned long>::type Tulong;
-    typedef typename cimg::superset<T,long>::type Tlong;
+    typedef typename cimg::superset<T,cimg_ulong>::type Tulong;
+    typedef typename cimg::superset<T,cimg_long>::type Tlong;
     typedef typename cimg::superset<T,float>::type Tfloat;
     typedef typename cimg::superset<T,double>::type Tdouble;
     typedef typename cimg::last<T,bool>::type boolT;
@@ -45726,8 +50593,10 @@ namespace cimg_library_suffixed {
     typedef typename cimg::last<T,short>::type shortT;
     typedef typename cimg::last<T,unsigned int>::type uintT;
     typedef typename cimg::last<T,int>::type intT;
-    typedef typename cimg::last<T,unsigned long>::type ulongT;
-    typedef typename cimg::last<T,long>::type longT;
+    typedef typename cimg::last<T,cimg_ulong>::type ulongT;
+    typedef typename cimg::last<T,cimg_long>::type longT;
+    typedef typename cimg::last<T,cimg_uint64>::type uint64T;
+    typedef typename cimg::last<T,cimg_int64>::type int64T;
     typedef typename cimg::last<T,float>::type floatT;
     typedef typename cimg::last<T,double>::type doubleT;
 
@@ -45856,11 +50725,11 @@ namespace cimg_library_suffixed {
       _width(0),_allocated_width(0),_data(0) {
 #define _CImgList_stdarg(t) { \
 	assign(n,width,height,depth,spectrum); \
-	const unsigned long siz = (unsigned long)width*height*depth*spectrum, nsiz = siz*n; \
+	const ulongT siz = (ulongT)width*height*depth*spectrum, nsiz = siz*n; \
 	T *ptrd = _data->_data; \
 	va_list ap; \
 	va_start(ap,val1); \
-	for (unsigned long l = 0, s = 0, i = 0; i<nsiz; ++i) { \
+	for (ulongT l = 0, s = 0, i = 0; i<nsiz; ++i) { \
 	  *(ptrd++) = (T)(i==0?val0:(i==1?val1:va_arg(ap,t))); \
 	  if ((++s)==siz) { ptrd = _data[++l]._data; s = 0; } \
 	} \
@@ -46366,8 +51235,7 @@ namespace cimg_library_suffixed {
        \note Can be used to exchange the content of two lists in a fast way.
     **/
     CImgList<T>& swap(CImgList<T>& list) {
-      cimg::swap(_width,list._width);
-      cimg::swap(_allocated_width,list._allocated_width);
+      cimg::swap(_width,list._width,_allocated_width,list._allocated_width);
       cimg::swap(_data,list._data);
       return list;
     }
@@ -46384,6 +51252,12 @@ namespace cimg_library_suffixed {
       return _empty.assign();
     }
 
+    //! Return a reference to an empty list \const.
+    static const CImgList<T>& const_empty() {
+      static const CImgList<T> _empty;
+      return _empty;
+    }
+
     //@}
     //------------------------------------------
     //
@@ -47925,8 +52799,9 @@ namespace cimg_library_suffixed {
        \return A one-column vector containing the selected image indexes.
     **/
     CImg<intT> get_select(CImgDisplay &disp, const bool feature_type=true,
-                          const char axis='x', const float align=0) const {
-      return _get_select(disp,0,feature_type,axis,align,0,false,false,false);
+                          const char axis='x', const float align=0,
+                          const bool exit_on_anykey=false) const {
+      return _get_select(disp,0,feature_type,axis,align,exit_on_anykey,0,false,false,false);
     }
 
     //! Display a simple interactive interface to select images or sublists.
@@ -47938,13 +52813,14 @@ namespace cimg_library_suffixed {
        \return A one-column vector containing the selected image indexes.
     **/
     CImg<intT> get_select(const char *const title, const bool feature_type=true,
-                          const char axis='x', const float align=0) const {
+                          const char axis='x', const float align=0,
+                          const bool exit_on_anykey=false) const {
       CImgDisplay disp;
-      return _get_select(disp,title,feature_type,axis,align,0,false,false,false);
+      return _get_select(disp,title,feature_type,axis,align,exit_on_anykey,0,false,false,false);
     }
 
     CImg<intT> _get_select(CImgDisplay &disp, const char *const title, const bool feature_type,
-                           const char axis, const float align,
+                           const char axis, const float align, const bool exit_on_anykey,
                            const unsigned int orig, const bool resize_disp,
                            const bool exit_on_rightbutton, const bool exit_on_wheel) const {
       if (is_empty())
@@ -47983,7 +52859,7 @@ namespace cimg_library_suffixed {
       bool old_is_resized = disp.is_resized();
       disp._normalization = 0;
       disp.show().set_key(0);
-      const unsigned char foreground_color[] = { 255,255,255 }, background_color[] = { 0,0,0 };
+      static const unsigned char foreground_color[] = { 255,255,255 }, background_color[] = { 0,0,0 };
 
       // Enter event loop.
       CImg<ucharT> visu0, visu;
@@ -47992,6 +52868,7 @@ namespace cimg_library_suffixed {
       int oindice0 = -1, oindice1 = -1, indice0 = -1, indice1 = -1;
       bool is_clicked = false, is_selected = false, text_down = false, update_display = true;
       unsigned int key = 0;
+
       while (!is_selected && !disp.is_closed() && !key) {
 
         // Create background image.
@@ -48095,6 +52972,7 @@ namespace cimg_library_suffixed {
         if (disp.button()&2 && exit_on_rightbutton) { is_selected = true; indice1 = indice0 = -1; }
         if (disp.wheel() && exit_on_wheel) is_selected = true;
 
+        CImg<charT> filename(32);
         switch (key = disp.key()) {
 #if cimg_OS!=2
         case cimg::keyCTRLRIGHT :
@@ -48124,10 +53002,9 @@ namespace cimg_library_suffixed {
           } break;
         case cimg::keyS : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
             static unsigned int snap_number = 0;
-            char filename[32] = { 0 };
             std::FILE *file;
             do {
-              cimg_snprintf(filename,sizeof(filename),cimg_appname "_%.4u.bmp",snap_number++);
+              cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.bmp",snap_number++);
               if ((file=std::fopen(filename,"r"))!=0) cimg::fclose(file);
             } while (file);
             if (visu0) {
@@ -48135,20 +53012,19 @@ namespace cimg_library_suffixed {
                                  foreground_color,background_color,0.7f,13).display(disp);
               visu0.save(filename);
               (+visu0).draw_text(0,0," Snapshot '%s' saved. ",
-                                 foreground_color,background_color,0.7f,13,filename).display(disp);
+                                 foreground_color,background_color,0.7f,13,filename._data).display(disp);
             }
             disp.set_key(key,false).wait(); key = 0;
           } break;
         case cimg::keyO :
           if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) {
             static unsigned int snap_number = 0;
-            char filename[32] = { 0 };
             std::FILE *file;
             do {
 #ifdef cimg_use_zlib
-              cimg_snprintf(filename,sizeof(filename),cimg_appname "_%.4u.cimgz",snap_number++);
+              cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.cimgz",snap_number++);
 #else
-              cimg_snprintf(filename,sizeof(filename),cimg_appname "_%.4u.cimg",snap_number++);
+              cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.cimg",snap_number++);
 #endif
               if ((file=std::fopen(filename,"r"))!=0) cimg::fclose(file);
             } while (file);
@@ -48156,13 +53032,17 @@ namespace cimg_library_suffixed {
                                foreground_color,background_color,0.7f,13).display(disp);
             save(filename);
             (+visu0).draw_text(0,0," Instance '%s' saved. ",
-                               foreground_color,background_color,0.7f,13,filename).display(disp);
+                               foreground_color,background_color,0.7f,13,filename._data).display(disp);
             disp.set_key(key,false).wait(); key = 0;
           } break;
         }
         if (disp.is_resized()) { disp.resize(false); visu0.assign(); }
         if (ym>=0 && ym<13) { if (!text_down) { visu.assign(); text_down = true; }}
         else if (ym>=visu.height() - 13) { if(text_down) { visu.assign(); text_down = false; }}
+        if (!exit_on_anykey && key && key!=cimg::keyESC &&
+            (key!=cimg::keyW || (!disp.is_keyCTRLLEFT() && !disp.is_keyCTRLRIGHT()))) {
+          key = 0;
+        }
       }
       CImg<intT> res(1,2,1,1,-1);
       if (is_selected) {
@@ -48335,7 +53215,7 @@ namespace cimg_library_suffixed {
    Bytef *const cbuf = new Bytef[csiz]; \
    cimg::fread(cbuf,csiz,nfile); \
    raw.assign(W,H,D,C); \
-   unsigned long destlen = (unsigned long)raw.size()*sizeof(Tss); \
+   uLongf destlen = (ulongT)raw.size()*sizeof(Tss); \
    uncompress((Bytef*)raw._data,&destlen,cbuf,csiz); \
    delete[] cbuf; \
    if (endian!=cimg::endianness()) cimg::invert_endianness(raw._data,raw.size()); \
@@ -48366,12 +53246,12 @@ namespace cimg_library_suffixed {
             else { \
               img.assign(W,H,D,C); \
               T *ptrd = img._data; \
-              for (unsigned long to_read = img.size(); to_read; ) { \
-                raw.assign(cimg::min(to_read,cimg_iobuffer)); \
+              for (ulongT to_read = img.size(); to_read; ) { \
+                raw.assign((unsigned int)cimg::min(to_read,cimg_iobuffer)); \
                 cimg::fread(raw._data,raw._width,nfile); \
                 if (endian!=cimg::endianness()) cimg::invert_endianness(raw._data,raw.size()); \
                 const Tss *ptrs = raw._data; \
-                for (unsigned long off = (unsigned long)raw._width; off; --off) *(ptrd++) = (T)*(ptrs++); \
+                for (ulongT off = (ulongT)raw._width; off; --off) *(ptrd++) = (T)*(ptrs++); \
                 to_read-=raw._width; \
               } \
             } \
@@ -48385,18 +53265,18 @@ namespace cimg_library_suffixed {
                                     "load_cimg(): Specified filename is (null).",
                                     cimglist_instance);
 
-      const unsigned long cimg_iobuffer = 24*1024*1024;
+      const ulongT cimg_iobuffer = (ulongT)24*1024*1024;
       std::FILE *const nfile = file?file:cimg::fopen(filename,"rb");
       bool loaded = false, endian = cimg::endianness();
       CImg<charT> tmp(256), str_pixeltype(256), str_endian(256);
       *tmp = *str_pixeltype = *str_endian = 0;
       unsigned int j, N = 0, W, H, D, C;
-      unsigned long csiz;
+      ulongT csiz;
       int i, err;
       do {
         j = 0; while ((i=std::fgetc(nfile))!='\n' && i>=0 && j<255) tmp[j++] = (char)i; tmp[j] = 0;
       } while (*tmp=='#' && i>=0);
-      err = cimg_sscanf(tmp,"%u%*c%255[A-Za-z_]%*c%255[sA-Za-z_ ]",
+      err = cimg_sscanf(tmp,"%u%*c%255[A-Za-z64_]%*c%255[sA-Za-z_ ]",
                         &N,str_pixeltype._data,str_endian._data);
       if (err<2) {
         if (!file) cimg::fclose(nfile);
@@ -48418,9 +53298,12 @@ namespace cimg_library_suffixed {
       _cimg_load_cimg_case("unsigned_int",unsigned int);
       _cimg_load_cimg_case("uint",unsigned int);
       _cimg_load_cimg_case("int",int);
-      _cimg_load_cimg_case("unsigned_long",unsigned long);
-      _cimg_load_cimg_case("ulong",unsigned long);
-      _cimg_load_cimg_case("long",long);
+      _cimg_load_cimg_case("unsigned_long",ulongT);
+      _cimg_load_cimg_case("ulong",ulongT);
+      _cimg_load_cimg_case("long",longT);
+      _cimg_load_cimg_case("unsigned_int64",uint64T);
+      _cimg_load_cimg_case("uint64",uint64T);
+      _cimg_load_cimg_case("int64",int64T);
       _cimg_load_cimg_case("float",float);
       _cimg_load_cimg_case("double",double);
 
@@ -48505,7 +53388,7 @@ namespace cimg_library_suffixed {
                                   cimglist_instance, \
                                   W,H,D,C,l,filename?filename:"(FILE*)"); \
           if (W*H*D*C>0) { \
-            if (l<nn0 || nx0>=W || ny0>=H || nz0>=D || nc0>=C) std::fseek(nfile,W*H*D*C*sizeof(Tss),SEEK_CUR); \
+            if (l<nn0 || nx0>=W || ny0>=H || nz0>=D || nc0>=C) cimg::fseek(nfile,W*H*D*C*sizeof(Tss),SEEK_CUR); \
             else { \
               const unsigned int \
                 _nx1 = nx1==~0U?W - 1:nx1, \
@@ -48523,32 +53406,32 @@ namespace cimg_library_suffixed {
               CImg<T> &img = _data[l - nn0]; \
               img.assign(1 + _nx1 - nx0,1 + _ny1 - ny0,1 + _nz1 - nz0,1 + _nc1 - nc0); \
               T *ptrd = img._data; \
-              const unsigned int skipvb = nc0*W*H*D*sizeof(Tss); \
-              if (skipvb) std::fseek(nfile,skipvb,SEEK_CUR); \
+              ulongT skipvb = nc0*W*H*D*sizeof(Tss); \
+              if (skipvb) cimg::fseek(nfile,skipvb,SEEK_CUR); \
               for (unsigned int c = 1 + _nc1 - nc0; c; --c) { \
-                const unsigned int skipzb = nz0*W*H*sizeof(Tss); \
-                if (skipzb) std::fseek(nfile,skipzb,SEEK_CUR); \
+                const ulongT skipzb = nz0*W*H*sizeof(Tss); \
+                if (skipzb) cimg::fseek(nfile,skipzb,SEEK_CUR); \
                 for (unsigned int z = 1 + _nz1 - nz0; z; --z) { \
-                  const unsigned int skipyb = ny0*W*sizeof(Tss); \
-                  if (skipyb) std::fseek(nfile,skipyb,SEEK_CUR); \
+                  const ulongT skipyb = ny0*W*sizeof(Tss); \
+                  if (skipyb) cimg::fseek(nfile,skipyb,SEEK_CUR); \
                   for (unsigned int y = 1 + _ny1 - ny0; y; --y) { \
-                    const unsigned int skipxb = nx0*sizeof(Tss); \
-                    if (skipxb) std::fseek(nfile,skipxb,SEEK_CUR); \
+                    const ulongT skipxb = nx0*sizeof(Tss); \
+                    if (skipxb) cimg::fseek(nfile,skipxb,SEEK_CUR); \
                     cimg::fread(raw._data,raw._width,nfile); \
                     if (endian!=cimg::endianness()) cimg::invert_endianness(raw._data,raw._width); \
                     const Tss *ptrs = raw._data; \
                     for (unsigned int off = raw._width; off; --off) *(ptrd++) = (T)*(ptrs++); \
-                    const unsigned int skipxe = (W - 1 - _nx1)*sizeof(Tss); \
-                    if (skipxe) std::fseek(nfile,skipxe,SEEK_CUR); \
+                    const ulongT skipxe = (W - 1 - _nx1)*sizeof(Tss); \
+                    if (skipxe) cimg::fseek(nfile,skipxe,SEEK_CUR); \
                   } \
-                  const unsigned int skipye = (H - 1 - _ny1)*W*sizeof(Tss); \
-                  if (skipye) std::fseek(nfile,skipye,SEEK_CUR); \
+                  const ulongT skipye = (H - 1 - _ny1)*W*sizeof(Tss); \
+                  if (skipye) cimg::fseek(nfile,skipye,SEEK_CUR); \
                 } \
-                const unsigned int skipze = (D - 1 - _nz1)*W*H*sizeof(Tss); \
-                if (skipze) std::fseek(nfile,skipze,SEEK_CUR); \
+                const ulongT skipze = (D - 1 - _nz1)*W*H*sizeof(Tss); \
+                if (skipze) cimg::fseek(nfile,skipze,SEEK_CUR); \
               } \
-              const unsigned int skipve = (C - 1 - _nc1)*W*H*D*sizeof(Tss); \
-              if (skipve) std::fseek(nfile,skipve,SEEK_CUR); \
+              const ulongT skipve = (C - 1 - _nc1)*W*H*D*sizeof(Tss); \
+              if (skipve) cimg::fseek(nfile,skipve,SEEK_CUR); \
             } \
           } \
         } \
@@ -48572,8 +53455,8 @@ namespace cimg_library_suffixed {
       *tmp = *str_pixeltype = *str_endian = 0;
       unsigned int j, N, W, H, D, C;
       int i, err;
-      j = 0; while((i=std::fgetc(nfile))!='\n' && i!=EOF && j<256) tmp[j++] = (char)i; tmp[j] = 0;
-      err = cimg_sscanf(tmp,"%u%*c%255[A-Za-z_]%*c%255[sA-Za-z_ ]",
+      j = 0; while ((i=std::fgetc(nfile))!='\n' && i!=EOF && j<256) tmp[j++] = (char)i; tmp[j] = 0;
+      err = cimg_sscanf(tmp,"%u%*c%255[A-Za-z64_]%*c%255[sA-Za-z_ ]",
                         &N,str_pixeltype._data,str_endian._data);
       if (err<2) {
         if (!file) cimg::fclose(nfile);
@@ -48602,9 +53485,12 @@ namespace cimg_library_suffixed {
       _cimg_load_cimg_case2("unsigned_int",unsigned int);
       _cimg_load_cimg_case2("uint",unsigned int);
       _cimg_load_cimg_case2("int",int);
-      _cimg_load_cimg_case2("unsigned_long",unsigned long);
-      _cimg_load_cimg_case2("ulong",unsigned long);
-      _cimg_load_cimg_case2("long",long);
+      _cimg_load_cimg_case2("unsigned_long",ulongT);
+      _cimg_load_cimg_case2("ulong",ulongT);
+      _cimg_load_cimg_case2("long",longT);
+      _cimg_load_cimg_case2("unsigned_int64",uint64T);
+      _cimg_load_cimg_case2("uint64",uint64T);
+      _cimg_load_cimg_case2("int64",int64T);
       _cimg_load_cimg_case2("float",float);
       _cimg_load_cimg_case2("double",double);
       if (!loaded) {
@@ -48805,7 +53691,7 @@ namespace cimg_library_suffixed {
       bool stop_flag = false;
       int err;
       if (nfirst_frame) {
-        err = std::fseek(nfile,nfirst_frame*(size_x*size_y + size_x*size_y/2),SEEK_CUR);
+        err = cimg::fseek(nfile,nfirst_frame*(size_x*size_y + size_x*size_y/2),SEEK_CUR);
         if (err) {
           if (!file) cimg::fclose(nfile);
           throw CImgIOException(_cimglist_instance
@@ -48818,7 +53704,7 @@ namespace cimg_library_suffixed {
       for (frame = nfirst_frame; !stop_flag && frame<=nlast_frame; frame+=nstep_frame) {
         tmp.fill(0);
         // *TRY* to read the luminance part, do not replace by cimg::fread!
-        err = (int)std::fread((void*)(tmp._data),1,(unsigned long)tmp._width*tmp._height,nfile);
+        err = (int)std::fread((void*)(tmp._data),1,(ulongT)tmp._width*tmp._height,nfile);
         if (err!=(int)(tmp._width*tmp._height)) {
           stop_flag = true;
           if (err>0)
@@ -48847,7 +53733,7 @@ namespace cimg_library_suffixed {
             }
             if (yuv2rgb) tmp.YCbCrtoRGB();
             insert(tmp);
-	    if (nstep_frame>1) std::fseek(nfile,(nstep_frame - 1)*(size_x*size_y + size_x*size_y/2),SEEK_CUR);
+	    if (nstep_frame>1) cimg::fseek(nfile,(nstep_frame - 1)*(size_x*size_y + size_x*size_y/2),SEEK_CUR);
           }
         }
       }
@@ -48867,7 +53753,7 @@ namespace cimg_library_suffixed {
       \param first_frame Index of the first frame to read.
       \param last_frame Index of the last frame to read.
       \param step_frame Step value for frame reading.
-      \note If step_frame==0, the current video stream is open or released without any frames read.
+      \note If step_frame==0, the current video stream is forced to be released (without any frames read).
     **/
     CImgList<T>& load_video(const char *const filename,
                             const unsigned int first_frame=0, const unsigned int last_frame=~0U,
@@ -48910,7 +53796,7 @@ namespace cimg_library_suffixed {
         } else
           if (filename)
             cimg::warn(_cimglist_instance
-                       "load_video() : File '%s', opened video stream associated with filename not found.",
+                       "load_video() : File '%s', no opened video stream associated with filename found.",
                        cimglist_instance,filename);
           else
             cimg::warn(_cimglist_instance
@@ -48980,7 +53866,7 @@ namespace cimg_library_suffixed {
           if (step>0) cimg_forY(frame,y) {
               cimg_forX(frame,x) { *(ptr_b++) = (T)*(ptrs++); *(ptr_g++) = (T)*(ptrs++); *(ptr_r++) = (T)*(ptrs++); }
               ptrs+=step;
-            } else for (unsigned long siz = (unsigned long)src->width*src->height; siz; --siz) {
+            } else for (ulongT siz = (ulongT)src->width*src->height; siz; --siz) {
               *(ptr_b++) = (T)*(ptrs++); *(ptr_g++) = (T)*(ptrs++); *(ptr_r++) = (T)*(ptrs++);
             }
           frame.move_to(*this);
@@ -49309,10 +54195,10 @@ namespace cimg_library_suffixed {
       cimglist_for(*this,l) msiz+=_data[l].size();
       msiz*=sizeof(T);
       const unsigned int mdisp = msiz<8*1024?0U:msiz<8*1024*1024?1U:2U;
-      char _title[64] = { 0 };
-      if (!title) cimg_snprintf(_title,sizeof(_title),"CImgList<%s>",pixel_type());
+      CImg<charT> _title(64);
+      if (!title) cimg_snprintf(_title,_title._width,"CImgList<%s>",pixel_type());
       std::fprintf(cimg::output(),"%s%s%s%s: %sthis%s = %p, %ssize%s = %u/%u [%u %s], %sdata%s = (CImg<%s>*)%p",
-                   cimg::t_magenta,cimg::t_bold,title?title:_title,cimg::t_normal,
+                   cimg::t_magenta,cimg::t_bold,title?title:_title._data,cimg::t_normal,
                    cimg::t_bold,cimg::t_normal,(void*)this,
                    cimg::t_bold,cimg::t_normal,_width,_allocated_width,
                    mdisp==0?msiz:(mdisp==1?(msiz>>10):(msiz>>20)),
@@ -49360,9 +54246,9 @@ namespace cimg_library_suffixed {
     **/
     const CImgList<T>& display(CImgDisplay &disp, const bool display_info,
                                const char axis='x', const float align=0,
-                               unsigned int *const XYZ=0) const {
+                               unsigned int *const XYZ=0, const bool exit_on_anykey=false) const {
       bool is_exit = false;
-      return _display(disp,0,display_info,axis,align,XYZ,0,true,is_exit);
+      return _display(disp,0,display_info,axis,align,XYZ,exit_on_anykey,0,true,is_exit);
     }
 
     //! Display the current CImgList instance in a new display window.
@@ -49374,15 +54260,16 @@ namespace cimg_library_suffixed {
     **/
     const CImgList<T>& display(const char *const title=0, const bool display_info=true,
                                const char axis='x', const float align=0,
-                               unsigned int *const XYZ=0) const {
+                               unsigned int *const XYZ=0, const bool exit_on_anykey=false) const {
       CImgDisplay disp;
       bool is_exit = false;
-      return _display(disp,title,display_info,axis,align,XYZ,0,true,is_exit);
+      return _display(disp,title,display_info,axis,align,XYZ,exit_on_anykey,0,true,is_exit);
     }
 
     const CImgList<T>& _display(CImgDisplay &disp, const char *const title, const bool display_info,
                                 const char axis, const float align, unsigned int *const XYZ,
-                                const unsigned int orig, const bool is_first_call, bool &is_exit) const {
+                                const bool exit_on_anykey, const unsigned int orig, const bool is_first_call,
+                                bool &is_exit) const {
       if (is_empty())
         throw CImgInstanceException(_cimglist_instance
                                     "display(): Empty instance.",
@@ -49423,13 +54310,13 @@ namespace cimg_library_suffixed {
           disp.resize(cimg_fitscreen(_data[0]._width,_data[0]._height,_data[0]._depth),false).
             set_title("%s (%ux%ux%ux%u)",
                       dtitle.data(),_data[0]._width,_data[0]._height,_data[0]._depth,_data[0]._spectrum);
-        _data[0]._display(disp,0,false,XYZ,!is_first_call);
+        _data[0]._display(disp,0,false,XYZ,exit_on_anykey,!is_first_call);
         if (disp.key()) is_exit = true;
         disp.resize(cimg_fitscreen(dw,dh,1),false).set_title("%s",dtitle.data());
       } else {
         bool disp_resize = !is_first_call;
         while (!disp.is_closed() && !is_exit) {
-          const CImg<intT> s = _get_select(disp,0,true,axis,align,orig,disp_resize,!is_first_call,true);
+          const CImg<intT> s = _get_select(disp,0,true,axis,align,exit_on_anykey,orig,disp_resize,!is_first_call,true);
           disp_resize = true;
           if (s[0]<0) { // No selections done.
             if (disp.button()&2) { disp.flush(); break; }
@@ -49444,10 +54331,12 @@ namespace cimg_library_suffixed {
                 ind0 = (unsigned int)cimg::max(0,s[0] - (int)delta),
                 ind1 = (unsigned int)cimg::min(width() - 1,s[0] + (int)delta);
               if ((ind0!=0 || ind1!=_width - 1) && ind1 - ind0>=3)
-                get_shared_images(ind0,ind1)._display(disp,0,false,axis,align,XYZ,orig + ind0,false,is_exit);
+                get_shared_images(ind0,ind1)._display(disp,0,false,axis,align,XYZ,exit_on_anykey,
+                                                      orig + ind0,false,is_exit);
             }
           } else if (s[0]!=0 || s[1]!=width() - 1)
-            get_shared_images(s[0],s[1])._display(disp,0,false,axis,align,XYZ,orig + s[0],false,is_exit);
+            get_shared_images(s[0],s[1])._display(disp,0,false,axis,align,XYZ,exit_on_anykey,
+                                                  orig + s[0],false,is_exit);
         }
       }
       return *this;
@@ -49581,7 +54470,7 @@ namespace cimg_library_suffixed {
        \param fps Number of desired frames per second.
        \param nb_loops Number of loops (\c 0 for infinite looping).
     **/
-    const CImgList<T>& save_gif_external(const char *const filename, const unsigned int fps=25,
+    const CImgList<T>& save_gif_external(const char *const filename, const float fps=25,
                                          const unsigned int nb_loops=0) {
       CImg<charT> command(1024), filename_tmp(256), filename_tmp2(256);
       CImgList<charT> filenames;
@@ -49607,15 +54496,15 @@ namespace cimg_library_suffixed {
       }
 
 #if cimg_OS!=2
-      cimg_snprintf(command,command._width,"%s -delay 1x%u -loop %u",
-                    cimg::imagemagick_path(),fps,nb_loops);
+      cimg_snprintf(command,command._width,"%s -delay %u -loop %u",
+                    cimg::imagemagick_path(),(unsigned int)cimg::max(0.0f,cimg::round(100/fps)),nb_loops);
       CImg<ucharT>::string(command).move_to(filenames,0);
       cimg_snprintf(command,command._width,"\"%s\" >/dev/null 2>&1",
                     CImg<charT>::string(filename)._system_strescape().data());
       CImg<ucharT>::string(command).move_to(filenames);
 #else
-      cimg_snprintf(command,command._width,"\"%s -delay 1x%u -loop %u",
-                    cimg::imagemagick_path(),fps,nb_loops);
+      cimg_snprintf(command,command._width,"\"%s -delay %u -loop %u",
+                    cimg::imagemagick_path(),(unsigned int)cimg::max(0.0f,cimg::round(100/fps)),nb_loops);
       CImg<ucharT>::string(command).move_to(filenames,0);
       cimg_snprintf(command,command._width,"\"%s\"\" >NUL 2>&1",
                     CImg<charT>::string(filename)._system_strescape().data());
@@ -49654,9 +54543,9 @@ namespace cimg_library_suffixed {
       cimglist_for(*this,l) {
         CImg<ucharT> YCbCr((*this)[l]);
         if (is_rgb) YCbCr.RGBtoYCbCr();
-        cimg::fwrite(YCbCr._data,(unsigned long)YCbCr._width*YCbCr._height,nfile);
+        cimg::fwrite(YCbCr._data,(size_t)YCbCr._width*YCbCr._height,nfile);
         cimg::fwrite(YCbCr.get_resize(YCbCr._width/2, YCbCr._height/2,1,3,3).data(0,0,0,1),
-                     (unsigned long)YCbCr._width*YCbCr._height/2,nfile);
+                     (size_t)YCbCr._width*YCbCr._height/2,nfile);
       }
       if (!file) cimg::fclose(nfile);
       return *this;
@@ -49707,8 +54596,8 @@ namespace cimg_library_suffixed {
           bool failed_to_compress = true;
           if (is_compressed) {
 #ifdef cimg_use_zlib
-            const unsigned long siz = sizeof(T)*ref.size();
-            unsigned long csiz = siz + siz/100 + 16;
+            const ulongT siz = sizeof(T)*ref.size();
+            uLongf csiz = siz + siz/100 + 16;
             Bytef *const cbuf = new Bytef[csiz];
             if (compress(cbuf,&csiz,(Bytef*)ref._data,siz))
               cimg::warn(_cimglist_instance
@@ -49758,7 +54647,7 @@ namespace cimg_library_suffixed {
 #define _cimg_save_cimg_case(Ts,Tss) \
       if (!saved && !cimg::strcasecmp(Ts,str_pixeltype)) { \
         for (unsigned int l = 0; l<lmax; ++l) { \
-          j = 0; while((i=std::fgetc(nfile))!='\n') tmp[j++]=(char)i; tmp[j] = 0; \
+          j = 0; while ((i=std::fgetc(nfile))!='\n') tmp[j++]=(char)i; tmp[j] = 0; \
           W = H = D = C = 0; \
           if (cimg_sscanf(tmp,"%u %u %u %u",&W,&H,&D,&C)!=4) \
             throw CImgIOException(_cimglist_instance \
@@ -49766,7 +54655,7 @@ namespace cimg_library_suffixed {
                                   cimglist_instance, \
                                   W,H,D,C,l,filename?filename:"(FILE*)"); \
           if (W*H*D*C>0) { \
-            if (l<n0 || x0>=W || y0>=H || z0>=D || c0>=D) std::fseek(nfile,W*H*D*C*sizeof(Tss),SEEK_CUR); \
+            if (l<n0 || x0>=W || y0>=H || z0>=D || c0>=D) cimg::fseek(nfile,W*H*D*C*sizeof(Tss),SEEK_CUR); \
             else { \
               const CImg<T>& img = (*this)[l - n0]; \
               const T *ptrs = img._data; \
@@ -49781,31 +54670,31 @@ namespace cimg_library_suffixed {
                 nc1 = c1>=C?C - 1:c1; \
               CImg<Tss> raw(1 + nx1 - x0); \
               const unsigned int skipvb = c0*W*H*D*sizeof(Tss); \
-              if (skipvb) std::fseek(nfile,skipvb,SEEK_CUR); \
+              if (skipvb) cimg::fseek(nfile,skipvb,SEEK_CUR); \
               for (unsigned int v = 1 + nc1 - c0; v; --v) { \
                 const unsigned int skipzb = z0*W*H*sizeof(Tss); \
-                if (skipzb) std::fseek(nfile,skipzb,SEEK_CUR); \
+                if (skipzb) cimg::fseek(nfile,skipzb,SEEK_CUR); \
                 for (unsigned int z = 1 + nz1 - z0; z; --z) { \
                   const unsigned int skipyb = y0*W*sizeof(Tss); \
-                  if (skipyb) std::fseek(nfile,skipyb,SEEK_CUR); \
+                  if (skipyb) cimg::fseek(nfile,skipyb,SEEK_CUR); \
                   for (unsigned int y = 1 + ny1 - y0; y; --y) { \
                     const unsigned int skipxb = x0*sizeof(Tss); \
-                    if (skipxb) std::fseek(nfile,skipxb,SEEK_CUR); \
+                    if (skipxb) cimg::fseek(nfile,skipxb,SEEK_CUR); \
                     raw.assign(ptrs, raw._width); \
                     ptrs+=img._width; \
                     if (endian) cimg::invert_endianness(raw._data,raw._width); \
                     cimg::fwrite(raw._data,raw._width,nfile); \
                     const unsigned int skipxe = (W - 1 - nx1)*sizeof(Tss); \
-                    if (skipxe) std::fseek(nfile,skipxe,SEEK_CUR); \
+                    if (skipxe) cimg::fseek(nfile,skipxe,SEEK_CUR); \
                   } \
                   const unsigned int skipye = (H - 1 - ny1)*W*sizeof(Tss); \
-                  if (skipye) std::fseek(nfile,skipye,SEEK_CUR); \
+                  if (skipye) cimg::fseek(nfile,skipye,SEEK_CUR); \
                 } \
                 const unsigned int skipze = (D - 1 - nz1)*W*H*sizeof(Tss); \
-                if (skipze) std::fseek(nfile,skipze,SEEK_CUR); \
+                if (skipze) cimg::fseek(nfile,skipze,SEEK_CUR); \
               } \
               const unsigned int skipve = (C - 1 - nc1)*W*H*D*sizeof(Tss); \
-              if (skipve) std::fseek(nfile,skipve,SEEK_CUR); \
+              if (skipve) cimg::fseek(nfile,skipve,SEEK_CUR); \
             } \
           } \
         } \
@@ -49828,8 +54717,8 @@ namespace cimg_library_suffixed {
       *tmp = *str_pixeltype = *str_endian = 0;
       unsigned int j, N, W, H, D, C;
       int i, err;
-      j = 0; while((i=std::fgetc(nfile))!='\n' && i!=EOF && j<256) tmp[j++] = (char)i; tmp[j] = 0;
-      err = cimg_sscanf(tmp,"%u%*c%255[A-Za-z_]%*c%255[sA-Za-z_ ]",&N,str_pixeltype._data,str_endian._data);
+      j = 0; while ((i=std::fgetc(nfile))!='\n' && i!=EOF && j<256) tmp[j++] = (char)i; tmp[j] = 0;
+      err = cimg_sscanf(tmp,"%u%*c%255[A-Za-z64_]%*c%255[sA-Za-z_ ]",&N,str_pixeltype._data,str_endian._data);
       if (err<2) {
         if (!file) cimg::fclose(nfile);
         throw CImgIOException(_cimglist_instance
@@ -49850,9 +54739,9 @@ namespace cimg_library_suffixed {
       _cimg_save_cimg_case("unsigned_int",unsigned int);
       _cimg_save_cimg_case("uint",unsigned int);
       _cimg_save_cimg_case("int",int);
-      _cimg_save_cimg_case("unsigned_long",unsigned long);
-      _cimg_save_cimg_case("ulong",unsigned long);
-      _cimg_save_cimg_case("long",long);
+      _cimg_save_cimg_case("unsigned_int64",uint64T);
+      _cimg_save_cimg_case("uint64",uint64T);
+      _cimg_save_cimg_case("int64",int64T);
       _cimg_save_cimg_case("float",float);
       _cimg_save_cimg_case("double",double);
       if (!saved) {
@@ -49903,11 +54792,11 @@ namespace cimg_library_suffixed {
                                 const unsigned int dx, const unsigned int dy,
                                 const unsigned int dz, const unsigned int dc) {
       std::FILE *const nfile = file?file:cimg::fopen(filename,"wb");
-      const unsigned long siz = (unsigned long)dx*dy*dz*dc*sizeof(T);
+      const ulongT siz = (ulongT)dx*dy*dz*dc*sizeof(T);
       std::fprintf(nfile,"%u %s\n",nb,pixel_type());
       for (unsigned int i=nb; i; --i) {
         std::fprintf(nfile,"%u %u %u %u\n",dx,dy,dz,dc);
-	for (unsigned long off=siz; off; --off) std::fputc(0,nfile);
+	for (ulongT off = siz; off; --off) std::fputc(0,nfile);
       }
       if (!file) cimg::fclose(nfile);
     }
@@ -49950,7 +54839,8 @@ namespace cimg_library_suffixed {
       \param compression_type Compression mode used to write data.
     **/
     const CImgList<T>& save_tiff(const char *const filename, const unsigned int compression_type=0,
-                                 const float *const voxel_size=0, const char *const description=0) const {
+                                 const float *const voxel_size=0, const char *const description=0,
+                                 const bool use_bigtiff=true) const {
       if (!filename)
         throw CImgArgumentException(_cimglist_instance
                                     "save_tiff(): Specified filename is (null).",
@@ -49958,21 +54848,21 @@ namespace cimg_library_suffixed {
       if (is_empty()) { cimg::fempty(0,filename); return *this; }
 
 #ifndef cimg_use_tiff
-      if (_width==1) _data[0].save_tiff(filename,compression_type,voxel_size,description);
+      if (_width==1) _data[0].save_tiff(filename,compression_type,voxel_size,description,use_bigtiff);
       else cimglist_for(*this,l) {
           CImg<charT> nfilename(1024);
           cimg::number_filename(filename,l,6,nfilename);
-          _data[l].save_tiff(nfilename,compression_type,voxel_size,description);
+          _data[l].save_tiff(nfilename,compression_type,voxel_size,description,use_bigtiff);
         }
 #else
-      TIFF *tif = TIFFOpen(filename,"w");
+      ulongT siz = 0;
+      cimglist_for(*this,l) siz+=_data[l].size();
+      const bool _use_bigtiff = use_bigtiff && sizeof(siz)>=8 && siz*sizeof(T)>=1UL<<31; // No bigtiff for small images.
+      TIFF *tif = TIFFOpen(filename,_use_bigtiff?"w8":"w4");
       if (tif) {
         for (unsigned int dir = 0, l = 0; l<_width; ++l) {
           const CImg<T>& img = (*this)[l];
-          if (img) {
-            if (img._depth==1) img._save_tiff(tif,dir++,compression_type,voxel_size,description);
-            else cimg_forZ(img,z) img.get_slice(z)._save_tiff(tif,dir++,compression_type,voxel_size,description);
-          }
+          cimg_forZ(img,z) img._save_tiff(tif,dir++,z,compression_type,voxel_size,description);
         }
         TIFFClose(tif);
       } else
@@ -50096,7 +54986,7 @@ namespace cimg_library_suffixed {
 
 #define _cimg_docase(x) ((x)>='a'&&(x)<='z'?(x) + 'A' - 'a':(x))
         const char
-          *const _codec = codec?codec:"mp4v",
+          *const _codec = codec && *codec?codec:"mp4v",
           codec0 = _cimg_docase(_codec[0]),
           codec1 = _codec[0]?_cimg_docase(_codec[1]):0,
           codec2 = _codec[1]?_cimg_docase(_codec[2]):0,
@@ -50261,8 +55151,8 @@ namespace cimg_library_suffixed {
           bool failed_to_compress = true;
           if (is_compressed) {
 #ifdef cimg_use_zlib
-            const unsigned long siz = sizeof(T)*ref.size();
-            unsigned long csiz = compressBound(siz);
+            const ulongT siz = sizeof(T)*ref.size();
+            uLongf csiz = (ulongT)compressBound(siz);
             Bytef *const cbuf = new Bytef[csiz];
             if (compress(cbuf,&csiz,(Bytef*)ref._data,siz))
               cimg::warn(_cimglist_instance
@@ -50296,11 +55186,11 @@ namespace cimg_library_suffixed {
         Bytef *cbuf = (Bytef*)stream; \
         if (sizeof(t)!=1 || cimg::type<t>::string()==cimg::type<bool>::string()) { \
           cbuf = new Bytef[csiz]; Bytef *_cbuf = cbuf; \
-          for (unsigned long i = 0; i<csiz; ++i) *(_cbuf++) = (Bytef)*(stream++); \
+          for (ulongT i = 0; i<csiz; ++i) *(_cbuf++) = (Bytef)*(stream++); \
           is_bytef = false; \
         } else { stream+=csiz; is_bytef = true; } \
         CImg<Tss> raw(W,H,D,C); \
-        unsigned long destlen = (unsigned long)raw.size()*sizeof(Tss); \
+        uLongf destlen = raw.size()*sizeof(Tss); \
         uncompress((Bytef*)raw._data,&destlen,cbuf,csiz); \
         if (!is_bytef) delete[] cbuf; \
         if (endian!=cimg::endianness()) cimg::invert_endianness(raw._data,raw.size()); \
@@ -50348,14 +55238,14 @@ namespace cimg_library_suffixed {
       CImg<charT> tmp(256), str_pixeltype(256), str_endian(256);
       *tmp = *str_pixeltype = *str_endian = 0;
       unsigned int j, N = 0, W, H, D, C;
-      unsigned long csiz;
+      ulongT csiz;
       int i, err;
       cimg::unused(is_bytef);
       do {
         j = 0; while ((i=(int)*stream)!='\n' && stream<estream && j<255) { ++stream; tmp[j++] = (char)i; }
         ++stream; tmp[j] = 0;
       } while (*tmp=='#' && stream<estream);
-      err = cimg_sscanf(tmp,"%u%*c%255[A-Za-z_]%*c%255[sA-Za-z_ ]",
+      err = cimg_sscanf(tmp,"%u%*c%255[A-Za-z64_]%*c%255[sA-Za-z_ ]",
                         &N,str_pixeltype._data,str_endian._data);
       if (err<2)
         throw CImgArgumentException("CImgList<%s>::get_unserialize(): CImg header not found in serialized buffer.",
@@ -50373,9 +55263,9 @@ namespace cimg_library_suffixed {
       _cimg_unserialize_case("unsigned_int",unsigned int);
       _cimg_unserialize_case("uint",unsigned int);
       _cimg_unserialize_case("int",int);
-      _cimg_unserialize_case("unsigned_long",unsigned long);
-      _cimg_unserialize_case("ulong",unsigned long);
-      _cimg_unserialize_case("long",long);
+      _cimg_unserialize_case("unsigned_int64",uint64T);
+      _cimg_unserialize_case("uint64",uint64T);
+      _cimg_unserialize_case("int64",int64T);
       _cimg_unserialize_case("float",float);
       _cimg_unserialize_case("double",double);
       if (!loaded)
@@ -50422,13 +55312,13 @@ namespace cimg_library_suffixed {
        \param is_variable_width Decide if the font has a variable (\c true) or fixed (\c false) width.
     **/
     static const CImgList<ucharT>& font(const unsigned int font_height, const bool is_variable_width=true) {
-      if (!font_height) return CImgList<ucharT>::empty();
+      if (!font_height) return CImgList<ucharT>::const_empty();
       cimg::mutex(11);
 
       // Decompress nearest base font data if needed.
-      const char *data_fonts[] = { cimg::data_font12x13, cimg::data_font20x23, cimg::data_font47x53, 0 };
-      const unsigned int data_widths[] = { 12,20,47,90 }, data_heights[] = { 13,23,53,103 },
-        data_Ms[] = { 86,79,57,47 };
+      static const char *data_fonts[] = { cimg::data_font12x13, cimg::data_font20x23, cimg::data_font47x53, 0 };
+      static const unsigned int data_widths[] = { 12,20,47,90 }, data_heights[] = { 13,23,53,103 },
+                                data_Ms[] = { 86,79,57,47 };
       const unsigned int data_ind = font_height<=13U?0U:font_height<=23U?1U:font_height<=53U?2U:3U;
       static CImg<ucharT> base_fonts[4];
       CImg<ucharT> &base_font = base_fonts[data_ind];
@@ -51172,7 +56062,7 @@ namespace cimg {
     char *pd = _path;
     for (char *ps = pd; *ps; ++ps) { if (*ps!='/' || *ps!=*(ps+1)) *(pd++) = *ps; }
     *pd = 0;
-    unsigned int lp = std::strlen(_path);
+    unsigned int lp = (unsigned int)std::strlen(_path);
     if (!_is_pattern && lp && _path[lp - 1]=='/') {
       _path[lp - 1] = 0; --lp;
 #if cimg_OS!=2
@@ -51192,7 +56082,7 @@ namespace cimg {
       } else { // No path to folder specified, assuming current folder.
         is_current = true; *_path = 0;
       }
-      lp = std::strlen(_path);
+      lp = (unsigned int)std::strlen(_path);
     }
 
     // Windows version.
@@ -51204,11 +56094,11 @@ namespace cimg {
     }
     WIN32_FIND_DATAA file_data;
     const HANDLE dir = FindFirstFileA(pattern.data(),&file_data);
-    if (dir==INVALID_HANDLE_VALUE) return CImgList<char>::empty();
+    if (dir==INVALID_HANDLE_VALUE) return CImgList<char>::const_empty();
     do {
       const char *const filename = file_data.cFileName;
       if (*filename!='.' || (filename[1] && (filename[1]!='.' || filename[2]))) {
-        const unsigned int lf = std::strlen(filename);
+        const unsigned int lf = (unsigned int)std::strlen(filename);
         const bool is_directory = (file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)!=0;
         if ((!mode && !is_directory) || (mode==1 && is_directory) || mode>=2) {
           if (include_path) {
@@ -51225,12 +56115,12 @@ namespace cimg {
     // Unix version (posix).
 #else
     DIR *const dir = opendir(is_root?"/":is_current?".":_path.data());
-    if (!dir) return CImgList<char>::empty();
+    if (!dir) return CImgList<char>::const_empty();
     struct dirent *ent;
     while ((ent=readdir(dir))!=0) {
       const char *const filename = ent->d_name;
       if (*filename!='.' || (filename[1] && (filename[1]!='.' || filename[2]))) {
-        const unsigned int lf = std::strlen(filename);
+        const unsigned int lf = (unsigned int)std::strlen(filename);
         CImg<char> full_filename(lp + lf + 2);
 
         if (!is_current) {
@@ -51329,7 +56219,8 @@ namespace cimg {
      \note Use the \c libcurl library, or the external binaries \c wget or \c curl to perform the download.
   **/
   inline char *load_network(const char *const url, char *const filename_local,
-                            const unsigned int timeout, const bool try_fallback) {
+                            const unsigned int timeout, const bool try_fallback,
+                            const char *const referer) {
     if (!url)
       throw CImgArgumentException("cimg::load_network(): Specified URL is (null).");
     if (!filename_local)
@@ -51364,10 +56255,11 @@ namespace cimg {
         curl_easy_setopt(curl,CURLOPT_FOLLOWLOCATION,1L);
         if (timeout) curl_easy_setopt(curl,CURLOPT_TIMEOUT,(long)timeout);
         if (std::strchr(url,'?')) curl_easy_setopt(curl,CURLOPT_HTTPGET,1L);
+        if (referer) curl_easy_setopt(curl,CURLOPT_REFERER,referer);
         res = curl_easy_perform(curl);
         curl_easy_cleanup(curl);
-        std::fseek(file,0,SEEK_END); // Check if file size is 0.
-        const long siz = std::ftell(file);
+        cimg::fseek(file,0,SEEK_END); // Check if file size is 0.
+        const cimg_ulong siz = cimg::ftell(file);
         cimg::fclose(file);
         if (siz>0 && res==CURLE_OK) {
           cimg::exception_mode(omode);
@@ -51383,23 +56275,41 @@ namespace cimg {
     cimg::unused(try_fallback);
 
     // Try with 'curl' first.
-    if (timeout)
-      cimg_snprintf(command,command._width,"%s -m %u -f --silent --compressed -o \"%s\" \"%s\"",
-                    cimg::curl_path(),timeout,filename_local,url);
-    else
-      cimg_snprintf(command,command._width,"%s -f --silent --compressed -o \"%s\" \"%s\"",
-                    cimg::curl_path(),filename_local,url);
+    if (timeout) {
+      if (referer)
+        cimg_snprintf(command,command._width,"%s -e %s -m %u -f --silent --compressed -o \"%s\" \"%s\"",
+                      cimg::curl_path(),referer,timeout,filename_local,url);
+      else
+        cimg_snprintf(command,command._width,"%s -m %u -f --silent --compressed -o \"%s\" \"%s\"",
+                      cimg::curl_path(),timeout,filename_local,url);
+    } else {
+      if (referer)
+        cimg_snprintf(command,command._width,"%s -e %s -f --silent --compressed -o \"%s\" \"%s\"",
+                      cimg::curl_path(),referer,filename_local,url);
+      else
+        cimg_snprintf(command,command._width,"%s -f --silent --compressed -o \"%s\" \"%s\"",
+                      cimg::curl_path(),filename_local,url);
+    }
     cimg::system(command);
 
     if (!(file = std::fopen(filename_local,"rb"))) {
 
       // Try with 'wget' otherwise.
-      if (timeout)
-        cimg_snprintf(command,command._width,"%s -T %u -q -r -l 0 --no-cache -O \"%s\" \"%s\"",
-                      cimg::wget_path(),timeout,filename_local,url);
-      else
-        cimg_snprintf(command,command._width,"%s -q -r -l 0 --no-cache -O \"%s\" \"%s\"",
-                      cimg::wget_path(),filename_local,url);
+      if (timeout) {
+        if (referer)
+          cimg_snprintf(command,command._width,"%s --referer=%s -T %u -q -r -l 0 --no-cache -O \"%s\" \"%s\"",
+                        cimg::wget_path(),referer,timeout,filename_local,url);
+        else
+          cimg_snprintf(command,command._width,"%s -T %u -q -r -l 0 --no-cache -O \"%s\" \"%s\"",
+                        cimg::wget_path(),timeout,filename_local,url);
+      } else {
+        if (referer)
+          cimg_snprintf(command,command._width,"%s --referer=%s -q -r -l 0 --no-cache -O \"%s\" \"%s\"",
+                        cimg::wget_path(),referer,filename_local,url);
+        else
+          cimg_snprintf(command,command._width,"%s -q -r -l 0 --no-cache -O \"%s\" \"%s\"",
+                        cimg::wget_path(),filename_local,url);
+      }
       cimg::system(command);
 
       if (!(file = std::fopen(filename_local,"rb")))
@@ -51420,7 +56330,7 @@ namespace cimg {
         file = std::fopen(filename_local,"rb");
       }
     }
-    std::fseek(file,0,SEEK_END); // Check if file size is 0.
+    cimg::fseek(file,0,SEEK_END); // Check if file size is 0.
     if (std::ftell(file)<=0)
       throw CImgIOException("cimg::load_network(): Failed to load URL '%s' with external commands "
                             "'wget' or 'curl'.",url);
@@ -51429,11 +56339,11 @@ namespace cimg {
   }
 
   // Implement a tic/toc mechanism to display elapsed time of algorithms.
-  inline unsigned long tictoc(const bool is_tic) {
+  inline cimg_ulong tictoc(const bool is_tic) {
     cimg::mutex(2);
-    static CImg<unsigned long> times(64);
+    static CImg<cimg_ulong> times(64);
     static unsigned int pos = 0;
-    const unsigned long t1 = cimg::time();
+    const cimg_ulong t1 = cimg::time();
     if (is_tic) { // Tic.
       times[pos++] = t1;
       if (pos>=times._width)
@@ -51444,9 +56354,9 @@ namespace cimg {
     // Toc.
     if (!pos)
       throw CImgArgumentException("cimg::toc(): No previous call to 'cimg::tic()' has been made.");
-    const unsigned long
+    const cimg_ulong
       t0 = times[--pos],
-      dt = t1>=t0?(t1 - t0):cimg::type<unsigned long>::max();
+      dt = t1>=t0?(t1 - t0):cimg::type<cimg_ulong>::max();
     const unsigned int
       edays = (unsigned int)(dt/86400000.0),
       ehours = (unsigned int)((dt - edays*86400000.0)/3600000.0),
@@ -51480,7 +56390,7 @@ namespace cimg {
   }
 
   // Return a temporary string describing the size of a memory buffer.
-  inline const char *strbuffersize(const unsigned long size) {
+  inline const char *strbuffersize(const cimg_ulong size) {
     static CImg<char> res(256);
     cimg::mutex(5);
     if (size<1024LU) cimg_snprintf(res,res._width,"%lu byte%s",size,size>1?"s":"");
@@ -51522,7 +56432,7 @@ namespace cimg {
                  logo._data,is_centered);
     throw CImgIOException("cimg::dialog(): No display available.");
 #else
-    const unsigned char
+    static const unsigned char
       black[] = { 0,0,0 }, white[] = { 255,255,255 }, gray[] = { 200,200,200 }, gray2[] = { 150,150,150 };
 
     // Create buttons and canvas graphics
@@ -51724,6 +56634,9 @@ namespace cil = cimg_library_suffixed;
 #ifdef _cimg_redefine_PI
 #define PI 3.141592653589793238462643383
 #endif
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
 
 #endif
 // Local Variables:
diff --git a/README.txt b/README.txt
index 8785b7e..64dd4e0 100644
--- a/README.txt
+++ b/README.txt
@@ -36,6 +36,7 @@
   - Maksim Aizenshtein
   - Alberto Albiol
   - Antonio Albiol
+  - Neil Brown
   - Haz-Edine Assemlal
   - Vincent Barra
   - Wolf Blecher
diff --git a/examples/CImg_demo.cpp b/examples/CImg_demo.cpp
index 1150d89..7142145 100644
--- a/examples/CImg_demo.cpp
+++ b/examples/CImg_demo.cpp
@@ -421,7 +421,7 @@ void* item_soccer_bobs() {
   CImg<unsigned char> foot(data_foot,200,200,1,3,false), canvas0(640,480,1,3,0);
   const unsigned char color[] = { 255, 255, 0 };
   float zoom = 0.2f;
-  cimg_forXY(canvas0,x,y) canvas0(x,y,1) = (unsigned char)(20 + (y*215/canvas0.height()) + 19*cimg::crand());
+  cimg_forXY(canvas0,x,y) canvas0(x,y,1) = (unsigned char)(20 + (y*215/canvas0.height()) + 19*cimg::rand(-1,1));
   canvas0.draw_text(5,5,"Left/Right Mouse Button = Zoom In/Out\nMiddle Button = Reset Screen",color);
   CImgList<unsigned char> canvas(16,canvas0);
   CImg<float> mask(foot.width(),foot.height());
@@ -649,7 +649,7 @@ void* item_plasma() {
 // Item : Oriented Convolutions
 //------------------------------
 void* item_oriented_convolutions() {
-  const CImg<unsigned char> img = CImg<unsigned char>(data_lena,256,256,1,1,false).noise(50,2);
+  const CImg<unsigned char> img = CImg<float>(data_milla,211,242,1,3).RGBtoYCbCr().channel(0).noise(50,2);
   CImgList<unsigned char> visu = (img,img,img);
   CImg<float> mask(16,16);
   const float value = 255;
@@ -682,11 +682,11 @@ void* item_shade_bobs() {
   while (!disp.is_closed() && !disp.is_keyQ() && !disp.is_keyESC()) {
     if ((t+=0.015f)>4*cimg::PI) {
       img.fill(0);
-      rx = (float)(cimg::crand());
-      ry = (float)(cimg::crand());
-      rz = (float)(cimg::crand());
-      rt = (float)(cimg::crand());
-      rcx = 0.6f*(float)(cimg::crand());
+      rx = (float)(cimg::rand(-1,1));
+      ry = (float)(cimg::rand(-1,1));
+      rz = (float)(cimg::rand(-1,1));
+      rt = (float)(cimg::rand(-1,1));
+      rcx = 0.6f*(float)(cimg::rand(-1,1));
       t = 0;
       palette = CImg<unsigned char>(3,4 + (int)(12*cimg::rand()),1,1,0).noise(255,2).resize(3,256,1,1,3);
       palette(0) = palette(1) = palette(2) = 0;
@@ -727,7 +727,7 @@ void* item_shade_bobs() {
 // Item : Fourier Filtering
 //-------------------------
 void* item_fourier_filtering() {
-  const CImg<unsigned char> img = CImg<unsigned char>(data_lena,256,256,1,1,false).resize(256,256);
+  const CImg<unsigned char> img = CImg<float>(data_milla,211,242,1,3).RGBtoYCbCr().channel(0).resize(256,256);
   CImgList<float> F = img.get_FFT();
   cimglist_apply(F,shift)(img.width()/2,img.height()/2,0,0,2);
   const CImg<unsigned char> mag = ((F[0].get_pow(2) + F[1].get_pow(2)).sqrt() + 1).log().normalize(0,255);
@@ -1035,7 +1035,7 @@ void* item_fireworks() {
 
     if (disp.button()&1 || !particles.size() || (--time)<0) {
       particles.insert(CImg<>::vector((float)cimg::rand()*img.width(),(float)img.height(),
-                                      (float)cimg::crand()*4,-6 - (float)cimg::rand()*3,
+                                      (float)cimg::rand(-1,1)*4,-6 - (float)cimg::rand()*3,
                                       30 + 60*(float)cimg::rand(),3));
       colors.insert(CImg<unsigned char>::vector(255,255,255));
       time = (float)(cimg::rand()*speed);
@@ -1094,9 +1094,9 @@ void* item_rubber_logo() {
   CImgList<unsigned int> colors(faces.size(),CImg<unsigned char>::vector(100,100,255));
   cimglist_for(colors,l) {
     const float x = (points(faces(l,0),0) + points(faces(l,1),0) + points(faces(l,2),0))/3;
-    if (x<30) colors[l] = CImg<unsigned char>::vector(255,100,100);
-    else { if (x<34) colors[l] = CImg<unsigned char>::vector(200,155,100);
-    else { if (x<55) colors[l] = CImg<unsigned char>::vector(100,255,155);
+    if (x<30.3) colors[l] = CImg<unsigned char>::vector(255,100,100);
+    else { if (x<34.6) colors[l] = CImg<unsigned char>::vector(200,155,100);
+    else { if (x<55.5) colors[l] = CImg<unsigned char>::vector(100,255,155);
     }}}
   faces.reverse_object3d();
   points.shift_object3d()*=5.5f;
@@ -1261,7 +1261,7 @@ void* item_breakout() {
         if (disp.is_resized()) disp.resize(disp);
       }
       board.fill(0); visu0 = background;
-      cimg_forXY(board,x,y) if (0.2f + cimg::crand()>=0) {
+      cimg_forXY(board,x,y) if (0.2f + cimg::rand(-1,1)>=0) {
         CImg<float> cbrick = CImg<double>::vector(100 + cimg::rand()*155,100 + cimg::rand()*155,100 + cimg::rand()*155).
           unroll('v').resize(brick.width(),brick.height());
         cimg_forC(cbrick,k) (cbrick.get_shared_channel(k).mul(brick))/=255;
@@ -1526,7 +1526,7 @@ void* item_word_puzzle() {
       *mention = completed?(timer<700?mention5:timer<800?mention4:timer<900?mention3:
                             timer<1000?mention2:timer<1200?mention1:mention0):mention0;
     canvas.assign().draw_text(0,0,"Final time : %d\n\n%s",white,0,1,32,timer,mention).resize(-100,-100,1,3);
-    ((background/=2)&CImg<unsigned char>(2,2).fill(0,255,255,0).resize(background,0,2)).
+    ((background/=2)&CImg<unsigned char>(2,2).fill((unsigned char)0,255,255,0).resize(background,0,2)).
       draw_image((background.width() - canvas.width())/2,(background.height() - canvas.height())/2,
                  canvas,canvas.get_dilate(3).dilate(3).dilate(3),1,255).display(disp.flush());
     while (!disp.is_closed() && !disp.key() && !disp.button()) disp.resize(disp).wait();
@@ -1586,16 +1586,16 @@ int main(int argc, char **argv) {
     // Demo selection menu
     //---------------------
     const unsigned char
-      white[]  = { 255, 255, 255 }, black[] = { 0, 0, 0 },     red[] = { 120, 50, 80 },
-      yellow[] = { 200, 155, 0 },   green[] = { 30, 200, 70 }, purple[] = { 175, 32, 186 },
-      blue[]   = { 55, 140, 185 },  grey[] = { 127, 127, 127 };
+      white[]  = { 255, 255, 255 }, black[] = { 0, 0, 0 }, red[] = { 120, 50, 80 },
+      yellow[] = { 200, 155, 0 }, green[] = { 30, 200, 70 }, purple[] = { 175, 32, 186 },
+      blue[] = { 55, 140, 185 }, grey[] = { 127, 127, 127 };
     float
       rx = 0, ry = 0, t = 0, gamma = 0, vgamma = 0, T = 0.9f,
-      nrx = (float)(2*cimg::crand()),
-      nry = (float)(2*cimg::crand());
+      nrx = (float)(2*cimg::rand(-1,1)),
+      nry = (float)(2*cimg::rand(-1,1));
     int y0 = 2*13;
     CImg<unsigned char> back(1,2,1,3,10), fore, text, img;
-    back.fillC(0,1,0,10,10,235).resize(320,420,1,3,3).get_shared_channel(2).noise(10,1).draw_plasma();
+    back.fillC(0,1,0,10,10,235).resize(350,570,1,3,3).get_shared_channel(2).noise(10,1).draw_plasma();
     back.draw_rectangle(0,y0 - 7,back.width() - 1,y0 + 20,red);
     fore.assign(back.width(),50,1,1,0).draw_text(20,y0 - 3,"** CImg %u.%u.%u Samples **",grey,0,1,23,
                                                 cimg_version/100,(cimg_version/10)%10,cimg_version%10);
@@ -1636,13 +1636,13 @@ int main(int argc, char **argv) {
                    "25- 3D Reflection\n"
                    "26- Fish-Eye Magnification\n"
                    "27- Word Puzzle\n",
-                   white,0,1,13).resize(-100,-100,1,3);
-    fore.resize(back,0).draw_image(20,y0 + 2*13,text|=text.get_dilate(3)>>4);
+                   white,0,1,18).resize(-100,-100,1,3);
+    fore.resize(back,0).draw_image(20,y0 + 3*13,text|=text.get_dilate(3)>>4);
 
     CImgDisplay disp(back,"CImg Library Samples",0,false,true);
     disp.move((disp.screen_width() - disp.window_width())/2,(disp.screen_height() - disp.window_height())/2);
     img = back; back*=0.15f;
-    for (y0+=2*13; !disp.is_closed() && !disp.is_keyQ() && !disp.is_keyESC(); demo_number = 0) {
+    for (y0+=3*13; !disp.is_closed() && !disp.is_keyQ() && !disp.is_keyESC(); demo_number = 0) {
       while (!demo_number && !disp.is_closed() && !disp.is_keyQ() && !disp.is_keyESC()) {
         img*=0.85f; img+=back;
         for (int i = 0; i<60; ++i) {
@@ -1660,23 +1660,22 @@ int main(int argc, char **argv) {
         }
         const unsigned char *ptrs = fore.data();
         cimg_for(img,ptrd,unsigned char) { const unsigned char val = *(ptrs++); if (val) *ptrd = val; }
-        int y = disp.mouse_y();
-        if (y>=y0 && y<y0 + 27*13) {
-          y = (y/13)*13 + 7;
-          for (int yy = y - 6; yy<=y + 6; ++yy)
-            img.draw_rectangle(0,yy,0,1,img.width() - 1,yy,0,1,(unsigned char)(130 - 15*cimg::abs(yy - y)));
-          img.draw_triangle(2,y - 4,2,y + 4,8,y,yellow).
-            draw_triangle(img.width() - 2,y - 4,img.width() - 2,y + 4,img.width() - 8,y,yellow);
+        const int y = (disp.mouse_y() - y0)/18, _y = 18*y + y0 + 9;
+        if (y>=0 && y<27) {
+          for (int yy = _y - 9; yy<=_y + 8; ++yy)
+            img.draw_rectangle(0,yy,0,1,img.width() - 1,yy,0,1,(unsigned char)(130 - 14*cimg::abs(yy - _y)));
+          img.draw_triangle(2,_y -  6,2,_y + 6,8,_y,yellow).
+            draw_triangle(img.width() - 2,_y - 6,img.width() - 2,_y + 6,img.width() - 8,_y,yellow);
         }
         gamma+=vgamma;
         if (gamma>1) {
           gamma = vgamma = 0;
           rx = nrx;
           ry = nry;
-          nrx=(float)(2*cimg::crand()); nry=(float)(2*cimg::crand());
+          nrx=(float)(2*cimg::rand(-1,1)); nry=(float)(2*cimg::rand(-1,1));
         }
-        t+=0.006f; T+=0.005f; if (T>1) { T-=(float)(1 + cimg::crand()); vgamma = 0.03f; }
-        if (disp.button()) { demo_number = 1 + (disp.mouse_y() - y0)/13; disp.set_button(); }
+        t+=0.006f; T+=0.005f; if (T>1) { T-=(float)(1 + cimg::rand(-1,1)); vgamma = 0.03f; }
+        if (disp.button()) { demo_number = 1 + (disp.mouse_y() - y0)/18; disp.set_button(); }
         disp.resize(disp,false).display(img).wait(25);
       }
       start_item(demo_number);
diff --git a/examples/Makefile b/examples/Makefile
index af16fdb..51527c6 100644
--- a/examples/Makefile
+++ b/examples/Makefile
@@ -86,17 +86,21 @@ CIMG_EXTRA_FILES = use_tiff_stream use_jpeg_buffer
 #---------------------------------
 CIMG_VERSION = _cimg_version
 X11PATH      = /usr/X11R6
-CC           = g++
 EXEPFX       =
-CCVER       = $(CC)
-ifeq ($(notdir $(CC)),g++)
-CCVER        = `$(CC) -v 2>&1 | tail -n 1`
+ifeq ($(MSYSTEM),MINGW32)
+EXESFX       = .exe
+else
+EXESFX       =
+endif
+CXXVER       = $(CXX)
+ifeq ($(notdir $(CXX)),g++)
+CXXVER       = `$(CXX) -v 2>&1 | tail -n 1`
 endif
-ifeq ($(notdir $(CC)),clang++)
-CCVER        = `$(CC) -v 2>&1 | head -n 1`
+ifeq ($(notdir $(CXX)),clang++)
+CXXVER       = `$(CXX) -v 2>&1 | head -n 1`
 endif
-ifeq ($(notdir $(CC)),icpc)
-CCVER        = "icpc \( `$(CC) -v 2>&1`\)"
+ifeq ($(notdir $(CXX)),icpc)
+CXXVER       = "icpc \( `$(CXX) -v 2>&1`\)"
 CFLAGS       = -I..
 LIBS         =
 else
@@ -109,10 +113,10 @@ endif
 #--------------------------------------------------
 
 # Flags to enable strict code standards
-ifeq ($(notdir $(CC)),icpc)
-CIMG_ANSI_CFLAGS = -std=c++11 -ansi
+ifeq ($(notdir $(CXX)),icpc)
+CIMG_ANSI_CFLAGS = -std=c++11
 else
-CIMG_ANSI_CFLAGS = -std=c++11 -ansi -pedantic
+CIMG_ANSI_CFLAGS = -std=c++11 -pedantic
 endif
 
 # Flags to enable code debugging.
@@ -123,10 +127,10 @@ CIMG_DEBUG_CFLAGS = -Dcimg_verbosity=3 -Dcimg_strict_warnings -g -fsanitize=addr
 CIMG_VT100_CFLAGS = -Dcimg_use_vt100
 
 # Flags to enable code optimization by the compiler.
-ifeq ($(notdir $(CC)),g++)
+ifeq ($(notdir $(CXX)),g++)
 CIMG_OPT_CFLAGS = -O2 -mtune=generic
 else
-ifeq ($(notdir $(CC)),icpc)
+ifeq ($(notdir $(CXX)),icpc)
 CIMG_OPT_CFLAGS = -fast
 else
 CIMG_OPT_CFLAGS = -O2
@@ -134,89 +138,117 @@ endif
 endif
 
 # Flags to enable OpenMP support.
-ifeq ($(notdir $(CC)),icpc)
+ifeq ($(notdir $(CXX)),icpc)
 CIMG_OPENMP_CFLAGS = #-Dcimg_use_openmp -openmp -i-static    # -> Seems to bug the compiler!
 else
-CIMG_OPENMP_CFLAGS = -Dcimg_use_openmp -fopenmp
+CIMG_OPENMP_DEFINE = -Dcimg_use_openmp -fopenmp
+CIMG_OPENMP_INCDIR =
+CIMG_OPENMP_CFLAGS = $(CIMG_OPENMP_DEFINE) $(CIMG_OPENMP_INCDIR)
 endif
 
 # Flags to enable OpenCV support.
-CIMG_OPENCV_CFLAGS = -Dcimg_use_opencv -I/usr/include/opencv
-CIMG_OPENCV_LIBS = -lopencv_core -lopencv_highgui
-#CIMG_OPENCV_LIBS = -lcv -lhighgui    #-> Use this for OpenCV < 2.2.0
+CIMG_OPENCV_DEFINE = -Dcimg_use_opencv
+CIMG_OPENCV_INCDIR = `pkg-config opencv --cflags || echo -I/usr/include/opencv` -I/usr/include/opencv
+CIMG_OPENCV_CFLAGS = $(CIMG_OPENCV_DEFINE) $(CIMG_OPENCV_INCDIR)
+CIMG_OPENCV_LIBS = `pkg-config opencv --libs || echo -lopencv_core -lopencv_highgui`
 
 # Flags used to disable display capablities of CImg
 CIMG_NODISPLAY_CFLAGS = -Dcimg_display=0
 
 # Flags to enable the use of the X11 library.
 # (X11 is used by CImg to handle display windows)
-# !!! For 64bits systems : replace -L$(X11PATH)/lib by -L$(X11PATH)/lib64 !!!
-CIMG_X11_CFLAGS = -I$(X11PATH)/include
-CIMG_X11_LIBS = -L$(X11PATH)/lib -lpthread -lX11
+CIMG_X11_DEFINE = -Dcimg_display=1
+CIMG_X11_INCDIR = `pkg-config --cflags x11 || echo -I/usr/X11R6/include`
+CIMG_X11_CFLAGS = $(CIMG_X11_DEFINE) $(CIMG_X11_INCDIR)
+CIMG_X11_LIBS = `pkg-config --libs x11 || echo -L/usr/X11R6/lib -lX11` -lpthread
 
 # Flags to enable fast image display, using the XSHM library (when using X11).
 # !!! Seems to randomly crash when used on MacOSX and 64bits systems, so use it only when necessary !!!
-CIMG_XSHM_CFLAGS = # -Dcimg_use_xshm
-CIMG_XSHM_LIBS = # -lXext
+CIMG_XSHM_CFLAGS = # -Dcimg_use_xshm `pkg-config --cflags xcb-shm`
+CIMG_XSHM_LIBS = # `pkg-config --libs xcb-shm || echo -L$(USR)/X11R6/lib -lXext`
 
 # Flags to enable GDI32 display (Windows native).
-CIMG_GDI32_CFLAGS = -mwindows
+CIMG_GDI32_DEFINE = -mwindows
+CIMG_GDI32_INCDIR =
+CIMG_GDI32_CFLAGS = $(CIMG_GDI32_DEFINE) $(CIMG_GDI32_INCDIR)
 CIMG_GDI32_LIBS = -lgdi32
 
 # Flags to enable screen mode switching, using the XRandr library (when using X11).
 # ( http://www.x.org/wiki/Projects/XRandR )
 # !!! Not supported by the X11 server on MacOSX, so do not use it on MacOSX !!!
-CIMG_XRANDR_CFLAGS = -Dcimg_use_xrandr
+CIMG_XRANDR_DEFINE = -Dcimg_use_xrandr
+CIMG_XRANDR_INCDIR =
+CIMG_XRANDR_CFLAGS = $(CIMG_XRANDR_DEFINE) $(CIMG_XRANDR_INCDIR)
 CIMG_XRANDR_LIBS = -lXrandr
 
 # Flags to enable native support for PNG image files, using the PNG library.
 # ( http://www.libpng.org/ )
-CIMG_PNG_CFLAGS = -Dcimg_use_png
+CIMG_PNG_DEFINE = -Dcimg_use_png
+CIMG_PNG_INCDIR =
+CIMG_PNG_CFLAGS = $(CIMG_PNG_DEFINE) $(CIMG_PNG_INCDIR)
 CIMG_PNG_LIBS = -lpng -lz
 
 # Flags to enable native support for JPEG image files, using the JPEG library.
 # ( http://www.ijg.org/ )
-CIMG_JPEG_CFLAGS = -Dcimg_use_jpeg
+CIMG_JPEG_DEFINE = -Dcimg_use_jpeg
+CIMG_JPEG_INCDIR =
+CIMG_JPEG_CFLAGS = $(CIMG_JPEG_DEFINE) $(CIMG_JPEG_INCDIR)
 CIMG_JPEG_LIBS = -ljpeg
 
 # Flags to enable native support for TIFF image files, using the TIFF library.
 # ( http://www.libtiff.org/ )
-CIMG_TIFF_CFLAGS = -Dcimg_use_tiff
+CIMG_TIFF_DEFINE = -Dcimg_use_tiff
+CIMG_TIFF_INCDIR =
+CIMG_TIFF_CFLAGS = $(CIMG_TIFF_DEFINE) $(CIMG_TIFF_INCDIR)
 CIMG_TIFF_LIBS = -ltiff
 
 # Flags to enable native support for MINC2 image files, using the MINC2 library.
 # ( http://en.wikibooks.org/wiki/MINC/Reference/MINC2.0_Users_Guide )
-CIMG_MINC2_CFLAGS = -Dcimg_use_minc2 -I${HOME}/local/include
+CIMG_MINC2_DEFINE = -Dcimg_use_minc2
+CIMG_MINC2_INCDIR = -I${HOME}/local/include
+CIMG_MINC2_CFLAGS = $(CIMG_MINC2_DEFINE) $(CIMG_MINC2_INCDIR)
 CIMG_MINC2_LIBS = -lminc_io -lvolume_io2 -lminc2 -lnetcdf -lhdf5 -lz -L${HOME}/local/lib
 
 # Flags to enable native support for EXR image files, using the OpenEXR library.
 # ( http://www.openexr.com/ )
-CIMG_EXR_CFLAGS = -Dcimg_use_openexr -I/usr/include/OpenEXR
+CIMG_EXR_DEFINE = -Dcimg_use_openexr
+CIMG_EXR_INCDIR = -I/usr/include/OpenEXR
+CIMG_EXR_CFLAGS = $(CIMG_EXR_DEFINE) $(CIMG_EXR_INCDIR)
 CIMG_EXR_LIBS = -lIlmImf -lHalf
 
 # Flags to enable native support for various video files, using the FFMPEG library.
 # ( http://www.ffmpeg.org/ )
-CIMG_FFMPEG_CFLAGS = -Dcimg_use_ffmpeg -D__STDC_CONSTANT_MACROS -I/usr/include/libavcodec -I/usr/include/libavformat -I/usr/include/libswscale -I/usr/include/ffmpeg
+CIMG_FFMPEG_DEFINE = -Dcimg_use_ffmpeg -D__STDC_CONSTANT_MACROS
+CIMG_FFMPEG_INCDIR = -I/usr/include/libavcodec -I/usr/include/libavformat -I/usr/include/libswscale -I/usr/include/ffmpeg
+CIMG_FFMPEG_CFLAGS = $(CIMG_FFMPEG_DEFINE) $(CIMG_FFMPEG_INCDIR)
 CIMG_FFMPEG_LIBS = -lavcodec -lavformat -lswscale
 
 # Flags to enable native support for compressed .cimgz files, using the Zlib library.
 # ( http://www.zlib.net/ )
-CIMG_ZLIB_CFLAGS = -Dcimg_use_zlib
-CIMG_ZLIB_LIBS = -lz
+CIMG_ZLIB_DEFINE = -Dcimg_use_zlib
+CIMG_ZLIB_INCDIR = `pkg-config --cflags zlib || echo -I$(USR)/$(INCLUDE)`
+CIMG_ZLIB_CFLAGS = $(CIMG_ZLIB_DEFINE) $(CIMG_ZLIB_INCDIR)
+CIMG_ZLIB_LIBS = `pkg-config --libs zlib || echo -lz`
 
 # Flags to enable native support for downloading files from the network.
 # ( http://curl.haxx.se/libcurl/ )
-CIMG_CURL_CFLAGS = -Dcimg_use_curl
+CIMG_CURL_DEFINE = -Dcimg_use_curl
+CIMG_CURL_INCDIR =
+CIMG_CURL_CFLAGS = $(CIMG_CURL_DEFINE)
 CIMG_CURL_LIBS = -lcurl
 
 # Flags to enable native support of most classical image file formats, using the Magick++ library.
 # ( http://www.imagemagick.org/Magick++/ )
-CIMG_MAGICK_CFLAGS = -Dcimg_use_magick `Magick++-config --cppflags` `Magick++-config --cxxflags`
-CIMG_MAGICK_LIBS = `Magick++-config --ldflags` `Magick++-config --libs`
+CIMG_MAGICK_DEFINE = -Dcimg_use_magick
+CIMG_MAGICK_INCDIR = `pkg-config --cflags GraphicsMagick++ || echo -I$(USR)/$(INCLUDE)/GraphicsMagick`
+CIMG_MAGICK_CFLAGS = $(CIMG_MAGICK_DEFINE) $(CIMG_MAGICK_INCDIR)
+CIMG_MAGICK_LIBS = `pkg-config --libs GraphicsMagick++ || echo -lGraphicsMagick++`
 
 # Flags to enable faster Discrete Fourier Transform computation, using the FFTW3 library
 # ( http://www.fftw.org/ )
-CIMG_FFTW3_CFLAGS = -Dcimg_use_fftw3
+CIMG_FFTW3_DEFINE = -Dcimg_use_fftw3
+CIMG_FFTW3_INCDIR =
+CIMG_FFTW3_CFLAGS = $(CIMG_FFTW3_DEFINE) $(CIMG_FFTW3_INCDIR)
 ifeq ($(OSTYPE),msys)
 CIMG_FFTW3_LIBS = -lfftw3-3
 else
@@ -225,12 +257,16 @@ endif
 
 # Flags to enable the use of LAPACK routines for matrix computation
 # ( http://www.netlib.org/lapack/ )
-CIMG_LAPACK_CFLAGS = -Dcimg_use_lapack
-CIMG_LAPACK_LIBS = -lblas -lg2c -llapack
+CIMG_LAPACK_DEFINE = -Dcimg_use_lapack
+CIMG_LAPACK_INCDIR =
+CIMG_LAPACK_CFLAGS = $(CIMG_LAPACK_DEFINE) $(CIMG_LAPACK_INCDIR)
+CIMG_LAPACK_LIBS = -lblas -llapack
 
 # Flags to enable the use of the Board library
 # ( http://libboard.sourceforge.net/ )
-CIMG_BOARD_CFLAGS = -Dcimg_use_board -I/usr/include/board
+CIMG_BOARD_DEFINE = -Dcimg_use_board
+CIMG_BOARD_INCDIR = -I/usr/include/board
+CIMG_BOARD_CFLAGS = $(CIMG_BOARD_DEFINE) $(CIMG_BOARD_INCDIR)
 CIMG_BOARD_LIBS = -lboard
 
 # Flags to compile on Sun Solaris
@@ -246,15 +282,11 @@ endif
 #-------------------------
 .cpp:
 	@echo
-	@echo "** Compiling '$* ($(CIMG_VERSION))' with '$(CCVER)'"
+	@echo "** Compiling '$* ($(CIMG_VERSION))' with '$(CXXVER)'"
 	@echo
-	$(CC) -o $(EXEPFX)$* $< $(CFLAGS) $(CONF_CFLAGS) $(LIBS) $(CONF_LIBS)
+	$(CXX) -o $(EXEPFX)$*$(EXESFX) $< $(CFLAGS) $(CONF_CFLAGS) $(LIBS) $(CONF_LIBS)
 ifeq ($(STRIP_EXE),true)
-ifeq ($(MSYSTEM),MINGW32)
-	strip $(EXEPFX)$*.exe
-else
-	strip $(EXEPFX)$*
-endif
+	strip $(EXEPFX)$*$(EXESFX)
 endif
 menu:
 	@echo
@@ -305,10 +337,12 @@ $(CIMG_ANSI_CFLAGS) \
 $(CIMG_VT100_CFLAGS) \
 $(CIMG_TIFF_CFLAGS) \
 $(CIMG_X11_CFLAGS) \
+$(CIMG_LAPACK_CFLAGS) \
 $(CIMG_XSHM_CFLAGS)" \
 "CONF_LIBS = \
 $(CIMG_X11_LIBS) \
 $(CIMG_TIFF_LIBS) \
+$(CIMG_LAPACK_LIBS) \
 $(CIMG_XSHM_LIBS)" \
 all $(CIMG_EXTRA_FILES)
 
diff --git a/examples/captcha.cpp b/examples/captcha.cpp
index 06a3c84..d8f962b 100644
--- a/examples/captcha.cpp
+++ b/examples/captcha.cpp
@@ -120,7 +120,7 @@ int main(int argc,char **argv) {
       }
       if (std::rand()%2) tmp = (tmp.get_dilate(3)-=tmp);
       tmp.blur((float)cimg::rand()*0.8f).normalize(0,255);
-      const float sin_offset = (float)cimg::crand()*3, sin_freq = (float)cimg::crand()/7;
+      const float sin_offset = (float)cimg::rand(-1,1)*3, sin_freq = (float)cimg::rand(-1,1)/7;
       cimg_forYC(captcha,y,v) captcha.get_shared_row(y,0,v).shift((int)(4*std::cos(y*sin_freq + sin_offset)));
       captcha.draw_image(6 + 40*k,tmp);
     }
diff --git a/examples/img/CImg_demo.h b/examples/img/CImg_demo.h
index 73aff28..7ca160c 100644
--- a/examples/img/CImg_demo.h
+++ b/examples/img/CImg_demo.h
@@ -7509,4105 +7509,6 @@ const unsigned char data_foot[] = {
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
 
-/* Define image 'lena' of size 256x256x1x1 and type 'const unsigned char' */
-const unsigned char data_lena[] = {
-  254, 254, 254, 254, 254, 254, 254, 254, 162, 165, 155, 156, 158, 158, 158, 155,
-  155, 156, 160, 162, 169, 169, 174, 177, 174, 169, 171, 162, 147, 155, 127, 114,
-  86, 86, 76, 98, 98, 98, 98, 96, 108, 101, 98, 108, 103, 101, 105, 101,
-  105, 105, 98, 98, 105, 117, 108, 119, 105, 117, 123, 119, 119, 125, 117, 133,
-  129, 133, 125, 129, 135, 131, 129, 125, 133, 127, 133, 127, 125, 125, 133, 133,
-  123, 125, 131, 131, 127, 125, 131, 131, 135, 133, 129, 129, 129, 137, 133, 133,
-  133, 129, 133, 129, 135, 131, 133, 131, 141, 127, 133, 129, 131, 129, 131, 127,
-  129, 135, 133, 129, 129, 127, 125, 127, 133, 129, 129, 133, 131, 131, 125, 131,
-  137, 133, 131, 127, 129, 127, 131, 127, 127, 129, 121, 133, 127, 125, 125, 133,
-  123, 127, 127, 131, 125, 121, 123, 123, 119, 121, 114, 119, 117, 110, 114, 98,
-  96, 110, 119, 135, 139, 147, 156, 155, 164, 167, 169, 158, 149, 156, 158, 151,
-  153, 156, 158, 156, 162, 156, 156, 153, 155, 156, 156, 155, 155, 153, 156, 156,
-  156, 156, 162, 156, 158, 164, 160, 160, 158, 162, 200, 213, 219, 219, 224, 222,
-  225, 218, 201, 158, 103, 96, 103, 98, 114, 119, 119, 123, 129, 117, 121, 121,
-  123, 127, 121, 123, 117, 123, 121, 119, 123, 129, 121, 123, 125, 121, 123, 114,
-  129, 125, 123, 123, 121, 129, 125, 117, 110, 112, 117, 119, 135, 171, 174, 158,
-  164, 164, 165, 165, 167, 162, 158, 162, 162, 165, 155, 156, 158, 158, 158, 155,
-  155, 156, 160, 162, 169, 169, 174, 177, 174, 169, 171, 162, 147, 155, 127, 114,
-  86, 86, 76, 98, 98, 98, 98, 96, 108, 101, 98, 108, 103, 101, 105, 101,
-  105, 105, 98, 98, 105, 117, 108, 119, 105, 117, 123, 119, 119, 125, 117, 133,
-  129, 133, 125, 129, 135, 131, 129, 125, 133, 127, 133, 127, 125, 125, 133, 133,
-  123, 125, 131, 131, 127, 125, 131, 131, 135, 133, 129, 129, 129, 137, 133, 133,
-  133, 129, 133, 129, 135, 131, 133, 131, 141, 127, 133, 129, 131, 129, 131, 127,
-  129, 135, 133, 129, 129, 127, 125, 127, 133, 129, 129, 133, 131, 131, 125, 131,
-  137, 133, 131, 127, 129, 127, 131, 127, 127, 129, 121, 133, 127, 125, 125, 133,
-  123, 127, 127, 131, 125, 121, 123, 123, 119, 121, 114, 119, 117, 110, 114, 98,
-  96, 110, 119, 135, 139, 147, 156, 155, 164, 167, 169, 158, 149, 156, 158, 151,
-  153, 156, 158, 156, 162, 156, 156, 153, 155, 156, 156, 155, 155, 153, 156, 156,
-  156, 156, 162, 156, 158, 164, 160, 160, 158, 162, 200, 213, 219, 219, 224, 222,
-  225, 218, 201, 158, 103, 96, 103, 98, 114, 119, 119, 123, 129, 117, 121, 121,
-  123, 127, 121, 123, 117, 123, 121, 119, 123, 129, 121, 123, 125, 121, 123, 114,
-  129, 125, 123, 123, 121, 129, 125, 117, 110, 112, 117, 119, 135, 171, 174, 158,
-  164, 164, 165, 165, 167, 162, 158, 162, 162, 165, 155, 156, 158, 158, 158, 155,
-  155, 156, 160, 162, 169, 169, 174, 177, 174, 169, 171, 162, 147, 155, 127, 114,
-  86, 86, 76, 98, 98, 98, 98, 96, 108, 101, 98, 108, 103, 101, 105, 101,
-  105, 105, 98, 98, 105, 117, 108, 119, 105, 117, 123, 119, 119, 125, 117, 133,
-  129, 133, 125, 129, 135, 131, 129, 125, 133, 127, 133, 127, 125, 125, 133, 133,
-  123, 125, 131, 131, 127, 125, 131, 131, 135, 133, 129, 129, 129, 137, 133, 133,
-  133, 129, 133, 129, 135, 131, 133, 131, 141, 127, 133, 129, 131, 129, 131, 127,
-  129, 135, 133, 129, 129, 127, 125, 127, 133, 129, 129, 133, 131, 131, 125, 131,
-  137, 133, 131, 127, 129, 127, 131, 127, 127, 129, 121, 133, 127, 125, 125, 133,
-  123, 127, 127, 131, 125, 121, 123, 123, 119, 121, 114, 119, 117, 110, 114, 98,
-  96, 110, 119, 135, 139, 147, 156, 155, 164, 167, 169, 158, 149, 156, 158, 151,
-  153, 156, 158, 156, 162, 156, 156, 153, 155, 156, 156, 155, 155, 153, 156, 156,
-  156, 156, 162, 156, 158, 164, 160, 160, 158, 162, 200, 213, 219, 219, 224, 222,
-  225, 218, 201, 158, 103, 96, 103, 98, 114, 119, 119, 123, 129, 117, 121, 121,
-  123, 127, 121, 123, 117, 123, 121, 119, 123, 129, 121, 123, 125, 121, 123, 114,
-  129, 125, 123, 123, 121, 129, 125, 117, 110, 112, 117, 119, 135, 171, 174, 158,
-  162, 167, 162, 160, 162, 156, 156, 158, 155, 156, 160, 156, 158, 155, 151, 156,
-  162, 156, 160, 167, 172, 172, 172, 174, 176, 171, 167, 160, 149, 135, 114, 98,
-  86, 76, 86, 81, 86, 86, 98, 110, 94, 101, 103, 101, 91, 98, 103, 91,
-  94, 101, 94, 112, 98, 103, 119, 108, 112, 114, 127, 121, 123, 114, 119, 125,
-  129, 127, 135, 119, 123, 125, 129, 127, 129, 131, 127, 129, 121, 127, 125, 125,
-  131, 135, 133, 133, 127, 131, 129, 137, 129, 125, 131, 129, 129, 125, 127, 129,
-  133, 133, 129, 131, 135, 131, 129, 129, 137, 127, 133, 129, 131, 127, 131, 123,
-  127, 133, 135, 125, 129, 125, 129, 129, 131, 125, 131, 131, 129, 127, 127, 127,
-  127, 131, 131, 125, 125, 125, 121, 129, 123, 131, 125, 123, 123, 125, 125, 131,
-  131, 127, 121, 125, 127, 127, 125, 121, 119, 123, 121, 117, 112, 110, 105, 98,
-  96, 112, 119, 125, 133, 147, 145, 158, 164, 162, 167, 160, 156, 155, 153, 155,
-  155, 158, 162, 156, 162, 158, 156, 156, 156, 153, 153, 158, 158, 160, 155, 153,
-  156, 156, 158, 160, 160, 160, 158, 158, 155, 156, 181, 207, 216, 219, 222, 224,
-  227, 222, 213, 187, 133, 103, 96, 108, 112, 114, 119, 117, 117, 121, 121, 129,
-  121, 127, 119, 117, 125, 123, 127, 123, 125, 121, 127, 125, 123, 114, 125, 125,
-  121, 125, 123, 117, 119, 123, 123, 125, 117, 112, 125, 129, 125, 123, 86, 49,
-  156, 160, 162, 158, 165, 160, 164, 156, 156, 165, 160, 156, 162, 153, 153, 160,
-  158, 155, 164, 171, 176, 177, 174, 174, 177, 171, 167, 160, 145, 135, 117, 103,
-  86, 79, 76, 81, 86, 91, 98, 96, 96, 98, 94, 105, 96, 103, 103, 103,
-  94, 114, 101, 96, 105, 105, 103, 117, 114, 117, 114, 125, 121, 129, 121, 125,
-  114, 121, 127, 131, 129, 131, 127, 123, 131, 125, 127, 129, 127, 131, 127, 127,
-  123, 129, 131, 129, 127, 131, 131, 129, 127, 133, 135, 127, 127, 143, 133, 129,
-  129, 131, 129, 129, 129, 127, 123, 125, 133, 127, 133, 137, 127, 121, 119, 127,
-  129, 137, 141, 131, 123, 125, 131, 131, 129, 127, 125, 129, 123, 129, 131, 133,
-  127, 133, 133, 125, 127, 119, 127, 129, 121, 133, 125, 127, 119, 127, 127, 127,
-  129, 127, 123, 125, 125, 123, 123, 125, 123, 119, 121, 121, 110, 110, 105, 108,
-  96, 103, 110, 117, 131, 139, 143, 149, 156, 158, 167, 160, 158, 158, 155, 153,
-  156, 158, 155, 156, 158, 156, 158, 162, 155, 160, 160, 153, 156, 155, 155, 158,
-  158, 158, 158, 158, 153, 158, 158, 160, 155, 155, 162, 193, 210, 219, 219, 222,
-  222, 225, 219, 206, 167, 112, 101, 105, 112, 112, 114, 125, 117, 117, 114, 125,
-  117, 119, 117, 123, 117, 117, 119, 123, 125, 121, 121, 119, 121, 121, 119, 125,
-  125, 121, 127, 121, 121, 125, 131, 125, 127, 123, 125, 123, 86, 52, 32, 26,
-  158, 160, 158, 155, 160, 158, 162, 160, 156, 155, 162, 160, 155, 156, 156, 153,
-  158, 158, 164, 171, 174, 171, 176, 177, 171, 165, 165, 160, 141, 131, 127, 108,
-  86, 76, 79, 86, 103, 86, 91, 98, 94, 94, 94, 89, 94, 108, 91, 96,
-  96, 94, 101, 103, 110, 105, 110, 119, 117, 121, 119, 119, 121, 121, 117, 127,
-  119, 133, 123, 121, 129, 129, 123, 131, 125, 131, 133, 121, 123, 127, 125, 133,
-  123, 133, 133, 137, 127, 127, 129, 129, 127, 131, 125, 123, 129, 131, 125, 127,
-  123, 125, 127, 127, 131, 129, 131, 129, 125, 133, 135, 125, 131, 125, 121, 123,
-  131, 123, 129, 125, 133, 125, 129, 123, 133, 125, 131, 125, 129, 125, 127, 123,
-  127, 125, 131, 129, 125, 125, 127, 123, 125, 125, 123, 127, 121, 127, 125, 123,
-  125, 125, 131, 125, 125, 125, 127, 127, 123, 117, 108, 112, 112, 112, 110, 108,
-  108, 96, 108, 119, 125, 137, 143, 151, 156, 162, 165, 167, 158, 158, 156, 153,
-  158, 156, 164, 162, 160, 158, 158, 160, 156, 156, 156, 156, 156, 160, 158, 155,
-  153, 156, 155, 156, 156, 158, 153, 156, 160, 151, 153, 174, 201, 212, 219, 221,
-  222, 224, 224, 215, 192, 149, 103, 96, 103, 108, 114, 114, 121, 114, 114, 123,
-  121, 121, 114, 121, 117, 121, 117, 119, 121, 123, 119, 114, 121, 117, 123, 125,
-  121, 123, 123, 127, 119, 121, 125, 131, 129, 131, 110, 84, 46, 32, 32, 38,
-  158, 160, 158, 160, 164, 160, 156, 156, 158, 165, 158, 158, 153, 155, 155, 153,
-  158, 167, 164, 171, 174, 174, 174, 169, 165, 172, 172, 162, 139, 135, 121, 101,
-  94, 71, 76, 91, 74, 86, 91, 103, 94, 96, 98, 103, 103, 98, 94, 98,
-  91, 98, 94, 98, 110, 101, 105, 108, 114, 112, 119, 121, 121, 117, 127, 121,
-  119, 121, 123, 137, 125, 129, 125, 129, 127, 127, 125, 125, 125, 131, 121, 133,
-  123, 127, 135, 125, 129, 125, 127, 131, 125, 127, 127, 131, 135, 129, 123, 127,
-  123, 127, 125, 125, 133, 125, 133, 129, 129, 133, 129, 127, 129, 123, 127, 121,
-  127, 129, 125, 129, 125, 129, 125, 127, 125, 133, 129, 129, 131, 127, 137, 127,
-  125, 127, 125, 131, 125, 129, 125, 125, 125, 121, 125, 127, 127, 127, 125, 133,
-  125, 119, 119, 125, 119, 125, 133, 125, 119, 121, 117, 119, 114, 108, 110, 110,
-  101, 101, 96, 105, 117, 131, 133, 145, 151, 155, 167, 162, 162, 162, 158, 156,
-  156, 160, 162, 162, 165, 162, 162, 158, 160, 156, 158, 158, 156, 158, 156, 158,
-  155, 156, 155, 155, 155, 158, 158, 160, 167, 149, 155, 155, 189, 209, 216, 219,
-  222, 222, 224, 224, 209, 176, 117, 98, 101, 105, 110, 117, 110, 121, 117, 119,
-  123, 119, 121, 114, 125, 112, 117, 119, 131, 121, 119, 114, 119, 117, 125, 117,
-  123, 125, 121, 121, 119, 119, 133, 129, 125, 123, 89, 46, 38, 29, 35, 38,
-  160, 162, 156, 162, 156, 151, 156, 156, 156, 156, 153, 158, 155, 153, 156, 156,
-  164, 169, 171, 174, 172, 172, 172, 174, 171, 169, 162, 160, 141, 131, 119, 105,
-  91, 89, 79, 86, 86, 91, 94, 96, 96, 98, 96, 105, 96, 101, 91, 101,
-  105, 96, 94, 98, 105, 103, 108, 108, 112, 112, 119, 119, 123, 119, 117, 129,
-  123, 119, 127, 123, 121, 131, 129, 133, 129, 125, 127, 125, 125, 125, 129, 127,
-  123, 123, 125, 125, 127, 127, 131, 129, 125, 127, 133, 133, 129, 127, 133, 123,
-  125, 127, 135, 133, 131, 131, 121, 135, 129, 125, 131, 131, 133, 125, 129, 129,
-  129, 131, 123, 131, 125, 123, 129, 127, 133, 127, 129, 133, 137, 127, 127, 129,
-  125, 135, 127, 127, 125, 121, 135, 123, 127, 129, 127, 121, 123, 127, 121, 123,
-  127, 119, 125, 127, 131, 125, 121, 121, 114, 119, 121, 119, 114, 117, 110, 108,
-  98, 105, 96, 105, 114, 123, 139, 147, 151, 156, 160, 164, 165, 164, 164, 160,
-  162, 162, 162, 169, 165, 167, 164, 160, 158, 160, 155, 156, 162, 160, 151, 155,
-  156, 153, 153, 153, 153, 156, 155, 156, 155, 160, 155, 149, 167, 201, 212, 218,
-  221, 225, 224, 225, 218, 200, 155, 98, 103, 101, 105, 110, 117, 110, 114, 121,
-  121, 112, 123, 117, 121, 117, 110, 123, 125, 114, 121, 125, 119, 127, 129, 121,
-  125, 119, 119, 125, 123, 125, 129, 127, 108, 84, 35, 38, 41, 38, 46, 35,
-  156, 156, 158, 158, 156, 155, 160, 156, 153, 155, 158, 155, 156, 151, 151, 167,
-  164, 167, 176, 169, 169, 172, 169, 169, 171, 169, 158, 160, 141, 137, 125, 98,
-  91, 81, 79, 84, 81, 96, 96, 81, 96, 108, 105, 105, 86, 91, 98, 108,
-  91, 94, 91, 98, 101, 108, 110, 108, 108, 117, 112, 121, 114, 121, 119, 125,
-  125, 127, 123, 129, 123, 127, 131, 129, 131, 125, 123, 125, 129, 123, 125, 125,
-  129, 129, 133, 131, 125, 141, 129, 129, 125, 131, 129, 129, 137, 127, 127, 125,
-  123, 125, 123, 125, 127, 121, 131, 131, 129, 125, 131, 125, 133, 133, 129, 123,
-  121, 131, 129, 129, 123, 127, 129, 129, 133, 137, 127, 141, 129, 127, 131, 127,
-  129, 131, 125, 125, 127, 127, 127, 123, 129, 127, 125, 123, 125, 114, 125, 127,
-  127, 127, 127, 123, 125, 123, 123, 123, 125, 123, 110, 119, 112, 112, 110, 125,
-  108, 108, 103, 94, 112, 117, 135, 141, 149, 155, 158, 156, 160, 171, 162, 160,
-  160, 164, 165, 165, 162, 162, 162, 165, 158, 160, 165, 162, 162, 158, 153, 153,
-  155, 155, 158, 151, 158, 149, 156, 151, 151, 155, 151, 158, 151, 184, 206, 215,
-  221, 222, 225, 225, 224, 213, 189, 125, 103, 91, 112, 103, 121, 112, 108, 117,
-  119, 121, 121, 114, 114, 119, 117, 127, 119, 117, 125, 121, 119, 123, 127, 123,
-  129, 131, 125, 129, 129, 133, 133, 108, 71, 23, 32, 23, 26, 38, 26, 35,
-  158, 162, 158, 155, 160, 155, 162, 165, 162, 164, 156, 156, 155, 156, 164, 162,
-  169, 171, 174, 167, 172, 171, 171, 165, 172, 165, 164, 153, 139, 131, 121, 101,
-  84, 89, 89, 81, 86, 101, 89, 91, 91, 89, 105, 96, 94, 101, 98, 94,
-  89, 98, 94, 103, 101, 112, 110, 108, 112, 110, 117, 121, 119, 123, 114, 125,
-  123, 125, 121, 127, 125, 127, 129, 125, 119, 123, 127, 127, 127, 125, 125, 123,
-  127, 127, 131, 125, 123, 127, 127, 127, 131, 135, 129, 123, 125, 133, 131, 127,
-  125, 123, 129, 137, 125, 125, 127, 125, 127, 127, 135, 125, 139, 125, 125, 127,
-  123, 135, 135, 123, 125, 121, 119, 125, 129, 131, 133, 133, 131, 127, 129, 127,
-  131, 125, 131, 133, 129, 127, 123, 121, 125, 125, 129, 125, 127, 123, 121, 119,
-  125, 123, 127, 121, 131, 117, 121, 127, 127, 127, 121, 123, 112, 112, 108, 114,
-  108, 108, 94, 96, 105, 119, 125, 139, 141, 155, 156, 162, 162, 171, 162, 162,
-  165, 162, 160, 167, 164, 165, 167, 167, 162, 160, 158, 164, 164, 155, 158, 155,
-  156, 162, 155, 156, 155, 158, 153, 155, 158, 153, 155, 151, 147, 156, 193, 210,
-  218, 224, 224, 225, 224, 219, 204, 164, 103, 98, 108, 105, 112, 108, 108, 121,
-  117, 119, 125, 117, 129, 131, 119, 121, 121, 139, 123, 117, 127, 125, 131, 123,
-  129, 133, 129, 131, 135, 125, 103, 79, 29, 20, 41, 29, 35, 38, 32, 29,
-  160, 156, 156, 156, 160, 160, 160, 162, 158, 156, 153, 162, 155, 156, 160, 162,
-  165, 171, 169, 171, 176, 167, 165, 169, 164, 165, 158, 156, 145, 131, 129, 129,
-  98, 96, 76, 76, 86, 89, 91, 98, 98, 103, 96, 103, 96, 96, 98, 91,
-  101, 91, 96, 89, 101, 105, 108, 105, 121, 110, 110, 114, 121, 121, 117, 127,
-  119, 123, 123, 127, 127, 125, 127, 125, 119, 131, 125, 129, 129, 131, 131, 127,
-  125, 123, 129, 133, 123, 121, 131, 125, 127, 121, 125, 125, 125, 125, 127, 127,
-  135, 125, 127, 131, 125, 127, 129, 125, 129, 127, 123, 129, 129, 125, 139, 131,
-  129, 129, 133, 127, 121, 125, 123, 123, 131, 133, 131, 129, 143, 131, 125, 125,
-  133, 121, 123, 125, 141, 121, 131, 119, 125, 123, 125, 125, 129, 119, 119, 123,
-  123, 123, 125, 127, 127, 123, 125, 123, 127, 119, 121, 119, 141, 114, 112, 112,
-  103, 101, 103, 89, 105, 114, 127, 137, 147, 147, 155, 158, 160, 167, 164, 164,
-  162, 162, 162, 169, 165, 171, 164, 164, 164, 156, 162, 162, 162, 169, 153, 160,
-  158, 160, 155, 156, 153, 155, 156, 158, 155, 151, 155, 155, 160, 147, 176, 204,
-  213, 221, 222, 225, 227, 224, 215, 192, 143, 94, 112, 103, 114, 108, 112, 114,
-  112, 119, 119, 121, 121, 119, 112, 127, 112, 121, 121, 129, 125, 125, 125, 129,
-  129, 133, 131, 141, 129, 105, 71, 41, 29, 46, 46, 29, 49, 32, 26, 26,
-  160, 158, 155, 158, 156, 153, 158, 160, 162, 158, 160, 158, 149, 156, 158, 164,
-  172, 171, 169, 164, 169, 172, 171, 164, 162, 162, 160, 151, 155, 135, 129, 119,
-  89, 84, 84, 86, 84, 86, 89, 86, 137, 91, 98, 89, 91, 105, 89, 98,
-  101, 98, 94, 96, 108, 117, 103, 114, 110, 123, 112, 117, 110, 121, 123, 119,
-  121, 117, 123, 125, 131, 127, 129, 129, 129, 123, 131, 131, 125, 125, 123, 125,
-  123, 129, 129, 131, 127, 125, 125, 127, 127, 125, 133, 131, 125, 121, 125, 125,
-  127, 133, 123, 127, 127, 125, 125, 129, 125, 123, 127, 125, 127, 123, 125, 125,
-  125, 125, 123, 121, 121, 125, 123, 125, 131, 127, 131, 133, 135, 127, 127, 127,
-  129, 129, 129, 125, 129, 127, 127, 129, 121, 127, 119, 119, 119, 121, 119, 125,
-  125, 123, 121, 125, 119, 117, 125, 123, 119, 117, 117, 121, 117, 119, 108, 108,
-  103, 117, 101, 96, 101, 103, 125, 135, 145, 153, 155, 158, 162, 160, 165, 162,
-  164, 165, 158, 164, 164, 165, 162, 167, 167, 167, 162, 153, 160, 156, 156, 156,
-  153, 156, 151, 155, 153, 153, 153, 155, 155, 153, 155, 153, 141, 147, 153, 190,
-  209, 216, 221, 224, 224, 225, 222, 210, 172, 108, 98, 103, 108, 114, 123, 121,
-  114, 117, 110, 121, 125, 121, 121, 117, 123, 114, 129, 127, 135, 133, 131, 127,
-  125, 131, 133, 131, 112, 55, 35, 20, 29, 29, 41, 32, 41, 32, 32, 38,
-  158, 160, 153, 162, 162, 156, 158, 160, 162, 155, 160, 162, 153, 160, 164, 167,
-  171, 167, 174, 167, 169, 169, 169, 156, 160, 162, 160, 155, 149, 137, 121, 108,
-  94, 79, 81, 84, 89, 79, 96, 96, 105, 101, 98, 94, 94, 98, 94, 94,
-  101, 94, 96, 98, 98, 105, 98, 105, 117, 114, 114, 121, 114, 110, 123, 121,
-  127, 125, 119, 129, 123, 139, 119, 125, 125, 121, 125, 125, 123, 121, 127, 125,
-  127, 127, 133, 125, 125, 129, 133, 127, 123, 125, 129, 129, 123, 125, 133, 131,
-  125, 129, 119, 129, 123, 127, 121, 123, 121, 127, 121, 117, 123, 123, 117, 123,
-  123, 123, 125, 127, 123, 127, 119, 123, 131, 125, 133, 129, 125, 133, 129, 125,
-  131, 125, 133, 133, 125, 127, 119, 125, 125, 131, 125, 125, 121, 123, 117, 121,
-  121, 127, 123, 125, 117, 121, 121, 123, 119, 117, 125, 117, 119, 112, 114, 105,
-  108, 105, 101, 103, 110, 119, 123, 131, 143, 149, 151, 160, 158, 164, 167, 167,
-  164, 171, 164, 156, 162, 164, 162, 160, 160, 164, 162, 158, 158, 164, 162, 155,
-  162, 158, 151, 149, 156, 153, 153, 153, 156, 153, 153, 151, 151, 147, 145, 172,
-  204, 213, 219, 224, 225, 225, 225, 218, 201, 158, 98, 98, 105, 112, 119, 123,
-  114, 123, 112, 119, 121, 119, 119, 119, 117, 117, 121, 129, 125, 123, 125, 125,
-  135, 137, 127, 108, 60, 79, 32, 26, 35, 38, 26, 29, 23, 35, 43, 41,
-  155, 153, 155, 156, 160, 156, 162, 162, 160, 156, 160, 155, 156, 164, 164, 165,
-  167, 169, 172, 171, 165, 164, 165, 162, 164, 164, 164, 149, 149, 137, 114, 101,
-  81, 71, 60, 71, 81, 86, 91, 98, 96, 101, 101, 96, 98, 94, 96, 91,
-  101, 91, 98, 101, 103, 101, 110, 105, 114, 121, 114, 121, 117, 119, 117, 123,
-  121, 129, 125, 129, 121, 125, 127, 127, 117, 125, 125, 117, 125, 127, 125, 125,
-  125, 127, 123, 119, 121, 127, 121, 117, 121, 127, 125, 119, 125, 135, 135, 129,
-  135, 125, 129, 121, 125, 123, 119, 119, 119, 123, 117, 123, 123, 127, 125, 125,
-  127, 114, 121, 121, 123, 123, 114, 125, 117, 121, 121, 131, 127, 123, 129, 125,
-  125, 125, 127, 133, 125, 127, 125, 125, 121, 125, 125, 123, 135, 121, 123, 127,
-  119, 125, 127, 121, 125, 125, 121, 121, 123, 123, 121, 117, 125, 127, 110, 101,
-  108, 101, 96, 98, 101, 108, 117, 125, 137, 143, 155, 158, 158, 164, 162, 162,
-  164, 164, 158, 162, 160, 158, 162, 164, 162, 164, 162, 162, 160, 158, 151, 155,
-  158, 153, 153, 155, 151, 155, 158, 155, 155, 155, 156, 153, 151, 151, 145, 147,
-  187, 212, 218, 222, 224, 227, 228, 225, 213, 189, 125, 101, 105, 108, 112, 114,
-  125, 121, 125, 114, 123, 121, 117, 117, 119, 129, 123, 117, 123, 127, 125, 129,
-  133, 135, 108, 71, 32, 32, 41, 18, 15, 29, 23, 26, 26, 41, 43, 26,
-  160, 158, 165, 160, 158, 156, 160, 160, 160, 158, 162, 162, 160, 167, 167, 172,
-  172, 172, 169, 169, 162, 160, 162, 162, 160, 164, 160, 155, 147, 137, 117, 105,
-  84, 76, 74, 76, 86, 84, 91, 89, 94, 101, 98, 94, 101, 98, 101, 89,
-  98, 91, 96, 101, 101, 105, 110, 110, 110, 123, 119, 112, 117, 125, 121, 123,
-  125, 119, 114, 121, 133, 125, 123, 123, 123, 123, 127, 125, 131, 127, 117, 131,
-  129, 125, 121, 127, 123, 123, 125, 129, 129, 123, 125, 121, 125, 127, 121, 131,
-  129, 139, 137, 123, 123, 119, 117, 119, 119, 114, 117, 119, 117, 123, 125, 123,
-  119, 123, 121, 119, 114, 123, 119, 127, 127, 123, 125, 123, 123, 129, 125, 131,
-  127, 129, 127, 127, 125, 127, 125, 119, 125, 121, 123, 127, 117, 121, 121, 121,
-  123, 119, 121, 121, 119, 125, 125, 121, 123, 117, 121, 123, 114, 117, 119, 114,
-  110, 103, 98, 103, 110, 117, 127, 133, 141, 143, 156, 156, 162, 162, 171, 165,
-  165, 162, 162, 160, 164, 158, 164, 156, 167, 158, 158, 158, 156, 156, 160, 156,
-  160, 156, 158, 155, 155, 160, 155, 153, 155, 155, 156, 153, 149, 153, 147, 145,
-  169, 203, 213, 222, 222, 224, 227, 227, 222, 206, 162, 96, 105, 110, 108, 112,
-  114, 119, 114, 123, 121, 117, 121, 121, 119, 119, 123, 121, 121, 125, 131, 135,
-  133, 108, 55, 20, 20, 35, 32, 23, 26, 26, 29, 26, 29, 46, 29, 43,
-  158, 160, 162, 158, 158, 160, 162, 167, 162, 160, 160, 165, 165, 171, 171, 172,
-  171, 169, 169, 169, 162, 162, 160, 160, 158, 165, 165, 158, 143, 135, 129, 110,
-  86, 86, 76, 76, 81, 91, 86, 94, 101, 96, 110, 91, 98, 96, 96, 94,
-  96, 94, 94, 91, 98, 101, 103, 110, 110, 112, 119, 121, 119, 125, 123, 117,
-  125, 121, 123, 123, 125, 129, 127, 121, 123, 123, 127, 125, 125, 127, 125, 123,
-  123, 125, 121, 125, 125, 127, 125, 121, 121, 127, 125, 119, 123, 117, 123, 129,
-  131, 123, 125, 125, 127, 123, 119, 117, 114, 112, 117, 112, 121, 119, 123, 125,
-  123, 125, 123, 123, 127, 121, 121, 121, 125, 129, 133, 125, 129, 129, 127, 131,
-  131, 123, 127, 127, 127, 121, 125, 123, 125, 129, 125, 125, 127, 123, 112, 127,
-  123, 117, 123, 121, 125, 129, 119, 123, 127, 131, 117, 119, 114, 110, 117, 112,
-  108, 110, 105, 101, 101, 112, 121, 131, 133, 147, 153, 153, 160, 160, 162, 167,
-  164, 164, 162, 156, 164, 156, 165, 160, 164, 158, 158, 160, 160, 158, 155, 156,
-  162, 156, 153, 155, 158, 165, 153, 160, 151, 153, 151, 155, 151, 151, 151, 143,
-  149, 185, 204, 216, 221, 222, 227, 227, 227, 218, 197, 131, 91, 114, 112, 119,
-  112, 114, 110, 123, 112, 110, 117, 121, 119, 121, 114, 127, 129, 133, 131, 129,
-  110, 55, 23, 29, 32, 29, 35, 20, 32, 20, 29, 38, 32, 32, 41, 46,
-  158, 158, 162, 156, 158, 160, 160, 158, 162, 165, 158, 164, 172, 176, 172, 171,
-  174, 171, 174, 167, 160, 160, 158, 158, 162, 162, 160, 158, 155, 139, 129, 101,
-  94, 79, 74, 84, 91, 84, 94, 91, 94, 105, 103, 105, 105, 108, 91, 94,
-  96, 86, 94, 96, 98, 103, 114, 105, 114, 110, 119, 117, 114, 114, 112, 117,
-  121, 121, 127, 117, 123, 127, 125, 125, 127, 119, 121, 127, 121, 127, 123, 121,
-  125, 123, 125, 129, 129, 127, 129, 129, 127, 125, 129, 125, 125, 119, 125, 123,
-  121, 127, 131, 121, 123, 131, 125, 117, 123, 114, 117, 119, 121, 117, 121, 123,
-  119, 114, 119, 121, 121, 117, 121, 119, 121, 125, 129, 123, 127, 129, 123, 121,
-  129, 125, 131, 125, 129, 119, 119, 123, 127, 123, 123, 121, 127, 125, 112, 123,
-  119, 119, 123, 121, 123, 121, 121, 127, 119, 125, 114, 112, 117, 112, 112, 105,
-  101, 101, 98, 101, 96, 114, 131, 127, 133, 145, 147, 153, 158, 160, 162, 164,
-  164, 165, 164, 162, 164, 160, 164, 162, 160, 165, 160, 160, 160, 162, 160, 158,
-  156, 156, 160, 158, 160, 158, 160, 158, 156, 158, 158, 156, 158, 153, 147, 145,
-  143, 153, 190, 209, 215, 222, 225, 228, 230, 227, 213, 193, 131, 101, 94, 108,
-  114, 121, 114, 117, 114, 127, 125, 121, 125, 117, 123, 127, 127, 131, 135, 117,
-  74, 23, 35, 15, 49, 32, 29, 23, 29, 32, 41, 35, 32, 29, 35, 46,
-  164, 164, 160, 158, 164, 165, 162, 162, 164, 162, 165, 169, 171, 167, 171, 171,
-  171, 169, 174, 164, 164, 162, 160, 160, 164, 162, 164, 155, 147, 129, 117, 103,
-  84, 66, 86, 89, 81, 89, 84, 96, 94, 98, 96, 103, 91, 96, 96, 94,
-  94, 96, 94, 94, 105, 103, 98, 110, 105, 108, 119, 119, 119, 123, 112, 127,
-  123, 123, 125, 127, 123, 123, 125, 125, 121, 127, 123, 121, 119, 121, 121, 129,
-  129, 129, 121, 119, 123, 127, 129, 129, 119, 125, 125, 125, 119, 127, 123, 125,
-  127, 125, 133, 123, 119, 117, 119, 114, 119, 123, 117, 110, 119, 121, 121, 121,
-  119, 129, 119, 117, 112, 123, 117, 121, 117, 121, 127, 123, 127, 131, 127, 125,
-  125, 131, 131, 127, 123, 131, 117, 121, 127, 125, 121, 123, 125, 125, 117, 123,
-  119, 125, 117, 119, 125, 121, 127, 123, 123, 123, 119, 117, 119, 112, 117, 110,
-  110, 112, 105, 101, 108, 112, 121, 125, 131, 139, 145, 155, 151, 156, 160, 160,
-  156, 167, 162, 162, 164, 160, 162, 158, 164, 162, 160, 160, 160, 164, 156, 158,
-  158, 158, 156, 158, 156, 156, 155, 158, 156, 153, 156, 156, 155, 147, 153, 145,
-  143, 143, 177, 209, 215, 222, 224, 228, 228, 228, 219, 203, 147, 103, 98, 101,
-  96, 110, 114, 114, 114, 119, 121, 121, 119, 129, 123, 131, 129, 127, 110, 60,
-  26, 20, 23, 23, 26, 46, 35, 32, 46, 20, 32, 29, 41, 38, 49, 35,
-  160, 160, 158, 164, 160, 158, 165, 165, 169, 167, 167, 172, 169, 169, 171, 174,
-  167, 171, 164, 162, 156, 156, 160, 162, 164, 162, 160, 156, 147, 131, 129, 96,
-  89, 79, 71, 76, 96, 89, 91, 89, 86, 98, 98, 96, 96, 94, 96, 91,
-  91, 103, 101, 98, 103, 103, 114, 101, 114, 110, 114, 114, 114, 110, 121, 117,
-  117, 121, 121, 123, 123, 119, 121, 125, 123, 117, 117, 119, 117, 123, 129, 123,
-  114, 117, 123, 123, 125, 119, 117, 121, 117, 127, 129, 123, 121, 123, 117, 127,
-  121, 123, 123, 125, 114, 121, 114, 123, 127, 121, 119, 121, 123, 123, 121, 123,
-  123, 123, 121, 114, 123, 119, 110, 121, 117, 117, 125, 127, 127, 125, 129, 125,
-  129, 127, 131, 123, 125, 123, 119, 121, 125, 119, 119, 119, 121, 123, 117, 114,
-  117, 121, 121, 123, 117, 119, 121, 121, 125, 114, 121, 119, 110, 110, 114, 108,
-  112, 110, 101, 101, 105, 114, 117, 129, 135, 137, 143, 149, 158, 156, 156, 153,
-  158, 164, 162, 160, 160, 162, 162, 162, 162, 158, 158, 155, 158, 160, 156, 164,
-  158, 158, 158, 153, 156, 158, 153, 158, 158, 155, 151, 151, 151, 153, 155, 141,
-  143, 145, 149, 193, 210, 219, 225, 228, 227, 228, 227, 212, 189, 127, 94, 98,
-  103, 112, 108, 108, 117, 119, 121, 129, 127, 127, 121, 133, 123, 101, 60, 18,
-  23, 23, 35, 35, 43, 46, 43, 43, 35, 32, 29, 32, 35, 49, 41, 32,
-  160, 164, 167, 160, 164, 160, 160, 164, 167, 165, 167, 171, 171, 167, 171, 165,
-  165, 167, 165, 165, 158, 158, 165, 164, 164, 162, 165, 153, 141, 139, 119, 105,
-  81, 63, 79, 76, 76, 81, 91, 91, 103, 94, 94, 96, 96, 91, 98, 96,
-  96, 96, 89, 96, 98, 103, 103, 110, 105, 112, 121, 114, 112, 110, 114, 121,
-  117, 117, 121, 123, 119, 121, 121, 123, 119, 119, 117, 121, 125, 117, 119, 125,
-  125, 119, 127, 125, 121, 121, 125, 125, 125, 117, 121, 121, 129, 119, 114, 121,
-  127, 123, 123, 119, 117, 119, 121, 119, 117, 119, 112, 117, 119, 110, 119, 121,
-  123, 119, 119, 112, 112, 112, 121, 114, 121, 121, 121, 119, 119, 121, 127, 127,
-  133, 123, 129, 125, 123, 125, 127, 125, 123, 121, 123, 119, 123, 121, 119, 123,
-  123, 119, 119, 119, 123, 121, 117, 121, 125, 119, 119, 112, 117, 112, 127, 125,
-  114, 105, 96, 96, 101, 105, 121, 121, 133, 139, 143, 149, 151, 155, 155, 158,
-  158, 162, 156, 160, 158, 162, 156, 160, 155, 164, 156, 156, 158, 156, 153, 155,
-  155, 160, 156, 158, 155, 155, 153, 155, 160, 155, 153, 155, 156, 147, 147, 143,
-  143, 137, 141, 167, 204, 216, 222, 227, 227, 228, 230, 224, 210, 165, 98, 91,
-  101, 105, 108, 110, 108, 117, 114, 123, 121, 133, 135, 125, 105, 66, 23, 32,
-  29, 20, 23, 32, 29, 35, 43, 55, 46, 41, 38, 32, 35, 23, 29, 38,
-  167, 171, 167, 158, 164, 167, 162, 164, 169, 167, 174, 167, 167, 165, 162, 165,
-  167, 169, 165, 156, 160, 160, 164, 164, 164, 164, 158, 155, 145, 131, 117, 91,
-  84, 71, 66, 81, 81, 96, 101, 96, 98, 94, 91, 91, 94, 98, 94, 91,
-  91, 98, 105, 98, 96, 114, 110, 112, 105, 117, 114, 121, 119, 123, 117, 119,
-  123, 112, 117, 123, 125, 119, 121, 121, 121, 119, 114, 117, 117, 114, 121, 114,
-  127, 127, 123, 117, 119, 129, 117, 121, 119, 119, 129, 121, 129, 125, 123, 119,
-  127, 129, 119, 121, 119, 119, 121, 117, 129, 108, 114, 112, 119, 123, 110, 112,
-  117, 117, 119, 117, 110, 114, 121, 114, 119, 112, 121, 123, 121, 125, 129, 125,
-  131, 125, 123, 125, 123, 119, 119, 123, 123, 123, 119, 123, 121, 114, 123, 123,
-  125, 123, 121, 125, 121, 117, 121, 125, 121, 119, 117, 110, 117, 108, 114, 114,
-  105, 110, 110, 98, 101, 103, 121, 123, 129, 135, 143, 147, 149, 149, 153, 153,
-  153, 164, 156, 165, 158, 155, 162, 155, 158, 151, 158, 155, 160, 156, 151, 153,
-  156, 158, 158, 158, 158, 155, 160, 153, 151, 155, 155, 151, 151, 149, 143, 147,
-  143, 145, 141, 149, 190, 212, 221, 225, 227, 227, 230, 227, 218, 201, 137, 94,
-  103, 114, 103, 108, 108, 114, 119, 123, 125, 127, 129, 108, 63, 32, 18, 32,
-  20, 26, 26, 26, 32, 38, 32, 29, 35, 35, 32, 26, 41, 26, 29, 29,
-  162, 158, 164, 160, 156, 160, 164, 169, 172, 174, 171, 165, 162, 169, 158, 160,
-  160, 160, 160, 165, 164, 158, 164, 162, 160, 164, 162, 153, 141, 133, 121, 96,
-  81, 76, 66, 79, 74, 91, 94, 91, 94, 101, 94, 94, 96, 101, 86, 105,
-  91, 101, 98, 94, 96, 103, 103, 110, 105, 114, 117, 112, 114, 117, 119, 125,
-  119, 112, 117, 125, 114, 125, 127, 117, 117, 119, 123, 121, 121, 121, 131, 127,
-  117, 117, 119, 125, 117, 125, 121, 123, 125, 121, 121, 125, 121, 119, 119, 127,
-  125, 125, 121, 119, 119, 121, 131, 123, 117, 117, 123, 121, 119, 121, 112, 114,
-  114, 117, 112, 114, 110, 114, 112, 112, 114, 112, 121, 125, 125, 121, 129, 127,
-  127, 131, 125, 123, 117, 125, 125, 123, 114, 121, 129, 137, 119, 121, 129, 129,
-  121, 123, 121, 117, 119, 125, 127, 125, 121, 123, 117, 117, 110, 117, 108, 112,
-  110, 119, 103, 103, 105, 108, 112, 114, 133, 129, 141, 143, 147, 149, 151, 155,
-  153, 151, 155, 160, 162, 155, 158, 158, 153, 156, 158, 155, 153, 155, 156, 155,
-  155, 155, 156, 155, 156, 158, 156, 153, 153, 147, 155, 147, 149, 153, 141, 147,
-  145, 137, 139, 141, 169, 204, 216, 224, 227, 228, 228, 230, 224, 210, 171, 105,
-  98, 105, 98, 103, 105, 103, 110, 119, 133, 129, 108, 74, 26, 23, 20, 20,
-  32, 23, 35, 46, 41, 49, 41, 38, 35, 29, 38, 32, 32, 26, 29, 15,
-  164, 164, 165, 167, 162, 164, 164, 172, 177, 172, 169, 160, 158, 162, 156, 156,
-  155, 156, 156, 164, 165, 164, 158, 160, 165, 164, 164, 153, 149, 127, 119, 98,
-  89, 74, 79, 79, 79, 91, 94, 89, 98, 91, 101, 94, 91, 98, 98, 96,
-  96, 101, 94, 91, 103, 96, 101, 108, 110, 114, 114, 117, 117, 123, 127, 117,
-  125, 119, 123, 117, 117, 119, 119, 119, 117, 121, 121, 119, 119, 123, 125, 121,
-  123, 117, 121, 121, 121, 123, 121, 127, 123, 125, 125, 125, 121, 123, 121, 119,
-  125, 129, 119, 125, 117, 121, 127, 125, 127, 121, 117, 117, 114, 114, 123, 127,
-  147, 127, 143, 119, 125, 114, 112, 112, 114, 112, 112, 123, 114, 112, 119, 123,
-  119, 119, 117, 127, 125, 125, 125, 121, 117, 123, 127, 127, 123, 119, 125, 121,
-  121, 123, 129, 121, 123, 119, 121, 119, 127, 117, 117, 119, 108, 119, 103, 112,
-  114, 110, 105, 98, 103, 103, 105, 123, 131, 137, 135, 143, 143, 147, 149, 153,
-  153, 153, 158, 156, 158, 162, 158, 155, 153, 158, 153, 153, 156, 155, 160, 156,
-  158, 155, 153, 156, 158, 153, 151, 155, 151, 147, 143, 145, 145, 141, 145, 145,
-  145, 141, 141, 145, 147, 189, 212, 218, 222, 228, 227, 230, 228, 218, 204, 139,
-  94, 96, 103, 105, 110, 108, 119, 119, 129, 103, 66, 35, 23, 20, 32, 20,
-  35, 38, 41, 46, 46, 49, 38, 43, 38, 35, 38, 23, 20, 29, 32, 20,
-  167, 160, 167, 165, 162, 164, 167, 171, 169, 167, 169, 155, 155, 156, 153, 153,
-  153, 153, 160, 164, 169, 167, 164, 158, 165, 162, 160, 155, 151, 139, 119, 96,
-  79, 76, 71, 86, 76, 81, 96, 103, 96, 103, 96, 94, 98, 89, 98, 94,
-  96, 96, 96, 94, 114, 108, 114, 112, 108, 121, 112, 117, 114, 123, 117, 117,
-  112, 114, 117, 117, 119, 114, 119, 117, 114, 123, 123, 123, 119, 119, 121, 121,
-  125, 125, 121, 121, 123, 149, 123, 127, 123, 125, 125, 119, 127, 119, 129, 114,
-  123, 139, 125, 114, 125, 117, 121, 123, 129, 143, 141, 139, 133, 164, 153, 197,
-  164, 197, 171, 189, 176, 195, 171, 179, 139, 125, 110, 114, 110, 114, 114, 121,
-  114, 125, 119, 121, 119, 119, 112, 121, 119, 131, 129, 121, 123, 119, 123, 121,
-  121, 121, 119, 121, 119, 127, 121, 121, 117, 119, 121, 112, 112, 110, 112, 103,
-  117, 101, 108, 101, 103, 119, 112, 125, 129, 133, 139, 141, 143, 149, 143, 151,
-  151, 153, 155, 156, 156, 160, 158, 158, 155, 155, 151, 153, 158, 153, 158, 155,
-  156, 158, 153, 156, 149, 155, 149, 149, 147, 147, 153, 145, 143, 141, 143, 143,
-  135, 145, 145, 143, 139, 160, 200, 213, 221, 227, 227, 230, 230, 225, 213, 181,
-  108, 98, 103, 105, 114, 114, 127, 123, 101, 79, 29, 23, 26, 38, 26, 23,
-  29, 32, 38, 49, 43, 43, 41, 43, 55, 20, 35, 43, 26, 29, 35, 26,
-  165, 164, 164, 160, 162, 165, 172, 174, 176, 167, 162, 153, 149, 147, 149, 153,
-  147, 155, 164, 167, 165, 167, 165, 158, 167, 165, 164, 155, 153, 133, 127, 101,
-  81, 79, 68, 84, 84, 76, 81, 89, 94, 98, 98, 98, 94, 98, 103, 94,
-  91, 94, 96, 96, 110, 108, 103, 103, 103, 112, 117, 117, 119, 119, 117, 119,
-  121, 121, 119, 123, 123, 121, 112, 121, 117, 121, 125, 125, 123, 129, 121, 117,
-  121, 121, 119, 121, 121, 121, 117, 127, 123, 131, 119, 117, 117, 123, 121, 121,
-  121, 121, 125, 127, 129, 117, 162, 133, 162, 149, 147, 160, 171, 177, 179, 182,
-  185, 189, 177, 190, 195, 187, 201, 182, 207, 195, 172, 171, 127, 119, 112, 114,
-  112, 119, 114, 123, 123, 119, 125, 125, 121, 131, 131, 123, 129, 127, 129, 119,
-  123, 114, 123, 121, 121, 129, 121, 117, 127, 119, 117, 112, 117, 114, 103, 105,
-  110, 108, 108, 101, 101, 105, 114, 117, 123, 131, 143, 141, 143, 147, 147, 145,
-  153, 147, 156, 158, 160, 156, 155, 155, 155, 155, 153, 153, 153, 156, 155, 156,
-  156, 160, 155, 151, 151, 155, 151, 147, 145, 141, 155, 147, 147, 147, 147, 141,
-  145, 149, 143, 141, 141, 143, 181, 209, 216, 224, 227, 228, 230, 228, 221, 206,
-  156, 101, 103, 108, 110, 123, 121, 108, 68, 20, 32, 18, 23, 29, 23, 29,
-  38, 49, 35, 49, 43, 46, 43, 35, 41, 29, 20, 29, 29, 20, 26, 32,
-  164, 165, 160, 162, 160, 169, 172, 177, 171, 164, 160, 151, 145, 143, 141, 145,
-  141, 153, 162, 165, 167, 160, 165, 162, 167, 167, 162, 158, 149, 129, 123, 103,
-  76, 66, 84, 81, 84, 89, 89, 86, 91, 98, 98, 96, 94, 96, 96, 98,
-  94, 94, 94, 103, 103, 108, 105, 101, 110, 114, 117, 119, 117, 112, 121, 117,
-  129, 119, 119, 121, 119, 129, 119, 123, 123, 123, 123, 131, 121, 125, 119, 123,
-  125, 121, 119, 112, 117, 119, 129, 121, 141, 123, 119, 133, 117, 117, 119, 110,
-  117, 129, 155, 158, 153, 162, 169, 160, 155, 147, 167, 172, 187, 165, 189, 174,
-  190, 184, 198, 177, 197, 187, 190, 198, 176, 197, 200, 203, 201, 182, 155, 131,
-  112, 108, 103, 119, 112, 119, 119, 117, 123, 131, 129, 127, 125, 125, 133, 121,
-  123, 119, 117, 119, 117, 114, 119, 121, 119, 121, 114, 110, 110, 114, 117, 103,
-  108, 103, 105, 98, 101, 108, 114, 119, 127, 141, 139, 141, 145, 141, 143, 143,
-  145, 151, 145, 149, 153, 156, 155, 155, 153, 156, 156, 155, 155, 155, 160, 151,
-  158, 156, 149, 155, 156, 145, 143, 151, 141, 143, 141, 143, 139, 147, 141, 141,
-  143, 141, 141, 141, 141, 149, 153, 195, 212, 221, 224, 228, 228, 233, 228, 216,
-  192, 131, 103, 117, 129, 129, 98, 57, 29, 15, 23, 23, 26, 23, 29, 29,
-  41, 32, 41, 41, 43, 49, 43, 43, 23, 32, 20, 23, 26, 29, 29, 29,
-  162, 162, 158, 165, 158, 171, 174, 174, 167, 160, 155, 143, 141, 135, 145, 131,
-  147, 153, 164, 165, 169, 164, 165, 162, 167, 164, 167, 153, 147, 133, 119, 101,
-  86, 74, 71, 76, 86, 76, 91, 94, 89, 96, 101, 96, 96, 108, 91, 86,
-  96, 94, 84, 91, 101, 98, 108, 110, 112, 112, 112, 121, 110, 117, 114, 119,
-  123, 125, 125, 114, 119, 121, 114, 129, 119, 125, 123, 127, 121, 127, 125, 131,
-  125, 123, 114, 117, 119, 121, 119, 125, 123, 123, 121, 123, 121, 117, 117, 141,
-  143, 151, 165, 164, 156, 139, 155, 162, 151, 158, 182, 169, 193, 169, 184, 172,
-  195, 181, 197, 184, 197, 193, 169, 187, 187, 203, 185, 197, 201, 203, 203, 198,
-  189, 147, 117, 110, 114, 110, 114, 110, 123, 123, 123, 119, 117, 125, 125, 114,
-  121, 125, 127, 127, 114, 117, 121, 117, 117, 108, 112, 114, 110, 121, 114, 105,
-  108, 108, 103, 103, 98, 101, 117, 123, 131, 139, 137, 156, 141, 143, 141, 147,
-  143, 153, 145, 155, 151, 156, 151, 156, 156, 151, 153, 151, 158, 153, 153, 153,
-  151, 153, 147, 153, 143, 147, 143, 145, 149, 137, 137, 141, 145, 141, 141, 149,
-  141, 147, 145, 143, 145, 143, 147, 172, 203, 215, 222, 227, 228, 233, 233, 225,
-  212, 174, 117, 112, 117, 114, 63, 32, 23, 20, 29, 29, 26, 32, 20, 23,
-  38, 41, 32, 46, 41, 38, 41, 35, 29, 26, 35, 29, 23, 32, 20, 26,
-  160, 162, 160, 164, 169, 169, 174, 169, 162, 156, 147, 143, 125, 121, 129, 135,
-  143, 156, 160, 165, 167, 167, 165, 165, 164, 164, 162, 160, 143, 135, 114, 103,
-  84, 66, 79, 71, 89, 81, 96, 96, 91, 101, 96, 81, 94, 101, 94, 89,
-  103, 91, 96, 101, 103, 105, 119, 112, 108, 117, 112, 123, 117, 119, 112, 117,
-  114, 123, 127, 119, 121, 114, 121, 123, 125, 141, 121, 121, 123, 125, 125, 110,
-  121, 117, 123, 112, 123, 121, 114, 123, 121, 117, 119, 121, 117, 129, 141, 158,
-  139, 145, 151, 169, 139, 141, 139, 155, 153, 162, 156, 182, 167, 167, 181, 176,
-  187, 182, 189, 198, 184, 189, 176, 193, 174, 195, 198, 184, 198, 206, 189, 201,
-  203, 203, 192, 135, 110, 110, 105, 110, 110, 123, 121, 125, 119, 119, 123, 127,
-  119, 121, 117, 123, 121, 119, 119, 110, 117, 114, 114, 112, 112, 103, 112, 105,
-  105, 112, 105, 98, 96, 101, 119, 119, 133, 137, 141, 143, 147, 141, 145, 143,
-  149, 145, 149, 149, 155, 155, 156, 160, 156, 156, 149, 151, 153, 149, 151, 147,
-  143, 151, 149, 147, 147, 147, 139, 141, 149, 149, 139, 141, 139, 135, 137, 141,
-  145, 139, 141, 143, 141, 141, 135, 137, 187, 210, 221, 227, 228, 228, 233, 233,
-  224, 207, 151, 121, 108, 68, 29, 15, 35, 26, 29, 41, 32, 41, 29, 46,
-  43, 43, 32, 29, 43, 35, 38, 18, 38, 35, 29, 35, 29, 26, 32, 29,
-  162, 165, 160, 164, 171, 176, 172, 167, 158, 153, 143, 131, 121, 119, 121, 137,
-  147, 156, 162, 169, 171, 167, 165, 169, 169, 167, 164, 164, 143, 133, 125, 98,
-  81, 66, 63, 74, 76, 81, 86, 84, 98, 91, 101, 94, 91, 103, 98, 96,
-  98, 94, 98, 91, 98, 103, 119, 108, 114, 112, 114, 114, 119, 110, 123, 112,
-  119, 119, 117, 117, 121, 123, 125, 119, 121, 114, 125, 117, 125, 127, 125, 121,
-  123, 121, 119, 125, 125, 119, 121, 123, 127, 129, 137, 133, 125, 141, 156, 151,
-  137, 149, 162, 147, 156, 153, 156, 151, 141, 164, 151, 165, 164, 182, 160, 184,
-  156, 192, 189, 195, 179, 200, 182, 177, 197, 182, 193, 198, 179, 198, 206, 193,
-  200, 210, 210, 201, 177, 123, 103, 108, 117, 112, 121, 121, 119, 123, 125, 114,
-  123, 119, 114, 121, 119, 117, 112, 117, 117, 117, 117, 110, 112, 110, 108, 103,
-  110, 98, 108, 101, 108, 101, 119, 121, 135, 137, 139, 141, 145, 147, 139, 143,
-  147, 149, 149, 149, 151, 149, 153, 151, 156, 155, 153, 149, 147, 149, 147, 151,
-  139, 153, 147, 147, 141, 145, 141, 145, 143, 141, 145, 133, 141, 137, 137, 141,
-  139, 143, 141, 141, 139, 139, 137, 139, 155, 201, 216, 225, 227, 230, 231, 233,
-  231, 219, 190, 121, 71, 20, 20, 20, 23, 15, 41, 23, 32, 43, 35, 35,
-  35, 38, 38, 41, 35, 29, 23, 46, 41, 35, 29, 20, 41, 20, 29, 26,
-  162, 165, 167, 164, 169, 177, 172, 164, 156, 153, 141, 119, 112, 112, 117, 137,
-  153, 156, 162, 165, 167, 171, 164, 165, 167, 167, 160, 155, 151, 129, 121, 96,
-  76, 60, 63, 74, 76, 89, 81, 81, 86, 84, 91, 98, 91, 96, 96, 89,
-  81, 98, 103, 94, 96, 103, 105, 114, 108, 119, 112, 117, 117, 112, 112, 119,
-  119, 110, 121, 127, 114, 125, 119, 121, 121, 123, 121, 117, 123, 123, 117, 125,
-  117, 108, 112, 117, 112, 139, 156, 151, 153, 141, 123, 110, 123, 129, 147, 143,
-  149, 158, 145, 155, 147, 147, 169, 147, 158, 162, 155, 174, 149, 172, 177, 177,
-  176, 169, 190, 185, 184, 181, 195, 179, 192, 201, 184, 198, 204, 187, 201, 204,
-  204, 204, 201, 210, 204, 201, 141, 108, 103, 110, 121, 117, 121, 121, 125, 114,
-  112, 112, 119, 119, 119, 121, 117, 117, 117, 110, 110, 105, 101, 103, 103, 98,
-  103, 98, 96, 101, 103, 110, 110, 123, 125, 131, 145, 147, 145, 139, 141, 143,
-  143, 151, 145, 151, 147, 145, 151, 153, 149, 155, 153, 149, 145, 149, 153, 149,
-  141, 143, 147, 143, 151, 143, 139, 137, 147, 141, 143, 141, 139, 139, 131, 137,
-  139, 135, 141, 135, 139, 137, 137, 135, 135, 177, 210, 219, 225, 228, 230, 231,
-  233, 228, 212, 135, 23, 26, 23, 15, 38, 26, 38, 23, 41, 43, 32, 43,
-  46, 32, 55, 49, 35, 38, 26, 29, 49, 38, 26, 32, 20, 32, 26, 23,
-  160, 169, 172, 172, 172, 171, 165, 156, 151, 139, 121, 105, 101, 105, 121, 133,
-  151, 158, 164, 172, 165, 171, 169, 167, 162, 167, 162, 160, 149, 139, 125, 98,
-  74, 63, 71, 76, 94, 84, 89, 94, 101, 89, 96, 89, 89, 96, 89, 94,
-  89, 101, 98, 103, 98, 98, 105, 105, 114, 123, 108, 114, 112, 119, 110, 110,
-  108, 112, 125, 114, 121, 117, 119, 121, 117, 125, 119, 123, 119, 119, 114, 117,
-  114, 112, 181, 158, 153, 160, 153, 147, 127, 129, 119, 121, 119, 121, 127, 141,
-  145, 139, 139, 133, 141, 143, 162, 149, 158, 155, 164, 153, 172, 151, 185, 177,
-  181, 177, 184, 162, 184, 189, 184, 195, 179, 198, 201, 189, 197, 200, 200, 197,
-  206, 210, 198, 201, 206, 210, 204, 174, 110, 103, 121, 105, 117, 112, 112, 119,
-  112, 121, 121, 123, 117, 114, 114, 112, 119, 108, 105, 105, 103, 112, 105, 105,
-  96, 98, 91, 89, 98, 103, 108, 121, 125, 141, 139, 143, 143, 147, 137, 143,
-  141, 143, 147, 145, 145, 149, 156, 158, 149, 155, 151, 149, 151, 143, 147, 141,
-  143, 143, 145, 147, 145, 151, 141, 145, 139, 139, 141, 141, 139, 133, 141, 139,
-  135, 139, 139, 141, 143, 145, 139, 139, 137, 147, 200, 212, 224, 225, 228, 233,
-  236, 231, 221, 105, 12, 23, 20, 18, 29, 32, 41, 20, 41, 35, 32, 29,
-  35, 41, 38, 29, 26, 32, 35, 81, 41, 41, 32, 46, 46, 29, 46, 35,
-  162, 165, 174, 174, 174, 167, 158, 149, 145, 129, 108, 89, 89, 108, 125, 139,
-  153, 160, 165, 169, 167, 164, 169, 165, 167, 167, 165, 158, 147, 131, 121, 105,
-  74, 71, 63, 66, 84, 74, 89, 84, 86, 91, 91, 76, 86, 86, 91, 91,
-  96, 89, 94, 96, 105, 112, 101, 112, 108, 112, 103, 121, 114, 117, 112, 110,
-  114, 112, 114, 112, 117, 121, 114, 117, 114, 119, 121, 119, 117, 123, 112, 121,
-  119, 123, 129, 147, 141, 137, 135, 117, 125, 117, 114, 117, 121, 127, 137, 147,
-  137, 135, 121, 139, 139, 137, 145, 145, 155, 165, 171, 149, 167, 171, 174, 177,
-  171, 162, 189, 184, 179, 192, 177, 190, 200, 193, 185, 203, 193, 185, 207, 203,
-  189, 203, 209, 203, 203, 204, 215, 207, 195, 149, 114, 114, 105, 105, 117, 114,
-  114, 112, 119, 114, 117, 114, 112, 114, 114, 114, 110, 105, 103, 103, 94, 101,
-  108, 91, 91, 89, 96, 108, 112, 123, 133, 133, 141, 145, 145, 145, 143, 145,
-  141, 145, 147, 151, 147, 145, 149, 151, 145, 153, 153, 147, 147, 145, 143, 139,
-  137, 145, 145, 145, 143, 151, 145, 139, 139, 135, 145, 143, 141, 137, 139, 141,
-  139, 143, 143, 139, 143, 143, 137, 141, 143, 139, 172, 203, 219, 225, 231, 233,
-  234, 233, 204, 32, 18, 23, 26, 32, 20, 32, 35, 41, 43, 35, 32, 38,
-  38, 38, 29, 26, 29, 35, 46, 26, 29, 29, 23, 26, 26, 23, 46, 46,
-  169, 171, 177, 176, 171, 164, 160, 149, 139, 112, 94, 74, 74, 105, 121, 139,
-  153, 164, 167, 167, 172, 165, 167, 165, 164, 167, 169, 158, 151, 141, 119, 98,
-  86, 71, 60, 60, 63, 74, 89, 91, 89, 91, 79, 84, 91, 91, 89, 94,
-  91, 96, 98, 96, 101, 103, 91, 101, 114, 108, 112, 103, 105, 112, 112, 108,
-  119, 112, 117, 117, 110, 114, 121, 119, 117, 114, 117, 114, 117, 112, 114, 181,
-  139, 105, 125, 121, 121, 125, 121, 114, 117, 119, 125, 117, 139, 131, 145, 137,
-  131, 137, 133, 145, 135, 151, 141, 149, 153, 155, 141, 162, 167, 167, 169, 153,
-  174, 155, 182, 193, 172, 181, 193, 201, 198, 200, 192, 185, 200, 203, 192, 198,
-  209, 193, 197, 203, 209, 201, 200, 204, 212, 206, 172, 108, 103, 103, 108, 108,
-  112, 112, 114, 112, 108, 117, 110, 108, 112, 108, 114, 112, 103, 110, 103, 105,
-  96, 103, 94, 91, 101, 103, 110, 123, 129, 131, 141, 147, 147, 143, 143, 145,
-  141, 145, 143, 143, 145, 141, 147, 145, 147, 153, 149, 153, 149, 139, 137, 145,
-  139, 137, 139, 147, 143, 143, 141, 143, 143, 147, 141, 141, 139, 135, 137, 139,
-  135, 141, 147, 143, 145, 153, 145, 137, 145, 137, 145, 184, 213, 224, 231, 233,
-  230, 215, 121, 12, 26, 12, 15, 23, 41, 23, 38, 38, 38, 29, 29, 52,
-  38, 32, 29, 26, 26, 35, 41, 46, 32, 20, 29, 32, 32, 43, 41, 32,
-  171, 174, 181, 171, 167, 162, 155, 145, 129, 110, 84, 68, 74, 98, 127, 141,
-  149, 165, 169, 167, 171, 165, 171, 162, 164, 167, 160, 155, 147, 135, 119, 105,
-  74, 63, 55, 74, 74, 81, 81, 86, 84, 89, 91, 86, 84, 91, 89, 105,
-  91, 89, 108, 96, 89, 94, 94, 101, 101, 110, 112, 108, 123, 105, 103, 114,
-  114, 117, 117, 123, 117, 114, 112, 112, 123, 121, 125, 114, 114, 119, 139, 174,
-  79, 98, 121, 123, 121, 108, 121, 112, 123, 121, 117, 121, 125, 139, 133, 129,
-  139, 127, 135, 137, 141, 131, 141, 139, 131, 156, 149, 160, 158, 158, 160, 160,
-  172, 197, 174, 171, 197, 181, 197, 201, 187, 197, 201, 200, 185, 206, 204, 185,
-  192, 204, 206, 198, 206, 207, 207, 204, 203, 203, 206, 198, 129, 101, 103, 103,
-  110, 112, 108, 108, 114, 108, 108, 112, 110, 112, 108, 105, 103, 96, 98, 101,
-  101, 101, 91, 91, 91, 98, 108, 125, 133, 135, 143, 147, 151, 155, 149, 143,
-  147, 141, 147, 151, 143, 143, 145, 143, 149, 145, 149, 153, 153, 145, 145, 139,
-  135, 141, 137, 139, 145, 143, 147, 141, 137, 143, 141, 141, 141, 139, 139, 139,
-  135, 143, 143, 143, 143, 147, 141, 139, 145, 147, 143, 151, 209, 219, 230, 228,
-  216, 158, 29, 32, 18, 29, 26, 20, 29, 23, 43, 52, 35, 52, 43, 46,
-  43, 26, 32, 32, 35, 41, 35, 20, 23, 32, 32, 29, 38, 49, 29, 12,
-  171, 169, 174, 167, 165, 153, 149, 137, 123, 103, 63, 55, 71, 103, 127, 139,
-  151, 169, 164, 176, 172, 167, 169, 169, 167, 167, 162, 151, 143, 125, 119, 101,
-  71, 68, 49, 74, 71, 81, 86, 86, 81, 96, 98, 89, 89, 94, 96, 89,
-  96, 94, 91, 91, 91, 103, 101, 103, 108, 112, 105, 108, 105, 108, 110, 108,
-  114, 117, 114, 119, 114, 114, 117, 117, 117, 121, 117, 114, 114, 117, 149, 131,
-  84, 103, 112, 110, 123, 112, 119, 121, 133, 121, 114, 112, 123, 133, 133, 139,
-  131, 123, 141, 129, 139, 139, 143, 129, 141, 151, 155, 153, 139, 169, 147, 181,
-  174, 174, 193, 181, 174, 195, 185, 182, 197, 197, 190, 193, 204, 190, 195, 204,
-  200, 193, 203, 207, 203, 200, 209, 209, 203, 203, 204, 209, 207, 176, 108, 91,
-  101, 101, 91, 101, 112, 110, 101, 110, 110, 103, 105, 110, 108, 103, 108, 98,
-  103, 98, 103, 101, 96, 101, 108, 121, 131, 139, 149, 149, 151, 153, 147, 149,
-  145, 147, 141, 149, 137, 149, 137, 139, 135, 139, 145, 151, 145, 143, 147, 143,
-  137, 141, 137, 143, 139, 145, 141, 139, 139, 145, 137, 143, 141, 141, 135, 137,
-  143, 143, 139, 149, 143, 145, 147, 149, 143, 149, 151, 143, 177, 212, 224, 212,
-  160, 29, 18, 26, 32, 20, 29, 26, 23, 41, 32, 32, 41, 41, 38, 46,
-  23, 29, 26, 35, 41, 35, 29, 26, 23, 23, 38, 41, 55, 55, 18, 6,
-  171, 172, 176, 167, 160, 151, 141, 125, 110, 71, 60, 57, 76, 108, 127, 137,
-  145, 162, 167, 169, 171, 165, 165, 171, 169, 171, 164, 156, 137, 135, 119, 101,
-  63, 68, 43, 63, 71, 68, 89, 86, 91, 103, 101, 101, 89, 94, 89, 89,
-  91, 91, 98, 98, 101, 98, 94, 108, 110, 108, 101, 105, 112, 112, 110, 112,
-  119, 114, 112, 112, 119, 117, 123, 123, 121, 121, 114, 114, 119, 133, 108, 98,
-  110, 101, 110, 114, 119, 110, 110, 127, 114, 121, 114, 117, 129, 135, 137, 141,
-  123, 135, 129, 127, 147, 127, 139, 131, 145, 139, 117, 153, 153, 164, 169, 162,
-  182, 177, 177, 198, 174, 177, 200, 184, 169, 201, 197, 181, 197, 201, 200, 193,
-  209, 204, 193, 206, 209, 212, 206, 203, 207, 209, 207, 209, 212, 210, 185, 110,
-  94, 89, 96, 98, 103, 105, 96, 108, 103, 103, 112, 108, 110, 108, 110, 98,
-  101, 103, 91, 89, 94, 101, 103, 119, 133, 135, 147, 149, 149, 151, 149, 149,
-  147, 141, 143, 137, 135, 137, 137, 141, 129, 137, 139, 145, 149, 145, 145, 139,
-  137, 143, 141, 141, 147, 145, 145, 141, 139, 139, 137, 143, 141, 143, 141, 143,
-  147, 143, 141, 143, 145, 141, 143, 145, 147, 143, 151, 151, 160, 204, 197, 139,
-  29, 18, 29, 26, 35, 29, 29, 29, 35, 32, 38, 29, 41, 43, 38, 23,
-  32, 46, 43, 43, 43, 43, 38, 29, 38, 32, 52, 55, 49, 20, 6, 18,
-  174, 174, 172, 164, 162, 147, 135, 121, 91, 66, 63, 60, 86, 105, 123, 139,
-  153, 164, 167, 167, 176, 167, 167, 169, 162, 162, 165, 155, 143, 135, 112, 96,
-  66, 71, 57, 68, 74, 91, 79, 86, 96, 91, 89, 112, 98, 91, 81, 84,
-  96, 91, 81, 86, 94, 98, 105, 101, 105, 105, 105, 112, 108, 112, 108, 103,
-  119, 110, 105, 112, 114, 110, 121, 114, 121, 110, 114, 110, 119, 149, 101, 108,
-  105, 119, 119, 112, 103, 101, 117, 119, 123, 121, 127, 133, 121, 143, 123, 135,
-  121, 143, 125, 143, 145, 137, 117, 133, 149, 143, 153, 141, 158, 147, 162, 172,
-  167, 189, 169, 181, 187, 185, 185, 200, 200, 182, 189, 206, 201, 195, 203, 209,
-  195, 201, 209, 203, 201, 207, 207, 209, 197, 206, 210, 212, 210, 206, 212, 193,
-  119, 76, 89, 91, 89, 96, 98, 96, 112, 103, 110, 96, 98, 96, 101, 103,
-  110, 98, 94, 91, 89, 96, 103, 123, 129, 143, 143, 151, 153, 153, 151, 147,
-  151, 145, 145, 141, 137, 133, 131, 133, 127, 125, 133, 141, 145, 149, 145, 143,
-  143, 135, 137, 139, 145, 147, 143, 139, 139, 141, 141, 137, 139, 147, 139, 143,
-  143, 139, 145, 145, 147, 143, 149, 151, 147, 147, 153, 153, 160, 162, 112, 29,
-  23, 26, 43, 23, 26, 32, 35, 32, 35, 32, 32, 43, 29, 43, 32, 20,
-  29, 52, 43, 38, 38, 26, 26, 49, 29, 55, 71, 60, 41, 12, 9, 38,
-  177, 172, 167, 162, 158, 139, 121, 103, 76, 63, 63, 63, 94, 112, 123, 135,
-  153, 162, 167, 174, 169, 169, 164, 164, 164, 165, 158, 151, 145, 129, 119, 105,
-  71, 66, 57, 71, 76, 74, 86, 79, 81, 89, 91, 96, 96, 103, 94, 94,
-  96, 91, 86, 101, 98, 98, 108, 105, 110, 108, 108, 114, 103, 105, 105, 114,
-  110, 112, 112, 114, 117, 112, 121, 112, 121, 119, 112, 112, 187, 119, 103, 108,
-  112, 105, 101, 98, 101, 105, 114, 119, 131, 125, 129, 105, 149, 129, 112, 141,
-  129, 141, 125, 149, 119, 137, 133, 147, 125, 149, 131, 155, 129, 167, 145, 165,
-  176, 165, 179, 167, 171, 195, 193, 182, 193, 197, 193, 187, 204, 206, 198, 198,
-  206, 204, 198, 210, 206, 206, 201, 204, 207, 206, 204, 209, 207, 206, 209, 209,
-  210, 121, 112, 98, 79, 86, 89, 96, 110, 98, 105, 103, 105, 98, 101, 98,
-  96, 91, 98, 94, 96, 96, 98, 121, 131, 147, 149, 151, 149, 162, 151, 151,
-  149, 145, 149, 143, 129, 127, 123, 125, 117, 119, 131, 139, 141, 155, 149, 143,
-  143, 139, 143, 149, 145, 147, 147, 139, 137, 143, 139, 137, 145, 139, 145, 149,
-  141, 141, 143, 147, 145, 149, 145, 147, 145, 149, 158, 156, 151, 108, 43, 29,
-  38, 26, 15, 23, 18, 20, 35, 49, 63, 38, 32, 26, 32, 26, 15, 18,
-  43, 38, 43, 49, 32, 46, 35, 41, 41, 60, 63, 29, 12, 12, 41, 127,
-  172, 167, 160, 156, 151, 139, 110, 81, 66, 71, 63, 71, 86, 110, 125, 135,
-  147, 162, 167, 171, 167, 172, 169, 164, 162, 160, 160, 153, 147, 131, 121, 91,
-  68, 66, 55, 71, 68, 68, 86, 84, 94, 84, 86, 94, 89, 96, 91, 94,
-  96, 96, 91, 101, 108, 89, 96, 103, 98, 108, 108, 108, 101, 112, 112, 123,
-  119, 114, 117, 112, 121, 110, 110, 117, 114, 119, 112, 123, 174, 101, 108, 117,
-  96, 103, 98, 103, 101, 117, 117, 108, 121, 117, 112, 133, 123, 125, 135, 129,
-  145, 121, 133, 129, 147, 141, 143, 147, 133, 143, 131, 141, 169, 153, 158, 147,
-  167, 167, 158, 190, 181, 181, 197, 197, 190, 190, 201, 200, 189, 201, 206, 200,
-  197, 204, 206, 200, 200, 207, 207, 198, 201, 207, 201, 185, 197, 203, 215, 221,
-  225, 224, 221, 207, 117, 71, 84, 91, 105, 98, 105, 108, 103, 101, 91, 91,
-  101, 105, 98, 94, 91, 103, 110, 121, 137, 143, 149, 153, 155, 155, 160, 156,
-  153, 151, 151, 139, 131, 123, 114, 114, 114, 112, 125, 127, 141, 145, 149, 147,
-  145, 145, 141, 147, 151, 151, 147, 143, 141, 141, 141, 141, 141, 143, 143, 143,
-  139, 145, 145, 143, 141, 143, 145, 145, 151, 153, 151, 158, 123, 57, 23, 32,
-  26, 20, 32, 29, 20, 35, 43, 41, 41, 43, 35, 32, 23, 23, 35, 41,
-  43, 60, 38, 32, 26, 38, 35, 38, 60, 57, 35, 20, 18, 38, 117, 151,
-  164, 162, 156, 155, 139, 123, 96, 66, 66, 74, 71, 66, 79, 114, 123, 139,
-  153, 160, 165, 171, 176, 169, 171, 167, 167, 164, 160, 156, 141, 135, 112, 108,
-  79, 52, 68, 57, 89, 71, 81, 89, 114, 91, 89, 101, 103, 89, 91, 94,
-  89, 94, 94, 103, 98, 98, 108, 105, 103, 112, 110, 105, 105, 105, 110, 108,
-  114, 114, 114, 112, 117, 117, 114, 119, 114, 112, 114, 155, 121, 105, 103, 98,
-  103, 94, 103, 105, 114, 119, 108, 114, 110, 125, 114, 137, 112, 123, 135, 127,
-  133, 127, 135, 133, 143, 131, 151, 117, 153, 143, 143, 153, 151, 167, 143, 162,
-  155, 174, 182, 162, 193, 200, 184, 197, 200, 203, 176, 200, 204, 190, 198, 198,
-  209, 190, 203, 207, 206, 195, 203, 206, 193, 195, 203, 218, 218, 219, 221, 224,
-  225, 231, 234, 234, 212, 84, 79, 79, 96, 96, 101, 105, 96, 91, 91, 98,
-  96, 91, 96, 86, 101, 94, 98, 127, 135, 141, 147, 145, 160, 155, 156, 155,
-  153, 156, 155, 149, 133, 121, 112, 98, 103, 108, 110, 119, 135, 139, 145, 149,
-  143, 143, 143, 145, 141, 149, 143, 141, 141, 145, 143, 139, 139, 141, 145, 141,
-  145, 137, 145, 143, 145, 149, 149, 149, 151, 149, 158, 139, 79, 35, 23, 32,
-  41, 18, 26, 18, 20, 35, 32, 35, 38, 35, 29, 23, 26, 29, 32, 43,
-  46, 43, 35, 29, 41, 35, 52, 46, 76, 55, 20, 26, 35, 91, 139, 167,
-  162, 164, 151, 143, 129, 108, 89, 66, 74, 76, 76, 66, 86, 110, 131, 143,
-  151, 160, 165, 172, 169, 169, 169, 171, 165, 164, 165, 153, 143, 133, 114, 101,
-  76, 66, 46, 63, 66, 74, 86, 86, 79, 86, 89, 89, 96, 91, 84, 89,
-  94, 91, 89, 89, 98, 101, 94, 105, 108, 105, 114, 105, 114, 110, 121, 112,
-  117, 110, 121, 112, 114, 117, 110, 110, 114, 117, 125, 129, 117, 101, 103, 101,
-  98, 105, 101, 108, 112, 110, 108, 108, 123, 123, 121, 123, 117, 135, 114, 135,
-  123, 125, 127, 133, 131, 141, 133, 156, 114, 137, 129, 160, 141, 155, 165, 155,
-  177, 153, 184, 193, 185, 185, 201, 203, 182, 198, 201, 192, 187, 201, 203, 198,
-  195, 204, 204, 193, 200, 195, 190, 195, 212, 219, 216, 216, 225, 218, 218, 222,
-  221, 225, 233, 236, 233, 177, 74, 71, 84, 91, 101, 96, 96, 96, 91, 94,
-  84, 96, 98, 98, 101, 103, 112, 127, 131, 143, 147, 155, 153, 158, 158, 153,
-  151, 153, 156, 141, 133, 121, 103, 94, 89, 91, 96, 117, 125, 129, 143, 155,
-  145, 147, 141, 141, 141, 143, 145, 143, 139, 137, 141, 141, 143, 149, 143, 145,
-  137, 135, 143, 139, 143, 141, 147, 151, 151, 156, 137, 103, 23, 32, 29, 32,
-  20, 23, 43, 26, 20, 46, 26, 35, 29, 32, 38, 32, 20, 32, 35, 41,
-  29, 29, 32, 29, 35, 38, 55, 71, 84, 52, 23, 35, 91, 141, 155, 171,
-  164, 156, 151, 131, 114, 94, 60, 71, 66, 74, 76, 76, 84, 103, 127, 139,
-  149, 158, 167, 174, 169, 167, 172, 167, 169, 164, 158, 155, 143, 135, 114, 89,
-  74, 60, 60, 66, 74, 81, 81, 86, 81, 96, 112, 91, 98, 86, 86, 89,
-  91, 96, 98, 101, 98, 94, 105, 105, 103, 101, 110, 105, 112, 112, 108, 114,
-  112, 112, 117, 117, 121, 112, 114, 119, 119, 121, 129, 117, 103, 110, 96, 91,
-  98, 105, 114, 114, 110, 119, 105, 125, 123, 114, 123, 121, 119, 117, 125, 125,
-  123, 125, 125, 141, 129, 125, 131, 135, 145, 119, 147, 143, 139, 143, 147, 162,
-  145, 185, 182, 174, 192, 206, 176, 190, 200, 197, 177, 201, 203, 190, 190, 204,
-  204, 192, 185, 190, 184, 198, 216, 218, 221, 216, 221, 218, 216, 222, 218, 219,
-  222, 221, 225, 230, 233, 215, 121, 60, 81, 89, 94, 89, 98, 91, 91, 89,
-  96, 89, 94, 86, 86, 96, 105, 123, 137, 139, 143, 153, 153, 151, 158, 151,
-  149, 151, 155, 143, 145, 125, 112, 76, 68, 71, 76, 96, 114, 129, 139, 145,
-  147, 143, 145, 135, 141, 143, 143, 141, 139, 141, 145, 139, 141, 145, 145, 143,
-  141, 143, 147, 147, 149, 145, 145, 156, 156, 145, 108, 38, 23, 35, 18, 20,
-  20, 29, 35, 32, 29, 38, 35, 38, 41, 32, 23, 32, 23, 38, 38, 46,
-  26, 46, 41, 26, 41, 52, 46, 66, 74, 46, 29, 81, 133, 153, 160, 162,
-  153, 153, 141, 127, 108, 86, 66, 76, 79, 71, 71, 74, 91, 108, 121, 137,
-  151, 156, 167, 172, 172, 171, 169, 171, 169, 164, 156, 156, 137, 127, 105, 117,
-  66, 55, 55, 63, 74, 79, 94, 84, 91, 91, 94, 96, 98, 86, 101, 101,
-  94, 91, 89, 96, 91, 94, 105, 105, 105, 112, 105, 105, 114, 108, 121, 117,
-  114, 119, 121, 114, 117, 114, 123, 112, 114, 121, 117, 103, 105, 91, 101, 103,
-  103, 114, 121, 108, 108, 112, 119, 119, 105, 119, 121, 112, 123, 114, 127, 112,
-  133, 119, 139, 139, 153, 135, 145, 143, 123, 145, 129, 145, 133, 145, 156, 133,
-  169, 155, 174, 181, 172, 182, 197, 195, 190, 198, 207, 201, 187, 206, 201, 193,
-  181, 179, 185, 204, 216, 219, 213, 218, 219, 216, 215, 219, 215, 216, 219, 210,
-  215, 221, 222, 230, 230, 233, 213, 84, 76, 76, 84, 89, 84, 94, 84, 91,
-  94, 89, 96, 89, 86, 105, 103, 121, 127, 139, 145, 153, 156, 155, 151, 151,
-  149, 151, 149, 143, 137, 129, 108, 81, 76, 52, 52, 81, 112, 127, 131, 145,
-  149, 143, 145, 139, 141, 145, 145, 145, 139, 145, 147, 137, 139, 145, 143, 141,
-  135, 141, 141, 145, 145, 145, 145, 155, 155, 121, 74, 35, 29, 15, 9, 20,
-  43, 23, 38, 32, 41, 43, 32, 26, 29, 35, 26, 43, 29, 35, 41, 35,
-  26, 38, 35, 35, 43, 63, 68, 57, 60, 55, 76, 123, 147, 153, 156, 162,
-  145, 147, 133, 105, 89, 60, 71, 71, 79, 74, 71, 81, 74, 105, 123, 141,
-  151, 164, 167, 171, 169, 172, 171, 169, 171, 164, 158, 156, 141, 129, 112, 98,
-  76, 68, 76, 68, 84, 79, 74, 79, 86, 89, 86, 89, 96, 91, 105, 94,
-  91, 91, 94, 94, 96, 96, 101, 103, 101, 105, 110, 103, 110, 108, 105, 110,
-  114, 117, 119, 114, 117, 114, 129, 114, 123, 125, 110, 96, 94, 105, 108, 108,
-  121, 119, 108, 110, 127, 117, 117, 119, 110, 121, 114, 127, 110, 125, 121, 137,
-  129, 137, 125, 143, 129, 137, 143, 137, 145, 131, 147, 133, 143, 147, 151, 162,
-  151, 164, 179, 160, 179, 204, 171, 187, 197, 190, 187, 204, 204, 174, 181, 174,
-  190, 210, 215, 225, 215, 215, 215, 212, 216, 215, 218, 215, 216, 212, 218, 219,
-  210, 215, 222, 221, 230, 227, 231, 181, 81, 66, 74, 94, 84, 89, 86, 84,
-  101, 89, 89, 89, 86, 98, 105, 117, 129, 135, 151, 151, 155, 153, 151, 155,
-  155, 149, 153, 141, 139, 125, 112, 89, 43, 35, 41, 74, 112, 119, 127, 135,
-  145, 145, 147, 139, 139, 137, 143, 149, 139, 139, 141, 143, 141, 143, 141, 147,
-  137, 143, 139, 135, 139, 143, 153, 156, 143, 84, 18, 15, 18, 20, 23, 15,
-  20, 20, 26, 52, 55, 43, 43, 38, 26, 15, 29, 38, 35, 43, 32, 20,
-  46, 38, 66, 74, 55, 66, 96, 68, 49, 71, 125, 147, 156, 149, 151, 153,
-  145, 139, 117, 94, 79, 63, 76, 76, 81, 81, 68, 74, 94, 103, 123, 139,
-  149, 160, 164, 167, 174, 167, 174, 172, 171, 169, 158, 155, 139, 131, 119, 98,
-  76, 63, 52, 63, 63, 79, 79, 84, 79, 79, 84, 89, 101, 96, 98, 89,
-  96, 86, 96, 98, 98, 98, 98, 112, 98, 101, 108, 110, 112, 101, 112, 119,
-  114, 112, 117, 114, 114, 114, 117, 123, 117, 110, 105, 105, 96, 96, 110, 105,
-  103, 117, 101, 127, 119, 108, 112, 119, 123, 105, 121, 105, 114, 125, 117, 133,
-  119, 129, 139, 135, 145, 125, 139, 133, 121, 153, 133, 141, 147, 145, 158, 143,
-  171, 155, 171, 184, 172, 179, 189, 193, 174, 195, 203, 185, 184, 164, 182, 203,
-  218, 215, 219, 218, 218, 213, 209, 212, 216, 212, 213, 216, 212, 215, 213, 215,
-  221, 213, 215, 219, 219, 231, 228, 227, 165, 68, 63, 74, 81, 81, 89, 91,
-  94, 86, 94, 86, 86, 94, 108, 117, 131, 139, 149, 155, 153, 155, 155, 151,
-  155, 145, 151, 143, 141, 129, 123, 94, 52, 29, 38, 46, 74, 112, 119, 137,
-  139, 149, 153, 147, 137, 139, 139, 139, 145, 139, 143, 139, 137, 139, 139, 141,
-  137, 145, 141, 141, 149, 153, 155, 149, 105, 32, 26, 18, 32, 18, 20, 32,
-  32, 49, 46, 41, 38, 43, 41, 38, 23, 18, 38, 46, 38, 29, 23, 20,
-  29, 41, 63, 55, 63, 71, 68, 55, 89, 131, 145, 155, 158, 147, 149, 143,
-  129, 129, 105, 79, 71, 68, 74, 79, 81, 84, 74, 71, 89, 103, 119, 139,
-  151, 156, 164, 167, 167, 171, 167, 169, 167, 171, 158, 149, 141, 125, 105, 96,
-  76, 63, 57, 74, 89, 86, 84, 86, 89, 81, 98, 96, 96, 105, 98, 98,
-  94, 86, 94, 94, 98, 103, 98, 98, 105, 105, 108, 110, 101, 114, 117, 121,
-  121, 119, 114, 119, 114, 108, 119, 127, 110, 105, 91, 101, 101, 101, 112, 108,
-  108, 117, 123, 117, 114, 108, 117, 114, 112, 110, 121, 121, 119, 125, 141, 121,
-  123, 137, 143, 141, 125, 151, 141, 143, 149, 139, 143, 143, 156, 156, 141, 151,
-  155, 160, 174, 153, 182, 197, 179, 189, 187, 201, 165, 164, 167, 192, 213, 215,
-  216, 221, 215, 212, 207, 212, 218, 206, 215, 215, 213, 212, 216, 209, 216, 213,
-  212, 216, 218, 224, 221, 227, 231, 224, 224, 117, 68, 68, 74, 84, 81, 84,
-  98, 96, 91, 89, 89, 89, 105, 117, 129, 133, 147, 153, 158, 155, 153, 153,
-  153, 151, 151, 151, 137, 131, 119, 94, 71, 26, 18, 29, 57, 94, 105, 121,
-  131, 147, 139, 151, 141, 137, 141, 139, 141, 141, 141, 135, 143, 139, 135, 143,
-  141, 147, 143, 141, 147, 151, 155, 119, 52, 20, 60, 81, 55, 23, 20, 38,
-  41, 41, 38, 43, 49, 43, 38, 26, 29, 26, 41, 49, 43, 41, 26, 35,
-  20, 60, 49, 49, 74, 71, 76, 86, 119, 139, 155, 156, 162, 145, 131, 155,
-  123, 117, 91, 63, 76, 74, 84, 84, 84, 66, 81, 76, 84, 105, 119, 141,
-  153, 156, 164, 167, 165, 169, 167, 169, 169, 164, 158, 153, 141, 131, 117, 89,
-  84, 63, 52, 74, 71, 79, 91, 86, 86, 81, 84, 89, 89, 91, 91, 91,
-  91, 94, 98, 94, 101, 96, 101, 103, 98, 98, 110, 108, 105, 114, 114, 112,
-  121, 119, 117, 112, 119, 117, 123, 110, 103, 108, 94, 101, 105, 105, 108, 103,
-  114, 114, 114, 114, 114, 117, 101, 117, 91, 114, 110, 131, 119, 137, 114, 139,
-  125, 145, 141, 127, 153, 137, 143, 139, 131, 147, 139, 153, 153, 139, 145, 135,
-  155, 151, 167, 187, 189, 174, 192, 187, 169, 169, 149, 198, 209, 212, 207, 215,
-  210, 212, 210, 215, 221, 213, 210, 215, 206, 213, 212, 212, 210, 210, 206, 218,
-  219, 222, 222, 224, 222, 230, 233, 231, 227, 206, 84, 66, 60, 74, 76, 81,
-  81, 76, 79, 84, 84, 98, 110, 117, 127, 139, 149, 153, 160, 155, 151, 155,
-  156, 156, 153, 141, 141, 137, 121, 96, 63, 23, 20, 23, 57, 94, 101, 108,
-  127, 141, 143, 149, 147, 145, 151, 143, 141, 143, 141, 135, 141, 133, 143, 145,
-  143, 139, 145, 145, 149, 155, 137, 74, 18, 41, 23, 26, 32, 26, 26, 26,
-  41, 32, 26, 38, 43, 41, 32, 29, 32, 49, 46, 32, 29, 32, 32, 41,
-  35, 38, 55, 57, 79, 84, 84, 112, 137, 145, 158, 156, 158, 139, 145, 162,
-  112, 103, 68, 66, 76, 76, 96, 84, 84, 79, 68, 68, 94, 105, 121, 139,
-  143, 153, 160, 164, 171, 167, 169, 172, 169, 160, 160, 156, 141, 129, 114, 96,
-  74, 66, 79, 71, 86, 89, 86, 91, 94, 96, 98, 81, 86, 84, 98, 84,
-  103, 89, 84, 98, 105, 94, 105, 108, 119, 98, 105, 108, 110, 119, 114, 114,
-  117, 119, 121, 114, 119, 125, 117, 121, 98, 96, 103, 121, 110, 105, 123, 108,
-  110, 114, 112, 110, 105, 108, 110, 108, 108, 119, 119, 129, 131, 114, 137, 121,
-  149, 137, 149, 143, 129, 149, 141, 149, 156, 143, 158, 119, 153, 151, 139, 151,
-  139, 167, 181, 156, 185, 185, 181, 169, 147, 167, 203, 215, 212, 215, 213, 203,
-  209, 212, 212, 222, 213, 216, 210, 210, 206, 204, 204, 207, 210, 216, 227, 225,
-  221, 215, 221, 215, 219, 225, 225, 234, 228, 233, 181, 81, 66, 57, 71, 79,
-  81, 76, 81, 76, 84, 98, 108, 127, 131, 143, 149, 151, 155, 153, 155, 151,
-  158, 156, 149, 147, 139, 129, 125, 86, 63, 23, 15, 23, 46, 68, 96, 114,
-  121, 139, 143, 145, 147, 149, 143, 145, 135, 143, 139, 149, 139, 141, 139, 137,
-  141, 143, 145, 145, 149, 151, 103, 38, 18, 18, 29, 26, 23, 35, 29, 41,
-  41, 29, 55, 41, 29, 29, 12, 23, 41, 46, 57, 32, 35, 35, 41, 35,
-  43, 41, 57, 81, 71, 94, 117, 141, 151, 156, 151, 155, 147, 141, 158, 172,
-  96, 94, 63, 71, 76, 79, 79, 86, 76, 74, 76, 76, 84, 103, 125, 137,
-  145, 160, 158, 164, 164, 167, 172, 169, 165, 167, 158, 155, 141, 137, 110, 98,
-  76, 52, 74, 76, 81, 86, 86, 76, 86, 96, 84, 84, 89, 94, 89, 94,
-  96, 96, 86, 98, 89, 91, 101, 108, 112, 105, 112, 117, 105, 110, 108, 112,
-  112, 114, 117, 119, 121, 129, 112, 110, 105, 110, 105, 112, 103, 117, 105, 112,
-  117, 112, 123, 103, 114, 105, 112, 112, 119, 112, 125, 119, 145, 119, 121, 143,
-  127, 143, 133, 133, 153, 129, 151, 149, 149, 149, 133, 141, 147, 127, 149, 135,
-  164, 156, 158, 181, 190, 158, 151, 147, 181, 210, 207, 212, 210, 210, 209, 209,
-  209, 218, 209, 215, 213, 206, 209, 204, 213, 206, 215, 216, 216, 213, 219, 215,
-  210, 209, 212, 213, 213, 218, 219, 221, 224, 227, 222, 172, 101, 76, 63, 74,
-  63, 81, 86, 68, 71, 86, 103, 117, 133, 135, 145, 153, 155, 155, 155, 151,
-  155, 156, 149, 149, 139, 133, 121, 91, 57, 20, 35, 43, 20, 76, 89, 98,
-  125, 127, 139, 145, 145, 145, 139, 133, 139, 137, 137, 133, 137, 147, 143, 143,
-  147, 143, 143, 151, 155, 129, 57, 41, 18, 12, 23, 26, 32, 32, 38, 38,
-  55, 32, 46, 29, 20, 20, 15, 32, 41, 46, 23, 26, 46, 41, 32, 38,
-  57, 49, 41, 66, 81, 121, 133, 149, 151, 156, 151, 149, 147, 160, 164, 171,
-  86, 74, 74, 79, 76, 81, 81, 81, 79, 79, 71, 71, 96, 98, 123, 133,
-  145, 155, 164, 165, 167, 167, 169, 169, 164, 165, 160, 151, 135, 125, 121, 96,
-  79, 63, 60, 63, 76, 89, 89, 89, 91, 84, 89, 91, 89, 91, 84, 89,
-  98, 98, 105, 96, 101, 110, 94, 105, 110, 105, 110, 112, 108, 108, 119, 119,
-  119, 112, 112, 114, 135, 112, 105, 105, 110, 114, 103, 105, 98, 110, 105, 108,
-  105, 121, 101, 127, 117, 123, 96, 123, 101, 121, 114, 143, 117, 141, 129, 119,
-  137, 131, 139, 137, 121, 153, 131, 145, 151, 137, 151, 143, 145, 145, 143, 156,
-  139, 158, 177, 171, 153, 125, 165, 192, 206, 204, 213, 209, 201, 210, 213, 216,
-  209, 203, 210, 206, 198, 206, 201, 213, 213, 215, 212, 204, 206, 204, 207, 210,
-  210, 213, 216, 216, 219, 219, 221, 218, 224, 225, 227, 233, 218, 160, 63, 52,
-  63, 57, 81, 79, 74, 89, 103, 119, 127, 137, 149, 155, 153, 153, 155, 155,
-  151, 151, 155, 145, 145, 133, 119, 91, 74, 26, 23, 32, 52, 26, 71, 84,
-  119, 117, 131, 141, 143, 145, 145, 145, 141, 137, 135, 137, 141, 143, 143, 147,
-  141, 143, 151, 151, 139, 98, 15, 15, 18, 20, 18, 35, 23, 63, 41, 38,
-  41, 35, 32, 32, 26, 26, 23, 35, 43, 35, 35, 20, 46, 35, 43, 38,
-  43, 46, 49, 60, 103, 133, 149, 149, 155, 158, 149, 143, 160, 171, 165, 172,
-  76, 63, 66, 86, 76, 79, 71, 79, 79, 84, 74, 68, 84, 96, 117, 139,
-  143, 162, 158, 164, 172, 172, 169, 169, 172, 167, 165, 153, 141, 131, 114, 98,
-  76, 60, 63, 63, 76, 84, 84, 91, 86, 101, 91, 89, 89, 96, 86, 98,
-  89, 96, 94, 96, 96, 96, 103, 103, 103, 105, 114, 110, 103, 121, 114, 110,
-  129, 108, 114, 127, 141, 98, 98, 96, 101, 112, 112, 103, 98, 105, 110, 105,
-  112, 108, 101, 123, 114, 123, 112, 129, 105, 121, 131, 121, 135, 129, 139, 129,
-  131, 139, 137, 133, 145, 143, 145, 141, 137, 147, 125, 135, 141, 129, 143, 133,
-  158, 169, 160, 153, 127, 182, 204, 201, 198, 203, 200, 210, 210, 203, 213, 213,
-  210, 206, 206, 207, 204, 212, 206, 209, 206, 209, 207, 210, 212, 210, 216, 209,
-  212, 216, 216, 218, 215, 218, 215, 219, 222, 222, 225, 227, 230, 230, 160, 110,
-  41, 55, 68, 68, 76, 86, 101, 117, 129, 137, 155, 151, 153, 155, 158, 151,
-  151, 153, 155, 172, 141, 131, 114, 96, 74, 23, 20, 20, 23, 29, 43, 66,
-  89, 112, 123, 131, 143, 143, 143, 143, 137, 137, 135, 143, 141, 133, 141, 143,
-  147, 149, 155, 149, 108, 23, 15, 20, 20, 20, 23, 23, 52, 29, 46, 57,
-  41, 32, 35, 41, 23, 29, 46, 41, 38, 23, 38, 32, 49, 41, 35, 43,
-  52, 57, 68, 86, 129, 139, 151, 145, 156, 158, 143, 155, 169, 172, 172, 169,
-  86, 84, 68, 79, 91, 76, 79, 84, 84, 81, 71, 74, 81, 108, 121, 139,
-  143, 158, 164, 167, 169, 169, 171, 169, 169, 164, 158, 153, 147, 125, 121, 101,
-  86, 60, 55, 66, 71, 81, 86, 86, 94, 84, 91, 79, 86, 94, 86, 94,
-  94, 94, 86, 98, 91, 108, 101, 105, 105, 112, 112, 114, 112, 110, 112, 112,
-  117, 117, 114, 139, 119, 98, 112, 91, 108, 101, 110, 103, 105, 108, 112, 96,
-  110, 101, 110, 112, 112, 114, 125, 108, 133, 137, 139, 137, 119, 143, 131, 143,
-  153, 129, 149, 145, 125, 156, 131, 137, 135, 133, 139, 123, 141, 149, 133, 151,
-  131, 155, 135, 139, 187, 207, 206, 204, 204, 203, 207, 197, 207, 204, 201, 207,
-  206, 204, 206, 207, 210, 195, 206, 209, 215, 203, 215, 218, 212, 213, 213, 215,
-  216, 215, 216, 218, 216, 216, 219, 213, 219, 221, 224, 219, 225, 231, 228, 164,
-  52, 52, 55, 68, 74, 84, 98, 123, 135, 137, 147, 155, 155, 153, 153, 151,
-  156, 153, 162, 155, 137, 131, 114, 96, 66, 26, 20, 23, 12, 20, 23, 49,
-  79, 91, 127, 125, 139, 145, 145, 143, 141, 137, 137, 135, 141, 139, 145, 147,
-  147, 151, 147, 133, 49, 32, 9, 15, 23, 23, 43, 35, 41, 43, 41, 35,
-  41, 46, 26, 35, 32, 41, 43, 66, 41, 26, 46, 32, 38, 38, 43, 35,
-  46, 52, 91, 127, 153, 149, 149, 151, 153, 145, 153, 165, 172, 171, 171, 171,
-  74, 89, 86, 81, 86, 76, 89, 94, 79, 89, 76, 76, 89, 103, 121, 139,
-  143, 158, 162, 158, 167, 167, 167, 167, 167, 165, 160, 155, 145, 131, 117, 103,
-  91, 60, 63, 68, 81, 79, 89, 84, 86, 86, 84, 101, 98, 86, 94, 94,
-  89, 98, 89, 101, 96, 94, 101, 103, 98, 108, 112, 110, 108, 117, 117, 114,
-  110, 110, 147, 112, 108, 94, 96, 91, 98, 101, 121, 114, 105, 103, 110, 108,
-  123, 119, 110, 110, 125, 105, 121, 125, 125, 139, 114, 139, 139, 133, 153, 139,
-  137, 141, 141, 141, 147, 131, 145, 139, 133, 139, 131, 145, 133, 143, 149, 123,
-  145, 127, 167, 187, 204, 200, 207, 210, 210, 195, 206, 200, 198, 204, 203, 197,
-  203, 206, 204, 200, 203, 212, 213, 207, 215, 216, 204, 213, 213, 213, 213, 213,
-  218, 219, 212, 207, 213, 215, 216, 212, 221, 221, 219, 219, 218, 222, 230, 225,
-  121, 26, 46, 57, 74, 81, 103, 119, 129, 135, 151, 149, 155, 155, 151, 149,
-  149, 153, 155, 151, 143, 133, 110, 91, 66, 29, 23, 20, 12, 18, 15, 26,
-  63, 81, 119, 123, 127, 137, 143, 143, 141, 135, 139, 135, 135, 143, 137, 145,
-  147, 147, 145, 89, 20, 26, 20, 32, 23, 26, 41, 32, 41, 49, 38, 32,
-  41, 38, 32, 26, 29, 38, 29, 23, 23, 29, 35, 35, 57, 41, 38, 38,
-  43, 81, 129, 145, 155, 153, 147, 143, 137, 145, 160, 169, 174, 171, 172, 169,
-  71, 71, 76, 79, 84, 84, 86, 86, 84, 81, 71, 79, 98, 108, 127, 133,
-  145, 156, 162, 167, 165, 164, 171, 176, 162, 165, 160, 153, 147, 135, 112, 101,
-  76, 68, 66, 66, 74, 74, 91, 86, 81, 81, 94, 86, 96, 98, 89, 81,
-  91, 81, 94, 96, 94, 101, 98, 108, 103, 101, 110, 114, 112, 105, 121, 110,
-  105, 123, 203, 117, 89, 98, 94, 96, 96, 101, 108, 105, 108, 105, 103, 105,
-  98, 108, 101, 112, 98, 127, 114, 135, 117, 123, 139, 125, 133, 143, 145, 141,
-  129, 127, 141, 141, 143, 141, 139, 149, 133, 125, 127, 108, 141, 127, 121, 123,
-  145, 190, 197, 179, 182, 204, 204, 209, 201, 204, 192, 207, 198, 193, 203, 207,
-  187, 195, 197, 204, 210, 212, 212, 213, 201, 213, 215, 209, 213, 210, 215, 209,
-  215, 216, 215, 213, 219, 216, 216, 215, 212, 224, 222, 222, 225, 228, 218, 228,
-  209, 55, 52, 52, 66, 76, 101, 117, 127, 139, 145, 153, 153, 153, 153, 156,
-  151, 153, 149, 145, 139, 129, 123, 103, 76, 35, 20, 18, 35, 23, 18, 20,
-  46, 74, 84, 110, 127, 129, 141, 147, 145, 137, 137, 133, 135, 139, 141, 145,
-  149, 151, 112, 35, 29, 26, 18, 23, 20, 18, 35, 35, 29, 38, 55, 35,
-  43, 35, 26, 29, 35, 43, 35, 23, 32, 23, 35, 29, 32, 38, 41, 49,
-  60, 112, 141, 155, 158, 143, 141, 141, 151, 160, 169, 172, 172, 176, 172, 169,
-  86, 81, 86, 84, 89, 84, 76, 66, 76, 84, 79, 79, 94, 110, 125, 137,
-  149, 158, 162, 162, 167, 164, 165, 165, 164, 162, 165, 155, 139, 131, 114, 103,
-  89, 60, 66, 71, 79, 81, 86, 79, 86, 98, 94, 84, 94, 91, 94, 94,
-  89, 89, 98, 98, 94, 96, 98, 103, 112, 105, 112, 105, 101, 110, 114, 110,
-  108, 156, 174, 108, 86, 86, 91, 108, 96, 112, 110, 110, 108, 108, 98, 117,
-  96, 112, 108, 108, 112, 119, 131, 98, 131, 127, 131, 129, 141, 151, 145, 133,
-  112, 153, 131, 143, 143, 133, 147, 127, 139, 141, 114, 135, 131, 121, 119, 171,
-  182, 204, 190, 187, 198, 197, 203, 204, 195, 201, 206, 192, 204, 203, 195, 193,
-  195, 204, 207, 206, 209, 209, 213, 212, 215, 206, 219, 216, 195, 215, 218, 213,
-  213, 218, 212, 213, 215, 213, 213, 215, 209, 213, 218, 224, 221, 230, 225, 230,
-  231, 114, 84, 52, 52, 74, 101, 108, 123, 141, 145, 153, 153, 153, 153, 155,
-  151, 156, 151, 147, 145, 129, 117, 101, 71, 41, 18, 29, 20, 15, 12, 9,
-  23, 46, 81, 103, 117, 121, 133, 139, 143, 137, 135, 131, 137, 143, 143, 147,
-  155, 129, 57, 20, 18, 26, 20, 23, 52, 26, 32, 32, 43, 49, 46, 38,
-  52, 29, 32, 41, 41, 52, 38, 35, 38, 35, 46, 41, 41, 20, 29, 74,
-  108, 141, 151, 153, 149, 145, 131, 149, 158, 167, 169, 169, 172, 172, 172, 172,
-  84, 76, 84, 84, 89, 81, 79, 89, 79, 74, 68, 79, 89, 105, 125, 143,
-  147, 162, 164, 164, 167, 167, 165, 162, 162, 164, 162, 153, 145, 141, 123, 96,
-  68, 63, 63, 66, 74, 76, 79, 89, 86, 91, 98, 89, 96, 96, 94, 91,
-  91, 94, 101, 94, 103, 98, 108, 103, 108, 103, 112, 110, 110, 114, 110, 98,
-  110, 206, 176, 91, 98, 84, 114, 94, 98, 98, 98, 112, 101, 101, 112, 103,
-  117, 114, 114, 119, 114, 119, 133, 129, 117, 133, 141, 133, 153, 141, 121, 143,
-  145, 108, 156, 143, 137, 151, 121, 131, 129, 131, 121, 96, 110, 123, 184, 179,
-  192, 189, 209, 198, 201, 187, 198, 189, 207, 203, 201, 207, 184, 195, 201, 206,
-  207, 204, 207, 209, 203, 210, 210, 213, 213, 212, 210, 216, 209, 213, 213, 212,
-  212, 215, 213, 212, 209, 213, 210, 215, 212, 218, 219, 221, 225, 222, 228, 233,
-  233, 218, 114, 38, 55, 68, 91, 112, 127, 135, 143, 147, 149, 149, 156, 153,
-  158, 156, 155, 149, 139, 123, 119, 96, 74, 41, 26, 23, 35, 15, 15, 18,
-  15, 29, 46, 84, 101, 114, 123, 141, 162, 156, 149, 127, 137, 143, 153, 149,
-  147, 91, 32, 23, 20, 32, 20, 32, 35, 26, 52, 43, 35, 41, 41, 41,
-  38, 26, 38, 49, 41, 26, 38, 26, 41, 49, 29, 35, 18, 23, 32, 94,
-  133, 151, 153, 149, 151, 137, 143, 160, 165, 164, 174, 171, 169, 167, 169, 169,
-  74, 96, 74, 86, 81, 89, 89, 91, 84, 76, 68, 76, 86, 96, 123, 139,
-  145, 155, 160, 167, 169, 165, 164, 167, 165, 169, 165, 153, 141, 129, 112, 103,
-  81, 71, 55, 76, 76, 74, 76, 86, 84, 86, 76, 94, 89, 91, 101, 89,
-  96, 89, 98, 98, 108, 94, 101, 110, 98, 110, 110, 117, 105, 110, 103, 103,
-  147, 210, 143, 86, 96, 101, 101, 94, 105, 108, 91, 110, 98, 112, 105, 103,
-  117, 108, 117, 117, 108, 133, 119, 121, 135, 133, 151, 135, 131, 127, 145, 123,
-  139, 145, 131, 137, 147, 125, 135, 119, 127, 121, 105, 98, 155, 182, 185, 185,
-  192, 200, 206, 204, 185, 193, 190, 201, 198, 203, 190, 172, 197, 206, 210, 200,
-  212, 210, 201, 201, 207, 207, 213, 213, 212, 215, 206, 210, 212, 212, 215, 215,
-  213, 200, 203, 210, 212, 216, 219, 218, 216, 215, 218, 218, 221, 219, 222, 230,
-  231, 234, 210, 43, 43, 60, 89, 110, 123, 129, 147, 151, 147, 149, 153, 153,
-  155, 155, 155, 160, 139, 125, 121, 105, 74, 46, 35, 23, 15, 29, 23, 35,
-  15, 12, 20, 52, 74, 137, 204, 209, 225, 225, 218, 179, 176, 207, 176, 143,
-  105, 29, 23, 18, 32, 23, 41, 35, 46, 23, 46, 41, 29, 43, 41, 52,
-  38, 46, 32, 43, 38, 29, 43, 35, 35, 41, 32, 32, 20, 29, 79, 129,
-  149, 155, 151, 139, 139, 137, 153, 164, 165, 169, 171, 167, 164, 162, 164, 169,
-  79, 91, 81, 81, 84, 79, 74, 76, 74, 74, 68, 68, 81, 101, 125, 137,
-  147, 149, 160, 167, 167, 164, 165, 167, 169, 164, 164, 155, 145, 139, 121, 103,
-  86, 74, 68, 66, 68, 81, 79, 84, 84, 79, 86, 84, 103, 91, 98, 94,
-  81, 96, 101, 121, 108, 103, 101, 94, 98, 101, 105, 108, 103, 108, 101, 94,
-  201, 198, 155, 89, 89, 103, 89, 98, 101, 101, 103, 105, 105, 112, 94, 101,
-  86, 123, 110, 110, 123, 114, 133, 114, 127, 137, 127, 129, 151, 137, 131, 141,
-  127, 114, 139, 137, 143, 123, 105, 127, 119, 105, 114, 162, 167, 195, 193, 197,
-  189, 195, 187, 187, 197, 197, 200, 192, 190, 169, 190, 193, 198, 203, 203, 209,
-  203, 204, 209, 206, 203, 210, 204, 215, 210, 210, 209, 212, 207, 215, 209, 206,
-  209, 212, 207, 212, 212, 215, 212, 219, 218, 210, 218, 221, 216, 222, 221, 231,
-  231, 233, 231, 103, 29, 60, 81, 103, 127, 137, 145, 151, 147, 151, 153, 153,
-  155, 151, 149, 153, 141, 137, 127, 89, 79, 38, 32, 20, 32, 26, 26, 12,
-  18, 12, 20, 68, 187, 213, 225, 225, 218, 212, 203, 213, 225, 225, 225, 185,
-  55, 20, 26, 41, 18, 63, 20, 35, 46, 38, 41, 38, 43, 46, 60, 49,
-  35, 49, 38, 35, 29, 26, 41, 38, 41, 32, 23, 23, 41, 71, 119, 139,
-  156, 151, 149, 143, 141, 149, 156, 167, 172, 171, 162, 169, 165, 169, 164, 164,
-  81, 81, 84, 79, 89, 89, 76, 76, 71, 81, 71, 79, 79, 98, 112, 139,
-  141, 160, 162, 165, 167, 164, 164, 165, 164, 165, 164, 149, 145, 131, 114, 101,
-  89, 55, 55, 63, 66, 76, 71, 76, 76, 91, 91, 79, 91, 89, 84, 86,
-  96, 101, 81, 94, 89, 98, 94, 108, 105, 112, 103, 101, 105, 96, 101, 121,
-  222, 189, 110, 79, 96, 91, 84, 101, 103, 101, 114, 114, 103, 96, 110, 94,
-  114, 101, 121, 110, 123, 129, 123, 135, 131, 129, 141, 131, 137, 143, 121, 119,
-  135, 141, 141, 135, 105, 123, 127, 108, 112, 129, 184, 185, 171, 184, 207, 201,
-  197, 181, 184, 181, 197, 206, 204, 177, 179, 195, 190, 201, 193, 201, 201, 204,
-  209, 206, 206, 204, 207, 207, 203, 201, 212, 213, 210, 207, 207, 197, 212, 215,
-  207, 219, 215, 204, 210, 215, 216, 215, 219, 213, 216, 219, 216, 219, 221, 222,
-  230, 228, 231, 185, 29, 55, 81, 103, 123, 133, 141, 151, 149, 158, 155, 151,
-  155, 156, 149, 155, 141, 137, 125, 103, 68, 38, 32, 29, 32, 29, 18, 23,
-  41, 26, 68, 203, 219, 227, 219, 204, 193, 215, 215, 219, 222, 224, 224, 219,
-  79, 15, 23, 29, 29, 35, 20, 46, 55, 52, 46, 46, 26, 43, 41, 29,
-  38, 41, 43, 41, 29, 35, 49, 63, 38, 23, 15, 26, 55, 108, 143, 151,
-  153, 149, 149, 139, 151, 162, 169, 179, 165, 165, 169, 169, 165, 164, 165, 164,
-  94, 84, 86, 89, 81, 71, 74, 81, 81, 76, 68, 81, 68, 98, 123, 129,
-  147, 153, 162, 165, 162, 165, 169, 162, 158, 165, 160, 153, 143, 133, 112, 103,
-  68, 55, 60, 68, 74, 74, 86, 74, 89, 86, 89, 86, 86, 94, 89, 86,
-  96, 96, 96, 98, 91, 94, 96, 101, 103, 103, 108, 101, 98, 89, 96, 169,
-  216, 153, 117, 98, 94, 86, 98, 96, 108, 98, 108, 110, 103, 103, 110, 110,
-  105, 127, 101, 121, 123, 125, 133, 121, 133, 135, 135, 139, 133, 121, 125, 139,
-  137, 135, 125, 101, 121, 103, 86, 103, 151, 174, 167, 189, 193, 181, 207, 181,
-  187, 190, 181, 184, 200, 189, 179, 195, 200, 195, 195, 189, 200, 201, 204, 198,
-  201, 204, 195, 213, 203, 201, 207, 207, 206, 210, 200, 198, 204, 209, 215, 213,
-  215, 209, 216, 216, 207, 210, 215, 218, 215, 218, 216, 218, 216, 218, 219, 221,
-  225, 233, 233, 218, 71, 49, 71, 103, 117, 135, 143, 149, 149, 153, 153, 153,
-  151, 153, 151, 155, 143, 133, 114, 94, 66, 35, 26, 20, 26, 23, 18, 23,
-  35, 119, 210, 225, 224, 210, 189, 212, 213, 222, 231, 233, 233, 236, 233, 230,
-  176, 29, 23, 29, 26, 29, 38, 49, 35, 38, 38, 49, 52, 43, 46, 35,
-  35, 43, 49, 35, 38, 46, 35, 35, 41, 29, 23, 26, 84, 133, 151, 151,
-  149, 149, 143, 151, 158, 174, 174, 179, 167, 167, 164, 169, 165, 162, 165, 165,
-  76, 81, 79, 81, 81, 84, 74, 79, 84, 86, 76, 60, 79, 105, 119, 131,
-  143, 155, 158, 165, 169, 162, 165, 164, 165, 167, 160, 155, 139, 129, 112, 98,
-  57, 63, 49, 55, 60, 68, 76, 81, 86, 91, 86, 89, 86, 89, 91, 86,
-  96, 89, 91, 103, 94, 91, 98, 103, 105, 101, 103, 98, 103, 94, 98, 221,
-  201, 172, 131, 96, 84, 101, 101, 96, 105, 105, 96, 112, 103, 117, 98, 125,
-  101, 117, 117, 105, 131, 119, 131, 127, 125, 119, 143, 114, 98, 135, 135, 129,
-  133, 119, 137, 123, 101, 105, 110, 171, 182, 179, 182, 200, 182, 171, 185, 187,
-  179, 181, 192, 192, 156, 176, 198, 195, 197, 187, 190, 198, 189, 203, 204, 200,
-  206, 204, 206, 197, 207, 198, 204, 203, 201, 189, 206, 212, 210, 210, 209, 210,
-  215, 209, 206, 215, 213, 206, 212, 213, 215, 216, 215, 215, 212, 213, 212, 216,
-  224, 228, 233, 228, 176, 43, 79, 103, 117, 131, 143, 149, 158, 149, 155, 156,
-  153, 149, 153, 155, 145, 135, 117, 94, 71, 29, 29, 20, 23, 18, 20, 41,
-  151, 213, 227, 221, 193, 179, 218, 222, 227, 228, 230, 230, 230, 233, 237, 237,
-  222, 32, 35, 32, 32, 26, 32, 38, 43, 41, 46, 32, 35, 32, 29, 29,
-  32, 43, 29, 38, 32, 46, 35, 49, 35, 23, 52, 68, 121, 149, 156, 156,
-  149, 145, 147, 158, 164, 171, 169, 171, 167, 167, 165, 167, 169, 169, 162, 162,
-  79, 74, 84, 71, 79, 79, 79, 84, 86, 86, 79, 79, 84, 96, 121, 127,
-  147, 153, 164, 162, 169, 171, 171, 169, 164, 165, 162, 156, 147, 125, 117, 91,
-  74, 57, 52, 52, 68, 66, 81, 86, 81, 81, 86, 101, 89, 101, 86, 84,
-  89, 98, 84, 91, 98, 103, 91, 94, 91, 110, 103, 105, 96, 89, 123, 218,
-  195, 169, 110, 86, 84, 91, 94, 96, 96, 94, 105, 123, 101, 101, 110, 98,
-  123, 96, 105, 123, 129, 127, 127, 110, 125, 127, 101, 119, 131, 135, 141, 137,
-  121, 131, 121, 105, 98, 119, 165, 162, 177, 190, 185, 184, 177, 164, 174, 171,
-  193, 201, 172, 179, 184, 195, 177, 195, 187, 198, 200, 192, 201, 193, 206, 193,
-  201, 204, 203, 207, 198, 206, 195, 190, 203, 210, 206, 209, 212, 209, 212, 210,
-  209, 207, 209, 203, 209, 207, 207, 216, 216, 212, 213, 213, 213, 213, 219, 216,
-  215, 224, 233, 230, 222, 108, 57, 96, 117, 137, 133, 155, 155, 149, 156, 158,
-  151, 151, 151, 149, 137, 129, 121, 103, 57, 20, 18, 12, 15, 23, 66, 195,
-  216, 221, 213, 171, 195, 221, 224, 225, 222, 224, 225, 222, 228, 228, 230, 237,
-  231, 63, 32, 32, 23, 26, 29, 29, 32, 43, 66, 23, 32, 35, 26, 38,
-  49, 29, 29, 29, 35, 29, 35, 32, 26, 38, 60, 108, 143, 158, 158, 145,
-  143, 145, 153, 164, 167, 169, 167, 169, 167, 165, 165, 167, 164, 160, 164, 162,
-  79, 86, 86, 91, 81, 79, 79, 86, 86, 79, 76, 71, 74, 108, 114, 129,
-  143, 153, 160, 165, 167, 169, 165, 164, 164, 165, 160, 149, 141, 131, 114, 96,
-  71, 74, 57, 60, 49, 76, 71, 86, 84, 89, 91, 91, 86, 91, 86, 96,
-  84, 98, 94, 94, 91, 94, 101, 94, 103, 105, 110, 117, 96, 89, 155, 219,
-  200, 155, 110, 84, 89, 91, 96, 91, 101, 101, 112, 117, 105, 94, 125, 105,
-  94, 123, 125, 123, 133, 119, 110, 125, 119, 108, 129, 131, 135, 131, 117, 123,
-  119, 101, 108, 74, 133, 174, 182, 169, 187, 189, 171, 172, 181, 172, 155, 200,
-  172, 160, 185, 197, 195, 189, 185, 169, 203, 193, 203, 198, 193, 203, 189, 206,
-  192, 206, 204, 203, 201, 177, 201, 204, 203, 207, 210, 206, 204, 206, 210, 210,
-  207, 209, 210, 209, 203, 210, 209, 210, 213, 218, 209, 218, 218, 218, 218, 216,
-  218, 221, 225, 230, 230, 201, 63, 79, 119, 133, 141, 155, 156, 160, 160, 160,
-  158, 153, 160, 153, 145, 135, 114, 89, 55, 23, 15, 18, 26, 86, 203, 219,
-  224, 204, 162, 197, 218, 228, 224, 221, 219, 218, 224, 224, 218, 222, 227, 237,
-  231, 123, 35, 26, 32, 32, 29, 32, 35, 46, 49, 38, 29, 29, 23, 20,
-  23, 15, 46, 32, 43, 43, 43, 43, 46, 41, 84, 139, 156, 156, 155, 149,
-  141, 155, 165, 167, 169, 169, 164, 167, 165, 169, 167, 165, 162, 164, 165, 160,
-  81, 84, 91, 81, 91, 81, 81, 89, 91, 91, 86, 71, 84, 101, 114, 137,
-  147, 155, 164, 174, 174, 167, 172, 167, 167, 171, 164, 155, 145, 129, 121, 101,
-  68, 57, 66, 55, 68, 76, 81, 89, 89, 91, 86, 89, 86, 96, 98, 94,
-  89, 94, 101, 91, 94, 94, 98, 110, 110, 101, 110, 108, 103, 96, 181, 216,
-  187, 137, 103, 81, 89, 103, 91, 98, 91, 108, 103, 105, 76, 110, 103, 103,
-  127, 121, 125, 131, 114, 123, 119, 105, 117, 131, 139, 131, 112, 108, 137, 121,
-  108, 117, 98, 141, 160, 174, 182, 195, 184, 174, 164, 165, 171, 185, 192, 167,
-  182, 195, 182, 189, 193, 190, 182, 190, 185, 206, 195, 206, 198, 189, 189, 193,
-  204, 195, 193, 182, 189, 206, 207, 210, 203, 203, 206, 204, 200, 193, 204, 212,
-  209, 206, 209, 210, 212, 209, 210, 210, 216, 216, 216, 218, 216, 212, 209, 213,
-  213, 216, 216, 222, 224, 225, 145, 74, 114, 129, 145, 151, 155, 151, 155, 158,
-  156, 155, 156, 151, 143, 127, 101, 91, 41, 20, 15, 32, 123, 212, 227, 218,
-  190, 156, 207, 221, 227, 224, 221, 218, 218, 218, 219, 216, 209, 219, 227, 234,
-  234, 158, 35, 26, 23, 18, 32, 32, 41, 29, 52, 32, 26, 26, 29, 20,
-  15, 35, 35, 38, 46, 43, 46, 32, 35, 57, 112, 149, 162, 153, 151, 147,
-  153, 162, 165, 167, 162, 164, 164, 164, 167, 162, 165, 162, 164, 164, 162, 164,
-  84, 86, 91, 91, 86, 89, 94, 89, 84, 81, 103, 91, 89, 105, 114, 125,
-  145, 158, 160, 169, 171, 167, 171, 172, 169, 167, 165, 158, 145, 137, 110, 94,
-  71, 63, 68, 66, 66, 79, 84, 81, 84, 86, 89, 89, 84, 96, 91, 86,
-  91, 96, 101, 94, 103, 94, 98, 103, 105, 105, 105, 96, 98, 96, 218, 206,
-  176, 177, 103, 76, 98, 89, 103, 108, 103, 101, 110, 71, 110, 119, 117, 110,
-  117, 127, 112, 119, 125, 101, 105, 127, 119, 129, 137, 117, 119, 133, 127, 108,
-  103, 98, 153, 162, 165, 181, 177, 179, 177, 171, 156, 167, 190, 181, 162, 182,
-  190, 192, 189, 182, 184, 185, 200, 193, 197, 189, 198, 185, 203, 195, 203, 185,
-  193, 190, 182, 201, 198, 206, 206, 207, 207, 198, 203, 209, 207, 204, 193, 209,
-  210, 209, 204, 209, 209, 218, 216, 215, 213, 209, 203, 210, 210, 213, 213, 215,
-  213, 215, 215, 218, 222, 225, 209, 112, 114, 125, 143, 153, 153, 158, 158, 156,
-  155, 155, 153, 151, 135, 119, 101, 66, 38, 26, 60, 167, 219, 224, 215, 179,
-  176, 209, 222, 222, 221, 221, 221, 215, 210, 209, 212, 213, 218, 221, 225, 231,
-  236, 162, 29, 26, 23, 26, 43, 55, 46, 29, 35, 20, 23, 35, 23, 23,
-  29, 26, 29, 35, 41, 38, 29, 23, 35, 101, 145, 153, 156, 153, 147, 151,
-  162, 164, 164, 164, 167, 164, 165, 164, 165, 164, 167, 164, 160, 162, 164, 165,
-  86, 89, 84, 89, 94, 91, 98, 89, 81, 84, 91, 91, 86, 103, 110, 135,
-  141, 155, 162, 165, 174, 172, 176, 174, 171, 169, 164, 158, 143, 135, 114, 96,
-  68, 63, 57, 63, 74, 74, 76, 91, 98, 96, 81, 91, 81, 89, 89, 96,
-  91, 86, 91, 101, 98, 94, 98, 101, 103, 108, 103, 98, 94, 103, 221, 218,
-  192, 137, 103, 81, 98, 96, 84, 98, 94, 81, 74, 110, 108, 112, 105, 125,
-  112, 110, 125, 114, 119, 125, 114, 105, 137, 127, 131, 153, 131, 125, 114, 89,
-  103, 137, 160, 179, 165, 179, 172, 158, 164, 176, 174, 174, 167, 165, 197, 185,
-  185, 187, 187, 179, 187, 198, 201, 185, 192, 192, 184, 200, 184, 201, 182, 192,
-  160, 176, 204, 198, 197, 198, 204, 207, 209, 206, 197, 198, 206, 206, 207, 197,
-  210, 210, 210, 206, 198, 215, 203, 189, 206, 206, 206, 212, 212, 215, 212, 216,
-  213, 215, 215, 218, 216, 221, 224, 212, 149, 123, 137, 147, 156, 151, 155, 155,
-  156, 153, 149, 149, 129, 114, 86, 52, 52, 123, 200, 225, 219, 206, 182, 195,
-  213, 222, 221, 219, 221, 218, 215, 210, 206, 212, 209, 216, 218, 224, 225, 231,
-  234, 155, 20, 26, 26, 26, 46, 43, 52, 35, 29, 26, 23, 23, 32, 20,
-  35, 41, 32, 29, 41, 23, 12, 43, 63, 133, 156, 156, 149, 149, 147, 160,
-  169, 165, 169, 164, 165, 164, 165, 165, 162, 167, 165, 164, 164, 156, 162, 162,
-  84, 96, 91, 89, 89, 94, 89, 86, 91, 89, 86, 86, 84, 98, 121, 125,
-  143, 156, 160, 171, 167, 167, 171, 172, 165, 171, 167, 156, 153, 139, 114, 98,
-  71, 63, 60, 57, 66, 81, 91, 81, 89, 96, 84, 101, 86, 84, 101, 108,
-  94, 89, 91, 96, 103, 101, 108, 98, 108, 101, 108, 94, 91, 117, 222, 201,
-  158, 117, 89, 76, 86, 89, 94, 98, 86, 98, 105, 121, 105, 114, 108, 110,
-  119, 119, 96, 105, 117, 123, 112, 129, 133, 129, 121, 125, 129, 117, 76, 110,
-  160, 169, 147, 162, 189, 162, 145, 160, 162, 187, 181, 147, 171, 181, 177, 200,
-  182, 179, 190, 197, 195, 187, 185, 200, 190, 190, 192, 177, 200, 182, 189, 171,
-  184, 204, 197, 198, 189, 192, 203, 203, 204, 206, 207, 204, 201, 204, 204, 207,
-  197, 212, 213, 207, 190, 158, 182, 207, 212, 210, 204, 213, 209, 210, 209, 207,
-  210, 213, 212, 209, 213, 221, 221, 222, 224, 165, 129, 145, 145, 149, 153, 155,
-  156, 149, 149, 139, 131, 105, 81, 89, 179, 218, 219, 212, 185, 185, 201, 216,
-  221, 221, 216, 215, 218, 212, 213, 209, 209, 212, 212, 219, 221, 224, 227, 230,
-  231, 131, 41, 32, 38, 35, 35, 38, 43, 29, 41, 35, 26, 29, 20, 23,
-  35, 52, 41, 55, 18, 12, 18, 52, 108, 147, 158, 153, 151, 147, 151, 162,
-  164, 169, 169, 162, 164, 162, 164, 165, 162, 164, 162, 167, 165, 160, 164, 160,
-  91, 89, 91, 91, 91, 91, 96, 91, 86, 89, 84, 86, 86, 94, 114, 133,
-  149, 155, 164, 167, 171, 169, 174, 169, 169, 174, 167, 156, 145, 143, 114, 101,
-  74, 66, 66, 71, 86, 74, 86, 89, 91, 91, 94, 94, 86, 94, 89, 96,
-  89, 86, 91, 94, 94, 96, 98, 101, 103, 114, 112, 94, 91, 147, 216, 212,
-  145, 110, 105, 91, 81, 81, 98, 86, 105, 98, 105, 103, 105, 108, 81, 121,
-  110, 86, 125, 123, 110, 123, 123, 110, 133, 117, 108, 129, 121, 98, 110, 141,
-  155, 169, 176, 151, 145, 162, 143, 156, 190, 155, 153, 185, 192, 179, 174, 174,
-  192, 189, 189, 198, 185, 177, 182, 182, 201, 187, 185, 189, 181, 171, 174, 192,
-  189, 184, 198, 200, 198, 189, 198, 198, 200, 206, 206, 198, 207, 210, 206, 206,
-  210, 207, 209, 204, 158, 179, 204, 203, 207, 209, 210, 215, 209, 210, 212, 212,
-  209, 209, 203, 207, 212, 212, 216, 218, 222, 215, 153, 145, 153, 156, 149, 151,
-  149, 153, 139, 131, 125, 105, 155, 209, 228, 215, 201, 200, 189, 209, 218, 219,
-  219, 216, 215, 210, 215, 210, 210, 209, 213, 210, 213, 218, 222, 225, 225, 228,
-  230, 86, 41, 18, 29, 35, 29, 23, 55, 43, 41, 35, 32, 29, 41, 35,
-  32, 41, 29, 35, 18, 12, 26, 89, 135, 160, 160, 155, 147, 151, 158, 162,
-  167, 169, 167, 165, 164, 172, 160, 164, 165, 162, 162, 158, 164, 164, 164, 164,
-  94, 91, 96, 91, 89, 84, 91, 89, 91, 84, 89, 81, 89, 103, 119, 137,
-  141, 151, 164, 167, 169, 169, 174, 172, 172, 169, 165, 160, 153, 141, 117, 105,
-  74, 55, 63, 60, 74, 74, 84, 81, 96, 91, 86, 91, 91, 89, 91, 89,
-  94, 84, 76, 86, 98, 94, 103, 101, 105, 110, 98, 94, 74, 190, 221, 192,
-  143, 110, 117, 94, 81, 94, 81, 101, 91, 117, 86, 105, 103, 89, 114, 112,
-  110, 119, 114, 112, 121, 131, 125, 133, 108, 114, 119, 110, 96, 112, 145, 167,
-  162, 160, 169, 151, 139, 141, 171, 165, 127, 160, 176, 177, 185, 182, 182, 181,
-  184, 197, 185, 174, 190, 182, 176, 193, 182, 200, 190, 179, 153, 165, 200, 197,
-  192, 184, 185, 201, 198, 190, 193, 203, 200, 193, 203, 197, 200, 210, 207, 206,
-  209, 210, 190, 155, 190, 204, 198, 200, 206, 210, 207, 210, 209, 213, 210, 210,
-  207, 207, 206, 201, 207, 210, 212, 215, 215, 218, 198, 139, 156, 153, 147, 143,
-  153, 153, 141, 129, 160, 203, 224, 218, 207, 197, 203, 197, 209, 221, 218, 218,
-  216, 215, 209, 213, 210, 209, 209, 212, 207, 213, 219, 221, 222, 222, 225, 230,
-  231, 35, 38, 35, 41, 38, 32, 26, 41, 46, 35, 26, 26, 26, 23, 41,
-  29, 38, 49, 35, 9, 18, 43, 114, 156, 162, 153, 156, 145, 155, 167, 167,
-  165, 167, 169, 160, 165, 162, 162, 162, 164, 162, 156, 164, 160, 162, 160, 155,
-  89, 101, 96, 96, 96, 86, 89, 91, 96, 89, 89, 86, 89, 98, 117, 135,
-  149, 149, 153, 171, 169, 169, 174, 177, 172, 171, 169, 162, 155, 137, 119, 108,
-  76, 66, 63, 60, 76, 76, 79, 84, 81, 96, 94, 94, 94, 96, 86, 96,
-  101, 81, 86, 96, 86, 94, 103, 98, 110, 101, 96, 89, 81, 198, 215, 182,
-  135, 127, 112, 105, 101, 79, 101, 94, 94, 86, 96, 79, 94, 114, 117, 117,
-  110, 98, 123, 121, 125, 119, 110, 103, 123, 110, 108, 98, 112, 135, 160, 156,
-  171, 143, 143, 151, 151, 160, 147, 135, 155, 158, 179, 177, 172, 185, 189, 187,
-  172, 174, 181, 179, 167, 200, 195, 179, 193, 174, 187, 167, 187, 189, 181, 197,
-  189, 192, 192, 187, 184, 203, 197, 184, 190, 200, 197, 198, 198, 210, 209, 212,
-  206, 187, 172, 187, 197, 197, 204, 209, 209, 207, 206, 207, 204, 209, 204, 207,
-  209, 209, 209, 207, 201, 201, 206, 206, 215, 212, 215, 143, 151, 155, 149, 151,
-  149, 141, 151, 203, 219, 221, 212, 195, 207, 179, 203, 213, 221, 218, 215, 215,
-  212, 209, 210, 209, 209, 210, 212, 212, 215, 218, 219, 222, 224, 225, 227, 225,
-  222, 35, 35, 29, 41, 32, 35, 26, 32, 32, 46, 35, 26, 29, 15, 32,
-  41, 32, 32, 29, 23, 38, 94, 143, 153, 162, 155, 145, 153, 158, 160, 169,
-  164, 167, 165, 164, 162, 160, 160, 165, 162, 167, 160, 162, 164, 165, 158, 158,
-  86, 96, 84, 86, 89, 96, 96, 98, 96, 81, 86, 79, 98, 98, 119, 131,
-  147, 153, 158, 167, 169, 176, 172, 176, 174, 176, 172, 164, 153, 139, 123, 101,
-  86, 55, 60, 57, 76, 81, 79, 84, 94, 101, 91, 96, 89, 86, 94, 94,
-  86, 86, 89, 91, 86, 96, 103, 101, 96, 98, 105, 86, 91, 222, 215, 158,
-  149, 121, 123, 98, 98, 103, 94, 96, 81, 94, 84, 98, 89, 91, 110, 94,
-  94, 123, 110, 114, 117, 105, 101, 129, 108, 110, 110, 123, 151, 143, 149, 160,
-  160, 141, 143, 147, 179, 139, 127, 162, 172, 169, 153, 176, 179, 187, 192, 174,
-  177, 171, 164, 162, 193, 187, 201, 197, 174, 158, 164, 192, 184, 187, 185, 172,
-  200, 193, 185, 185, 182, 181, 187, 197, 179, 187, 201, 207, 204, 195, 207, 201,
-  172, 185, 201, 206, 198, 201, 192, 198, 200, 203, 204, 206, 204, 204, 204, 200,
-  200, 206, 206, 207, 203, 201, 206, 201, 204, 209, 219, 164, 151, 151, 149, 147,
-  139, 181, 209, 225, 209, 198, 193, 203, 187, 209, 219, 218, 216, 215, 212, 210,
-  209, 209, 210, 212, 212, 213, 210, 213, 213, 216, 221, 218, 222, 225, 227, 228,
-  212, 35, 38, 43, 43, 43, 41, 38, 46, 29, 23, 41, 20, 18, 23, 35,
-  35, 35, 32, 35, 35, 74, 127, 147, 162, 153, 153, 147, 153, 160, 169, 167,
-  167, 169, 164, 164, 164, 167, 158, 162, 162, 162, 164, 162, 162, 158, 160, 155,
-  91, 94, 98, 89, 86, 91, 98, 89, 94, 86, 91, 76, 94, 98, 127, 133,
-  149, 155, 164, 164, 171, 171, 174, 174, 172, 177, 174, 164, 155, 139, 127, 96,
-  74, 68, 66, 63, 74, 76, 76, 79, 94, 81, 89, 91, 98, 94, 96, 94,
-  79, 96, 94, 91, 94, 98, 96, 98, 98, 96, 101, 81, 96, 225, 209, 179,
-  135, 135, 121, 98, 101, 98, 103, 96, 103, 91, 96, 91, 98, 117, 101, 110,
-  117, 110, 123, 114, 101, 112, 114, 123, 117, 103, 123, 164, 147, 153, 147, 149,
-  143, 145, 156, 153, 135, 129, 153, 164, 165, 169, 164, 177, 185, 177, 177, 177,
-  174, 171, 181, 189, 167, 198, 179, 187, 155, 164, 187, 182, 181, 184, 176, 185,
-  177, 189, 192, 172, 190, 187, 176, 192, 195, 189, 200, 190, 190, 160, 172, 179,
-  189, 200, 203, 197, 187, 192, 189, 201, 203, 200, 201, 206, 206, 200, 193, 203,
-  198, 195, 200, 203, 201, 193, 197, 198, 193, 206, 210, 197, 141, 156, 153, 172,
-  207, 215, 212, 200, 203, 210, 189, 207, 212, 219, 215, 213, 213, 206, 207, 212,
-  210, 207, 209, 212, 212, 210, 209, 215, 213, 212, 215, 221, 227, 227, 225, 230,
-  171, 46, 35, 41, 41, 41, 46, 23, 41, 32, 20, 20, 20, 41, 23, 35,
-  29, 41, 46, 55, 60, 101, 149, 153, 151, 149, 145, 149, 165, 169, 167, 162,
-  169, 169, 169, 167, 164, 164, 160, 165, 167, 162, 160, 153, 160, 158, 158, 158,
-  91, 98, 89, 86, 98, 96, 86, 86, 96, 89, 91, 81, 89, 103, 117, 135,
-  145, 160, 167, 169, 174, 169, 179, 177, 174, 181, 174, 169, 153, 139, 123, 94,
-  81, 68, 66, 68, 84, 98, 76, 86, 86, 91, 91, 84, 89, 94, 89, 96,
-  81, 94, 96, 91, 98, 98, 91, 94, 105, 98, 86, 81, 129, 222, 204, 160,
-  174, 127, 129, 98, 84, 101, 86, 98, 94, 103, 91, 101, 94, 96, 103, 103,
-  103, 117, 103, 98, 121, 119, 125, 119, 98, 123, 151, 147, 153, 160, 149, 137,
-  135, 153, 158, 129, 137, 162, 169, 158, 153, 172, 177, 160, 149, 172, 172, 174,
-  185, 174, 172, 190, 179, 156, 181, 153, 181, 184, 179, 190, 182, 190, 185, 182,
-  182, 182, 177, 192, 177, 197, 189, 181, 201, 190, 197, 190, 165, 190, 193, 192,
-  197, 192, 179, 179, 201, 200, 206, 197, 206, 204, 201, 203, 203, 197, 190, 193,
-  201, 200, 195, 198, 198, 195, 192, 201, 195, 198, 200, 210, 172, 149, 192, 221,
-  216, 200, 184, 209, 195, 201, 212, 215, 216, 215, 212, 213, 209, 207, 209, 212,
-  207, 210, 213, 213, 212, 210, 212, 209, 207, 213, 218, 218, 224, 228, 227, 231,
-  137, 23, 35, 38, 43, 60, 38, 43, 46, 35, 38, 26, 29, 35, 26, 23,
-  26, 29, 52, 57, 81, 131, 151, 156, 156, 143, 149, 155, 164, 167, 167, 162,
-  164, 164, 165, 164, 164, 158, 162, 164, 162, 160, 160, 162, 162, 160, 160, 160,
-  89, 89, 94, 91, 101, 91, 81, 89, 86, 86, 96, 86, 91, 101, 123, 137,
-  145, 155, 164, 167, 174, 176, 177, 179, 177, 176, 174, 165, 156, 143, 119, 101,
-  79, 66, 52, 60, 71, 66, 76, 81, 81, 89, 86, 94, 94, 91, 84, 86,
-  86, 84, 94, 89, 98, 98, 96, 98, 96, 91, 89, 71, 172, 225, 204, 190,
-  147, 137, 121, 108, 108, 89, 105, 110, 101, 86, 101, 94, 101, 108, 110, 108,
-  117, 108, 98, 119, 127, 121, 114, 98, 114, 155, 139, 149, 149, 153, 145, 133,
-  141, 158, 121, 125, 151, 149, 143, 167, 171, 174, 167, 174, 164, 165, 160, 182,
-  192, 187, 174, 164, 181, 162, 164, 181, 182, 185, 181, 174, 182, 192, 185, 179,
-  182, 184, 179, 176, 192, 179, 198, 201, 200, 201, 184, 182, 189, 181, 185, 192,
-  201, 201, 203, 189, 198, 201, 201, 204, 192, 203, 198, 190, 198, 195, 189, 195,
-  197, 197, 195, 197, 198, 195, 187, 201, 193, 197, 195, 203, 198, 207, 215, 209,
-  197, 200, 204, 198, 206, 215, 216, 210, 212, 213, 210, 210, 212, 212, 206, 207,
-  207, 212, 212, 213, 209, 212, 207, 203, 206, 218, 218, 216, 227, 227, 230, 230,
-  68, 20, 26, 20, 26, 23, 35, 76, 55, 29, 38, 18, 41, 26, 26, 43,
-  43, 52, 71, 84, 123, 145, 155, 149, 149, 145, 156, 165, 165, 169, 169, 169,
-  165, 162, 165, 164, 160, 164, 160, 164, 162, 158, 164, 162, 156, 158, 162, 164,
-  89, 94, 86, 94, 98, 79, 98, 94, 98, 84, 86, 94, 94, 112, 123, 131,
-  145, 160, 171, 174, 174, 177, 179, 177, 176, 179, 174, 167, 156, 141, 112, 112,
-  71, 63, 68, 68, 71, 79, 76, 86, 81, 79, 84, 101, 94, 89, 86, 84,
-  89, 86, 91, 89, 86, 86, 98, 94, 91, 89, 84, 74, 203, 218, 207, 169,
-  156, 141, 137, 119, 101, 112, 101, 89, 84, 98, 98, 96, 98, 103, 114, 112,
-  110, 133, 121, 119, 133, 114, 96, 105, 151, 156, 149, 143, 143, 141, 139, 162,
-  141, 119, 131, 155, 145, 151, 153, 155, 179, 151, 153, 158, 164, 169, 182, 169,
-  189, 193, 193, 167, 156, 162, 177, 200, 185, 171, 177, 182, 174, 177, 195, 174,
-  181, 179, 179, 179, 177, 190, 185, 200, 190, 184, 189, 193, 193, 187, 197, 189,
-  184, 197, 193, 201, 193, 198, 200, 197, 203, 193, 200, 189, 177, 184, 193, 193,
-  197, 182, 198, 187, 195, 190, 181, 177, 195, 185, 193, 201, 207, 209, 203, 203,
-  203, 201, 207, 212, 219, 215, 212, 209, 209, 210, 209, 209, 209, 206, 207, 210,
-  212, 213, 210, 212, 212, 212, 198, 200, 209, 213, 216, 218, 224, 227, 228, 222,
-  20, 12, 23, 20, 43, 26, 23, 32, 32, 32, 18, 23, 29, 29, 49, 35,
-  32, 38, 60, 101, 137, 155, 155, 153, 149, 151, 156, 164, 167, 167, 167, 164,
-  167, 162, 160, 167, 162, 164, 162, 164, 162, 164, 162, 162, 158, 158, 160, 162,
-  98, 98, 84, 84, 84, 86, 89, 89, 86, 86, 89, 86, 101, 108, 117, 133,
-  145, 156, 164, 172, 176, 177, 179, 174, 176, 179, 172, 169, 155, 135, 121, 105,
-  79, 55, 60, 60, 76, 79, 79, 89, 81, 91, 81, 91, 84, 89, 86, 91,
-  89, 81, 98, 91, 86, 91, 103, 94, 89, 103, 79, 79, 218, 219, 193, 201,
-  141, 147, 125, 127, 117, 125, 108, 108, 101, 94, 101, 96, 103, 123, 94, 98,
-  114, 108, 117, 123, 117, 108, 103, 141, 149, 149, 155, 141, 133, 143, 160, 137,
-  135, 133, 158, 145, 151, 143, 155, 158, 131, 167, 149, 158, 172, 177, 182, 190,
-  172, 165, 179, 153, 171, 185, 171, 185, 182, 172, 176, 184, 189, 172, 171, 187,
-  179, 177, 184, 176, 177, 174, 193, 181, 181, 193, 197, 189, 181, 187, 195, 176,
-  190, 193, 192, 203, 201, 197, 195, 201, 195, 189, 184, 189, 185, 176, 187, 193,
-  197, 197, 181, 189, 189, 181, 172, 172, 182, 203, 216, 204, 192, 172, 195, 204,
-  203, 207, 216, 218, 215, 215, 209, 200, 209, 209, 207, 210, 207, 206, 204, 212,
-  209, 213, 210, 213, 215, 195, 184, 193, 207, 213, 216, 216, 219, 225, 225, 195,
-  26, 9, 23, 29, 20, 26, 23, 32, 35, 29, 20, 26, 23, 46, 38, 23,
-  18, 43, 89, 129, 149, 153, 153, 145, 143, 153, 164, 164, 167, 165, 164, 167,
-  167, 167, 169, 164, 160, 165, 164, 164, 164, 158, 165, 164, 160, 164, 162, 160,
-  84, 86, 84, 89, 86, 89, 89, 96, 86, 86, 86, 86, 89, 108, 112, 133,
-  145, 156, 164, 171, 177, 176, 176, 176, 176, 177, 172, 167, 149, 143, 125, 108,
-  81, 63, 57, 68, 74, 84, 89, 86, 84, 89, 89, 91, 91, 91, 84, 84,
-  84, 91, 86, 86, 98, 98, 94, 98, 96, 91, 79, 76, 218, 213, 200, 158,
-  162, 147, 133, 129, 105, 133, 114, 110, 91, 101, 91, 105, 103, 89, 96, 108,
-  131, 110, 125, 105, 101, 110, 149, 127, 145, 155, 141, 141, 133, 162, 133, 105,
-  137, 149, 153, 151, 153, 165, 164, 133, 145, 137, 167, 158, 167, 189, 176, 177,
-  179, 147, 151, 185, 184, 184, 185, 162, 164, 182, 174, 182, 182, 189, 177, 174,
-  189, 181, 182, 177, 176, 179, 174, 181, 187, 185, 189, 195, 185, 189, 192, 197,
-  184, 195, 192, 200, 201, 198, 193, 187, 189, 192, 195, 185, 172, 189, 172, 195,
-  190, 190, 171, 190, 164, 177, 167, 198, 210, 209, 197, 167, 200, 197, 207, 209,
-  212, 216, 215, 213, 213, 206, 203, 207, 209, 210, 206, 210, 206, 207, 209, 212,
-  212, 212, 213, 215, 200, 176, 174, 189, 201, 212, 212, 210, 219, 224, 225, 114,
-  29, 20, 20, 23, 20, 26, 29, 35, 74, 26, 23, 29, 43, 32, 35, 20,
-  15, 52, 117, 141, 156, 156, 149, 147, 156, 160, 169, 165, 165, 167, 165, 167,
-  165, 169, 169, 164, 158, 164, 162, 160, 164, 165, 160, 164, 162, 164, 164, 167,
-  84, 89, 98, 86, 76, 81, 86, 79, 94, 98, 81, 84, 91, 105, 114, 139,
-  143, 155, 164, 171, 174, 172, 179, 177, 172, 176, 174, 165, 155, 141, 119, 110,
-  84, 57, 66, 71, 76, 74, 86, 81, 84, 91, 91, 94, 91, 84, 91, 86,
-  86, 91, 79, 89, 91, 94, 96, 101, 94, 91, 84, 81, 230, 216, 182, 190,
-  156, 165, 125, 143, 117, 125, 125, 94, 110, 89, 98, 101, 91, 112, 98, 110,
-  129, 108, 84, 89, 117, 151, 133, 141, 147, 137, 143, 133, 160, 121, 110, 129,
-  151, 149, 147, 156, 151, 162, 149, 131, 143, 143, 149, 167, 160, 164, 182, 162,
-  153, 151, 172, 181, 192, 181, 179, 171, 169, 169, 185, 182, 177, 179, 187, 177,
-  172, 156, 181, 185, 176, 162, 179, 181, 179, 192, 174, 179, 184, 184, 193, 197,
-  195, 177, 197, 200, 198, 197, 187, 182, 179, 187, 184, 190, 192, 169, 193, 169,
-  189, 187, 179, 174, 160, 189, 209, 216, 200, 181, 200, 195, 203, 204, 210, 213,
-  215, 212, 210, 213, 206, 206, 204, 207, 206, 207, 209, 207, 207, 212, 210, 212,
-  212, 213, 210, 210, 182, 164, 172, 174, 195, 212, 200, 204, 218, 218, 219, 23,
-  35, 26, 23, 29, 32, 35, 23, 41, 29, 38, 26, 35, 32, 32, 41, 32,
-  23, 71, 131, 151, 153, 151, 147, 151, 162, 167, 165, 165, 167, 167, 165, 160,
-  164, 169, 160, 162, 162, 164, 164, 165, 162, 167, 160, 171, 165, 164, 162, 162,
-  91, 86, 89, 86, 89, 89, 86, 86, 84, 94, 81, 91, 101, 98, 123, 135,
-  147, 158, 167, 176, 176, 174, 177, 176, 177, 176, 177, 165, 156, 139, 125, 103,
-  68, 63, 60, 66, 81, 89, 86, 91, 89, 86, 98, 94, 96, 86, 89, 94,
-  89, 81, 91, 94, 89, 86, 86, 96, 98, 89, 76, 74, 222, 210, 201, 167,
-  177, 145, 177, 127, 160, 125, 114, 101, 110, 105, 84, 68, 105, 94, 103, 123,
-  112, 96, 94, 110, 143, 147, 135, 133, 141, 143, 141, 160, 110, 117, 125, 143,
-  151, 153, 151, 158, 153, 151, 139, 143, 155, 177, 145, 135, 176, 158, 153, 145,
-  167, 182, 181, 177, 169, 172, 179, 176, 169, 169, 162, 174, 189, 176, 164, 172,
-  172, 171, 167, 171, 179, 182, 176, 169, 172, 162, 181, 176, 181, 187, 184, 195,
-  195, 187, 181, 190, 192, 185, 185, 184, 177, 190, 190, 195, 192, 184, 185, 165,
-  187, 174, 167, 172, 203, 216, 200, 193, 197, 204, 206, 203, 210, 215, 210, 209,
-  207, 204, 203, 204, 206, 206, 206, 210, 207, 207, 206, 212, 209, 207, 212, 210,
-  215, 209, 215, 189, 174, 167, 160, 172, 198, 164, 177, 200, 210, 219, 177, 23,
-  23, 57, 46, 43, 23, 32, 41, 52, 29, 20, 23, 26, 23, 32, 43, 66,
-  57, 117, 147, 155, 155, 151, 149, 155, 167, 171, 169, 167, 169, 164, 165, 165,
-  167, 172, 167, 160, 172, 160, 167, 164, 164, 162, 167, 169, 164, 162, 162, 165,
-  84, 89, 81, 94, 86, 84, 86, 84, 86, 81, 81, 94, 94, 94, 123, 131,
-  151, 158, 172, 174, 172, 172, 177, 176, 171, 176, 169, 164, 155, 141, 131, 98,
-  81, 76, 63, 71, 81, 91, 81, 84, 89, 89, 89, 86, 91, 81, 89, 91,
-  94, 86, 86, 98, 89, 89, 94, 89, 96, 91, 86, 84, 227, 210, 174, 189,
-  141, 164, 131, 139, 137, 133, 121, 119, 114, 94, 76, 96, 79, 91, 123, 110,
-  110, 84, 119, 139, 147, 139, 141, 123, 133, 129, 164, 112, 108, 127, 143, 153,
-  145, 158, 155, 147, 151, 137, 164, 162, 153, 145, 143, 137, 153, 172, 139, 164,
-  172, 174, 185, 177, 164, 169, 167, 177, 172, 177, 177, 164, 172, 182, 164, 167,
-  174, 174, 171, 177, 165, 179, 177, 151, 167, 177, 182, 179, 177, 184, 185, 182,
-  193, 193, 192, 184, 187, 187, 182, 182, 179, 171, 184, 193, 182, 182, 155, 169,
-  167, 169, 195, 207, 201, 190, 192, 201, 201, 204, 210, 218, 213, 209, 206, 207,
-  201, 195, 203, 204, 204, 201, 209, 207, 206, 207, 207, 209, 209, 210, 212, 215,
-  215, 210, 207, 174, 155, 162, 177, 198, 149, 141, 172, 195, 204, 222, 49, 41,
-  12, 55, 68, 38, 35, 41, 29, 32, 38, 18, 32, 23, 35, 38, 52, 71,
-  103, 137, 149, 151, 151, 147, 151, 165, 164, 162, 167, 165, 167, 156, 164, 165,
-  164, 164, 165, 167, 165, 164, 165, 160, 164, 167, 171, 169, 162, 164, 164, 162,
-  89, 81, 91, 91, 86, 86, 81, 91, 91, 84, 91, 86, 86, 103, 123, 141,
-  155, 162, 165, 172, 177, 171, 171, 176, 176, 172, 171, 164, 153, 141, 121, 103,
-  76, 55, 66, 57, 79, 86, 79, 91, 84, 108, 96, 89, 84, 84, 89, 86,
-  84, 79, 89, 91, 89, 84, 89, 98, 89, 94, 74, 89, 228, 192, 195, 156,
-  181, 137, 189, 131, 153, 125, 141, 121, 101, 96, 101, 81, 86, 110, 96, 105,
-  76, 117, 145, 143, 131, 137, 127, 137, 129, 158, 103, 117, 119, 133, 135, 149,
-  156, 147, 147, 135, 149, 155, 160, 167, 139, 167, 167, 156, 141, 135, 179, 151,
-  165, 174, 164, 169, 174, 171, 171, 176, 176, 167, 181, 169, 155, 158, 190, 171,
-  165, 172, 176, 177, 164, 156, 169, 172, 172, 171, 177, 187, 174, 182, 172, 172,
-  185, 193, 187, 182, 169, 177, 177, 184, 171, 181, 165, 189, 181, 174, 162, 160,
-  181, 203, 209, 190, 185, 197, 187, 204, 207, 212, 213, 210, 209, 206, 198, 198,
-  201, 200, 198, 203, 206, 206, 209, 209, 209, 209, 209, 213, 207, 213, 215, 212,
-  213, 216, 172, 165, 160, 177, 195, 160, 127, 155, 181, 195, 213, 212, 18, 20,
-  18, 18, 41, 32, 66, 41, 23, 15, 38, 35, 38, 26, 35, 41, 63, 84,
-  127, 143, 156, 147, 149, 153, 153, 162, 165, 165, 165, 169, 167, 167, 167, 162,
-  162, 164, 167, 165, 165, 162, 160, 160, 165, 164, 167, 162, 164, 164, 164, 162,
-  79, 94, 86, 84, 89, 86, 91, 86, 86, 84, 86, 79, 89, 108, 123, 141,
-  145, 160, 167, 171, 174, 176, 174, 172, 176, 176, 174, 167, 156, 145, 123, 101,
-  84, 52, 66, 57, 71, 84, 86, 96, 86, 89, 91, 89, 94, 84, 84, 89,
-  84, 91, 81, 91, 94, 86, 98, 86, 91, 84, 79, 89, 231, 206, 164, 192,
-  145, 167, 135, 155, 139, 141, 123, 133, 94, 98, 89, 101, 103, 96, 101, 79,
-  105, 145, 141, 135, 139, 119, 141, 139, 156, 101, 114, 112, 141, 153, 141, 145,
-  147, 153, 131, 156, 139, 137, 143, 151, 155, 156, 162, 143, 137, 145, 177, 174,
-  164, 149, 155, 153, 171, 182, 171, 165, 174, 162, 160, 172, 162, 167, 160, 176,
-  177, 164, 156, 143, 179, 167, 171, 174, 172, 172, 177, 169, 184, 176, 165, 181,
-  177, 181, 182, 181, 181, 174, 172, 182, 172, 171, 171, 181, 176, 164, 179, 200,
-  212, 184, 169, 195, 192, 204, 206, 216, 215, 213, 212, 209, 203, 203, 201, 204,
-  203, 201, 201, 206, 206, 207, 210, 210, 209, 207, 210, 209, 209, 212, 215, 215,
-  213, 203, 160, 171, 176, 189, 156, 139, 149, 174, 185, 190, 222, 171, 15, 20,
-  18, 20, 35, 41, 32, 32, 26, 26, 35, 26, 35, 23, 29, 60, 63, 105,
-  143, 158, 153, 151, 147, 151, 164, 165, 164, 171, 162, 165, 172, 164, 165, 162,
-  169, 165, 165, 164, 167, 167, 164, 167, 164, 160, 164, 167, 158, 160, 165, 162,
-  91, 86, 94, 81, 81, 89, 89, 84, 86, 84, 91, 86, 86, 110, 125, 135,
-  151, 158, 167, 172, 179, 174, 174, 174, 172, 176, 176, 164, 155, 141, 133, 101,
-  84, 66, 63, 74, 71, 89, 81, 96, 89, 89, 89, 89, 84, 84, 94, 84,
-  89, 86, 96, 101, 89, 89, 101, 91, 84, 79, 79, 112, 224, 185, 195, 160,
-  187, 141, 176, 135, 143, 112, 141, 114, 112, 112, 103, 91, 94, 103, 79, 131,
-  141, 145, 141, 131, 133, 123, 121, 164, 86, 131, 117, 143, 141, 141, 147, 139,
-  133, 139, 139, 141, 151, 133, 153, 151, 160, 149, 139, 139, 160, 176, 156, 155,
-  164, 162, 155, 164, 171, 160, 171, 162, 158, 160, 165, 171, 169, 176, 177, 162,
-  171, 131, 158, 181, 164, 179, 171, 179, 169, 158, 179, 176, 182, 176, 167, 162,
-  181, 164, 167, 172, 182, 179, 171, 176, 181, 162, 172, 153, 156, 184, 206, 200,
-  172, 193, 193, 200, 206, 212, 210, 209, 209, 206, 203, 201, 200, 201, 203, 203,
-  203, 204, 203, 207, 209, 213, 209, 210, 209, 210, 209, 212, 213, 213, 218, 218,
-  218, 164, 158, 174, 190, 162, 139, 158, 174, 174, 179, 206, 228, 52, 20, 18,
-  20, 20, 32, 29, 38, 71, 18, 26, 26, 38, 32, 20, 35, 63, 94, 131,
-  153, 155, 151, 145, 147, 153, 160, 167, 169, 165, 174, 167, 158, 164, 162, 158,
-  162, 167, 164, 162, 164, 167, 162, 162, 167, 164, 167, 162, 160, 158, 160, 160,
-  89, 84, 101, 79, 79, 84, 91, 94, 91, 89, 79, 91, 96, 103, 121, 133,
-  149, 162, 167, 172, 169, 176, 174, 172, 174, 172, 172, 162, 153, 149, 125, 103,
-  76, 71, 60, 66, 79, 81, 79, 94, 89, 91, 96, 89, 94, 86, 96, 86,
-  81, 89, 89, 89, 89, 84, 94, 96, 84, 79, 63, 119, 212, 209, 177, 203,
-  171, 179, 149, 165, 141, 135, 131, 162, 114, 127, 105, 94, 98, 86, 117, 127,
-  139, 141, 135, 133, 135, 145, 135, 101, 114, 117, 137, 153, 145, 139, 153, 143,
-  133, 145, 153, 131, 129, 147, 155, 158, 151, 135, 141, 151, 162, 156, 167, 155,
-  151, 158, 174, 155, 155, 164, 139, 147, 164, 165, 167, 177, 171, 174, 160, 137,
-  162, 169, 165, 167, 177, 156, 171, 177, 176, 167, 164, 169, 162, 177, 164, 176,
-  153, 179, 164, 169, 167, 177, 165, 167, 171, 156, 149, 184, 200, 210, 181, 181,
-  192, 192, 206, 201, 209, 206, 206, 204, 197, 189, 200, 200, 200, 203, 204, 207,
-  204, 201, 207, 209, 210, 210, 212, 212, 209, 212, 210, 212, 216, 215, 216, 216,
-  190, 158, 164, 187, 149, 153, 172, 179, 162, 147, 181, 222, 212, 32, 20, 23,
-  46, 41, 35, 38, 29, 32, 41, 32, 41, 43, 23, 35, 68, 60, 108, 145,
-  158, 158, 149, 147, 155, 164, 162, 167, 169, 165, 167, 167, 162, 160, 160, 160,
-  162, 160, 167, 162, 162, 164, 162, 158, 165, 165, 162, 162, 162, 164, 165, 165,
-  86, 91, 96, 91, 86, 84, 98, 86, 91, 96, 89, 89, 96, 108, 125, 137,
-  145, 158, 169, 177, 177, 177, 177, 177, 177, 177, 174, 165, 156, 145, 127, 112,
-  96, 63, 52, 57, 81, 79, 86, 89, 84, 96, 86, 81, 86, 79, 89, 86,
-  89, 89, 94, 89, 86, 89, 101, 94, 84, 79, 63, 167, 216, 195, 210, 177,
-  195, 177, 158, 171, 145, 149, 143, 151, 129, 112, 94, 96, 79, 123, 135, 139,
-  110, 135, 131, 119, 137, 147, 98, 119, 112, 141, 133, 137, 147, 156, 137, 137,
-  141, 129, 112, 131, 149, 155, 143, 165, 131, 147, 162, 164, 155, 158, 164, 158,
-  153, 143, 174, 171, 164, 171, 155, 147, 139, 129, 143, 135, 153, 147, 158, 165,
-  162, 177, 172, 171, 160, 169, 167, 165, 176, 176, 176, 158, 179, 160, 179, 167,
-  179, 158, 172, 172, 156, 169, 160, 155, 156, 165, 195, 209, 192, 176, 197, 179,
-  201, 209, 213, 209, 200, 200, 193, 192, 193, 195, 197, 203, 204, 206, 203, 206,
-  209, 207, 209, 210, 212, 210, 210, 210, 209, 213, 212, 213, 218, 218, 224, 213,
-  155, 162, 187, 151, 155, 177, 169, 119, 127, 164, 204, 230, 135, 18, 23, 26,
-  29, 43, 41, 35, 49, 29, 41, 68, 41, 52, 41, 26, 43, 81, 129, 153,
-  153, 149, 151, 147, 158, 165, 164, 162, 158, 165, 160, 162, 167, 164, 160, 162,
-  162, 160, 169, 164, 164, 162, 162, 164, 165, 164, 169, 162, 164, 162, 164, 160,
-  84, 86, 91, 91, 91, 96, 86, 86, 89, 91, 98, 101, 101, 114, 119, 135,
-  151, 162, 164, 174, 176, 177, 171, 177, 174, 172, 172, 164, 158, 151, 133, 98,
-  81, 57, 60, 63, 68, 84, 91, 91, 84, 89, 86, 86, 86, 81, 96, 94,
-  89, 86, 98, 89, 86, 84, 94, 84, 86, 66, 57, 145, 212, 213, 195, 200,
-  192, 171, 177, 151, 160, 141, 141, 149, 145, 114, 98, 74, 89, 133, 139, 137,
-  137, 117, 125, 131, 141, 96, 129, 114, 131, 151, 139, 133, 143, 135, 135, 145,
-  117, 129, 121, 135, 147, 153, 155, 121, 125, 151, 153, 176, 158, 162, 155, 145,
-  143, 156, 139, 155, 151, 158, 156, 131, 137, 151, 153, 112, 60, 147, 171, 158,
-  164, 164, 160, 162, 162, 162, 165, 171, 164, 171, 172, 167, 160, 164, 156, 172,
-  164, 169, 162, 172, 162, 141, 162, 151, 179, 203, 198, 185, 184, 182, 204, 204,
-  201, 212, 209, 197, 198, 198, 201, 200, 198, 198, 207, 204, 204, 207, 207, 209,
-  207, 207, 212, 212, 210, 209, 210, 212, 209, 213, 213, 216, 216, 218, 219, 181,
-  164, 181, 145, 167, 147, 108, 74, 108, 127, 184, 221, 227, 41, 26, 12, 29,
-  41, 43, 52, 26, 46, 38, 29, 71, 35, 32, 26, 38, 49, 103, 149, 162,
-  153, 149, 151, 153, 160, 165, 167, 164, 165, 165, 162, 162, 160, 160, 160, 160,
-  160, 164, 162, 160, 160, 164, 162, 162, 165, 162, 160, 167, 164, 156, 160, 160,
-  96, 84, 89, 84, 86, 89, 94, 81, 94, 89, 94, 101, 98, 105, 123, 135,
-  147, 160, 165, 172, 171, 177, 172, 176, 172, 177, 172, 167, 158, 143, 123, 105,
-  79, 63, 55, 71, 71, 74, 96, 98, 89, 81, 84, 84, 84, 81, 91, 91,
-  91, 86, 79, 84, 94, 89, 101, 84, 81, 68, 60, 164, 222, 201, 207, 195,
-  174, 185, 149, 177, 155, 174, 135, 167, 139, 125, 89, 89, 114, 129, 123, 123,
-  125, 121, 137, 143, 96, 119, 125, 127, 151, 143, 135, 141, 135, 139, 145, 105,
-  123, 137, 141, 131, 143, 160, 121, 139, 153, 143, 155, 153, 149, 108, 84, 105,
-  110, 101, 84, 86, 112, 129, 153, 108, 149, 137, 149, 153, 103, 112, 165, 167,
-  167, 167, 172, 162, 149, 137, 147, 158, 162, 169, 169, 167, 151, 149, 158, 89,
-  179, 164, 174, 141, 164, 145, 158, 189, 203, 193, 181, 184, 190, 203, 200, 210,
-  204, 206, 203, 197, 197, 200, 201, 198, 203, 203, 204, 207, 206, 209, 209, 206,
-  207, 212, 206, 213, 212, 213, 212, 212, 209, 213, 213, 216, 219, 218, 209, 164,
-  177, 155, 162, 105, 68, 79, 84, 129, 165, 210, 228, 200, 18, 12, 12, 29,
-  26, 23, 43, 29, 26, 26, 38, 46, 35, 43, 38, 46, 81, 133, 155, 160,
-  149, 149, 149, 155, 158, 169, 165, 165, 164, 160, 167, 158, 164, 162, 162, 164,
-  158, 162, 160, 158, 164, 162, 162, 164, 160, 165, 162, 164, 164, 158, 162, 158,
-  89, 96, 84, 91, 84, 91, 91, 94, 86, 94, 91, 94, 94, 108, 121, 135,
-  149, 162, 167, 171, 169, 177, 176, 174, 177, 177, 169, 172, 156, 149, 129, 105,
-  81, 71, 49, 55, 79, 76, 79, 91, 86, 84, 89, 86, 86, 86, 86, 96,
-  84, 86, 81, 89, 94, 91, 84, 89, 86, 76, 63, 153, 216, 216, 201, 204,
-  197, 151, 176, 153, 165, 125, 177, 133, 164, 127, 117, 125, 112, 127, 119, 119,
-  117, 133, 133, 127, 96, 121, 125, 145, 135, 143, 137, 131, 141, 133, 114, 125,
-  121, 133, 139, 158, 133, 117, 135, 151, 164, 151, 147, 135, 86, 91, 160, 133,
-  141, 114, 117, 108, 98, 71, 108, 79, 145, 174, 172, 167, 149, 117, 98, 91,
-  112, 137, 137, 165, 160, 162, 158, 158, 105, 158, 147, 156, 167, 127, 137, 84,
-  41, 133, 156, 153, 139, 167, 195, 207, 171, 185, 171, 204, 210, 210, 212, 204,
-  201, 206, 203, 204, 198, 201, 206, 200, 206, 204, 206, 212, 207, 207, 209, 210,
-  207, 210, 209, 212, 210, 210, 213, 212, 210, 215, 215, 219, 219, 218, 171, 167,
-  164, 121, 68, 84, 84, 94, 110, 162, 201, 222, 228, 89, 18, 20, 15, 29,
-  41, 23, 32, 23, 26, 38, 29, 38, 32, 35, 43, 55, 103, 145, 158, 156,
-  149, 147, 155, 165, 165, 169, 164, 167, 164, 167, 164, 165, 164, 167, 165, 158,
-  164, 165, 165, 164, 164, 164, 162, 162, 162, 162, 160, 160, 160, 156, 165, 160,
-  94, 91, 86, 89, 89, 89, 84, 94, 94, 79, 89, 86, 94, 108, 127, 137,
-  149, 158, 167, 177, 176, 179, 179, 176, 177, 172, 171, 167, 156, 139, 123, 105,
-  79, 57, 66, 63, 71, 76, 79, 86, 86, 98, 86, 86, 96, 86, 91, 94,
-  86, 91, 84, 89, 86, 89, 89, 94, 71, 68, 57, 141, 225, 206, 209, 209,
-  187, 197, 162, 176, 119, 182, 131, 167, 135, 127, 110, 105, 129, 114, 103, 123,
-  121, 133, 112, 127, 114, 127, 147, 139, 135, 131, 135, 133, 121, 112, 127, 133,
-  133, 133, 141, 145, 131, 127, 151, 155, 145, 155, 145, 98, 121, 143, 141, 139,
-  129, 119, 117, 105, 110, 89, 68, 79, 160, 176, 171, 172, 158, 123, 137, 112,
-  133, 131, 105, 84, 123, 143, 153, 179, 145, 114, 105, 55, 105, 49, 114, 119,
-  32, 35, 172, 151, 167, 203, 189, 156, 171, 176, 198, 192, 204, 204, 209, 200,
-  201, 204, 203, 203, 206, 206, 200, 204, 204, 206, 207, 206, 209, 209, 209, 210,
-  209, 212, 213, 215, 210, 210, 210, 210, 212, 212, 216, 219, 212, 179, 158, 153,
-  79, 76, 81, 84, 89, 103, 137, 187, 218, 225, 189, 23, 23, 35, 20, 26,
-  29, 26, 38, 26, 20, 43, 41, 43, 41, 29, 43, 81, 125, 149, 155, 149,
-  143, 151, 156, 162, 172, 171, 167, 165, 167, 169, 169, 164, 160, 160, 165, 162,
-  162, 160, 162, 160, 162, 160, 158, 160, 160, 162, 160, 160, 160, 158, 160, 158,
-  89, 91, 98, 89, 86, 96, 79, 94, 105, 96, 96, 94, 105, 119, 131, 133,
-  155, 155, 169, 176, 181, 172, 177, 179, 177, 174, 174, 164, 162, 143, 127, 103,
-  74, 60, 55, 63, 68, 76, 89, 79, 84, 84, 91, 103, 96, 89, 81, 101,
-  86, 94, 86, 84, 91, 89, 94, 89, 76, 71, 60, 123, 219, 216, 207, 198,
-  210, 181, 189, 145, 172, 123, 156, 139, 167, 149, 101, 103, 96, 121, 108, 117,
-  133, 112, 98, 123, 127, 143, 135, 133, 137, 135, 139, 133, 112, 129, 127, 125,
-  139, 131, 127, 129, 125, 145, 137, 147, 156, 135, 114, 147, 149, 145, 135, 112,
-  101, 101, 98, 63, 49, 49, 55, 57, 162, 151, 169, 167, 135, 149, 127, 137,
-  129, 114, 98, 79, 89, 101, 63, 84, 76, 55, 60, 41, 26, 43, 23, 63,
-  20, 26, 127, 189, 203, 169, 164, 164, 192, 203, 209, 206, 204, 207, 201, 200,
-  204, 209, 204, 203, 203, 204, 204, 201, 206, 204, 209, 209, 206, 209, 207, 210,
-  206, 209, 213, 213, 210, 213, 213, 212, 213, 215, 218, 190, 165, 133, 94, 74,
-  74, 76, 86, 91, 94, 133, 185, 207, 219, 216, 35, 20, 15, 18, 35, 29,
-  41, 32, 23, 23, 18, 26, 41, 41, 29, 29, 74, 105, 145, 155, 147, 149,
-  147, 153, 160, 169, 169, 164, 171, 162, 169, 167, 162, 164, 162, 162, 162, 164,
-  162, 164, 160, 162, 160, 160, 162, 162, 164, 160, 165, 162, 164, 162, 160, 158,
-  94, 96, 91, 91, 94, 96, 89, 86, 91, 101, 98, 94, 91, 108, 125, 137,
-  155, 160, 171, 176, 176, 179, 177, 179, 176, 177, 171, 171, 158, 145, 127, 105,
-  81, 55, 46, 66, 74, 66, 89, 84, 94, 81, 91, 84, 89, 96, 84, 96,
-  84, 86, 86, 84, 86, 81, 84, 79, 81, 79, 66, 103, 224, 215, 193, 210,
-  181, 210, 171, 176, 121, 141, 112, 149, 153, 112, 103, 96, 110, 123, 112, 131,
-  108, 89, 119, 112, 143, 135, 135, 125, 133, 149, 114, 129, 125, 135, 127, 137,
-  129, 131, 127, 119, 137, 149, 139, 133, 139, 114, 123, 135, 155, 127, 98, 94,
-  101, 96, 84, 89, 108, 71, 81, 96, 137, 156, 147, 143, 147, 135, 68, 55,
-  60, 60, 43, 101, 139, 41, 63, 55, 41, 38, 43, 26, 32, 26, 35, 20,
-  18, 81, 185, 200, 153, 160, 177, 203, 203, 206, 209, 203, 210, 203, 203, 201,
-  206, 206, 204, 203, 203, 203, 203, 204, 203, 207, 207, 209, 209, 212, 207, 210,
-  207, 213, 216, 215, 213, 213, 213, 215, 212, 184, 141, 108, 91, 84, 81, 76,
-  79, 89, 89, 94, 137, 179, 197, 213, 225, 141, 32, 26, 26, 38, 29, 32,
-  35, 26, 18, 41, 35, 38, 43, 26, 23, 32, 68, 129, 151, 149, 149, 147,
-  151, 162, 165, 165, 167, 167, 167, 164, 165, 162, 167, 162, 167, 160, 164, 162,
-  164, 155, 160, 162, 162, 164, 165, 164, 164, 162, 160, 156, 165, 158, 160, 162,
-  89, 89, 94, 96, 91, 91, 94, 101, 84, 89, 101, 94, 94, 110, 121, 141,
-  151, 165, 167, 176, 174, 177, 177, 176, 174, 174, 176, 167, 158, 151, 125, 110,
-  79, 60, 46, 68, 71, 74, 81, 96, 84, 98, 96, 86, 84, 94, 84, 89,
-  84, 94, 91, 94, 89, 86, 103, 86, 86, 71, 71, 81, 228, 207, 212, 189,
-  216, 185, 204, 153, 153, 125, 133, 141, 131, 117, 112, 108, 103, 108, 133, 108,
-  101, 105, 110, 131, 131, 141, 131, 137, 135, 137, 114, 131, 125, 129, 129, 127,
-  141, 127, 117, 137, 141, 141, 137, 145, 103, 105, 141, 143, 127, 119, 105, 127,
-  135, 105, 117, 149, 123, 110, 63, 86, 110, 84, 123, 153, 86, 71, 108, 46,
-  41, 55, 127, 103, 46, 52, 66, 86, 26, 32, 18, 15, 23, 68, 23, 103,
-  117, 195, 187, 137, 155, 193, 207, 209, 210, 206, 204, 201, 204, 200, 201, 201,
-  203, 201, 203, 206, 200, 203, 203, 204, 201, 206, 207, 206, 210, 207, 209, 204,
-  206, 218, 212, 212, 216, 216, 210, 158, 112, 81, 81, 81, 89, 86, 86, 79,
-  76, 96, 110, 147, 185, 190, 204, 219, 193, 26, 35, 32, 18, 35, 38, 26,
-  38, 26, 35, 20, 29, 35, 26, 26, 18, 43, 89, 143, 151, 149, 149, 147,
-  153, 167, 176, 164, 165, 169, 164, 162, 164, 169, 167, 167, 160, 164, 167, 164,
-  167, 164, 160, 160, 158, 158, 162, 162, 162, 162, 164, 162, 160, 165, 160, 158,
-  89, 89, 94, 98, 103, 89, 89, 84, 89, 103, 96, 89, 91, 112, 121, 139,
-  147, 164, 169, 176, 172, 176, 181, 174, 176, 176, 176, 165, 158, 143, 133, 110,
-  84, 74, 57, 74, 71, 84, 81, 98, 86, 84, 91, 86, 86, 86, 98, 84,
-  89, 89, 89, 89, 98, 84, 86, 81, 89, 76, 66, 55, 203, 219, 204, 218,
-  190, 213, 184, 182, 121, 119, 98, 123, 133, 129, 108, 105, 108, 123, 123, 98,
-  105, 112, 135, 133, 129, 131, 129, 135, 139, 101, 119, 125, 131, 133, 135, 127,
-  121, 123, 135, 141, 131, 133, 141, 105, 108, 133, 131, 125, 125, 98, 125, 121,
-  101, 103, 133, 121, 98, 55, 71, 71, 74, 79, 121, 96, 114, 68, 60, 68,
-  84, 129, 55, 71, 96, 74, 79, 101, 43, 26, 18, 20, 12, 18, 35, 164,
-  203, 165, 149, 158, 192, 207, 203, 210, 204, 203, 206, 203, 203, 204, 203, 201,
-  203, 209, 203, 200, 203, 203, 206, 201, 201, 209, 203, 204, 209, 209, 213, 210,
-  210, 218, 213, 215, 212, 133, 94, 76, 79, 84, 81, 76, 94, 79, 84, 94,
-  96, 135, 158, 181, 203, 206, 206, 101, 32, 18, 20, 23, 29, 41, 35, 32,
-  35, 26, 41, 38, 29, 43, 29, 23, 23, 49, 121, 156, 156, 149, 149, 155,
-  164, 167, 171, 167, 172, 167, 164, 167, 169, 167, 169, 167, 165, 164, 167, 162,
-  160, 162, 162, 162, 162, 162, 162, 164, 162, 164, 158, 164, 162, 160, 158, 160,
-  86, 91, 105, 91, 101, 98, 94, 96, 84, 91, 86, 91, 96, 112, 127, 135,
-  153, 162, 171, 177, 179, 176, 176, 172, 174, 177, 174, 167, 162, 145, 125, 105,
-  76, 63, 55, 68, 71, 79, 76, 84, 81, 89, 89, 81, 84, 84, 91, 84,
-  101, 86, 98, 79, 89, 81, 86, 84, 86, 84, 60, 55, 193, 210, 219, 195,
-  216, 192, 200, 147, 155, 110, 91, 169, 133, 153, 117, 121, 131, 105, 81, 108,
-  110, 127, 129, 145, 137, 139, 129, 125, 114, 121, 125, 127, 131, 135, 129, 125,
-  123, 127, 137, 137, 141, 129, 117, 110, 135, 137, 135, 119, 98, 129, 137, 119,
-  125, 76, 46, 43, 41, 43, 41, 43, 57, 94, 101, 137, 103, 121, 105, 137,
-  117, 89, 149, 43, 41, 23, 46, 129, 32, 29, 46, 12, 18, 55, 162, 201,
-  151, 112, 160, 207, 195, 200, 198, 200, 203, 207, 204, 198, 203, 201, 197, 201,
-  200, 198, 206, 204, 201, 203, 201, 203, 203, 207, 206, 207, 210, 212, 210, 206,
-  215, 216, 212, 184, 103, 81, 84, 81, 91, 81, 76, 81, 91, 96, 103, 121,
-  149, 172, 185, 204, 204, 206, 46, 26, 18, 23, 29, 29, 43, 29, 35, 20,
-  32, 23, 46, 35, 41, 41, 35, 26, 38, 89, 135, 153, 155, 145, 143, 155,
-  160, 169, 169, 171, 169, 167, 164, 164, 172, 165, 167, 171, 164, 164, 164, 167,
-  160, 165, 164, 160, 162, 158, 162, 162, 156, 160, 162, 158, 162, 162, 162, 158,
-  98, 101, 101, 101, 101, 91, 89, 91, 89, 86, 94, 98, 98, 108, 129, 139,
-  149, 156, 171, 172, 174, 174, 174, 179, 171, 176, 177, 164, 158, 145, 129, 101,
-  81, 68, 63, 55, 71, 71, 81, 79, 76, 89, 96, 86, 89, 94, 86, 84,
-  89, 86, 89, 86, 89, 84, 81, 84, 86, 86, 71, 68, 117, 228, 190, 218,
-  193, 219, 189, 172, 123, 129, 153, 139, 162, 110, 155, 121, 110, 94, 94, 117,
-  125, 127, 141, 127, 133, 137, 112, 112, 121, 117, 127, 125, 129, 133, 129, 117,
-  131, 141, 137, 137, 127, 114, 94, 125, 127, 145, 119, 123, 94, 121, 98, 74,
-  66, 60, 74, 49, 35, 57, 55, 52, 84, 112, 133, 117, 103, 76, 71, 101,
-  55, 149, 101, 60, 76, 43, 43, 131, 18, 18, 18, 32, 89, 184, 193, 133,
-  112, 162, 200, 207, 200, 197, 195, 190, 198, 203, 200, 198, 198, 204, 198, 193,
-  200, 203, 195, 204, 195, 203, 204, 203, 204, 204, 204, 209, 207, 209, 204, 209,
-  210, 197, 147, 127, 79, 84, 86, 86, 84, 81, 84, 81, 119, 133, 156, 160,
-  165, 184, 200, 201, 218, 81, 15, 23, 29, 23, 20, 35, 26, 43, 23, 29,
-  35, 29, 32, 32, 55, 46, 41, 43, 60, 114, 149, 147, 155, 147, 147, 164,
-  171, 172, 172, 169, 169, 171, 162, 167, 169, 167, 172, 164, 164, 162, 164, 169,
-  167, 167, 162, 164, 164, 162, 164, 160, 162, 162, 164, 164, 160, 156, 158, 156,
-  101, 98, 98, 91, 94, 84, 94, 94, 91, 89, 89, 91, 98, 117, 121, 143,
-  149, 156, 171, 177, 181, 176, 176, 174, 177, 176, 176, 164, 158, 145, 127, 101,
-  76, 60, 55, 60, 71, 98, 81, 86, 86, 86, 89, 91, 81, 94, 89, 91,
-  91, 86, 86, 91, 89, 81, 86, 96, 96, 86, 84, 52, 84, 218, 219, 197,
-  212, 192, 210, 149, 160, 131, 131, 149, 133, 145, 127, 131, 89, 96, 114, 112,
-  145, 125, 125, 141, 133, 135, 110, 125, 125, 123, 123, 131, 131, 119, 121, 131,
-  147, 135, 135, 125, 121, 96, 133, 131, 135, 117, 114, 91, 68, 55, 43, 63,
-  96, 81, 60, 38, 23, 35, 26, 63, 147, 89, 131, 105, 38, 35, 35, 86,
-  114, 66, 74, 114, 57, 9, 41, 114, 18, 15, 15, 96, 177, 181, 137, 117,
-  171, 192, 201, 198, 190, 189, 190, 195, 200, 200, 200, 200, 200, 195, 195, 198,
-  201, 197, 201, 198, 201, 201, 201, 203, 201, 204, 204, 206, 209, 210, 209, 197,
-  125, 89, 147, 137, 119, 96, 89, 74, 81, 98, 119, 139, 158, 160, 172, 171,
-  182, 187, 201, 215, 94, 18, 23, 26, 29, 23, 41, 38, 38, 32, 32, 20,
-  23, 23, 26, 29, 32, 46, 89, 35, 76, 135, 156, 155, 151, 145, 158, 171,
-  171, 171, 176, 167, 165, 167, 164, 165, 165, 165, 167, 169, 167, 169, 165, 165,
-  167, 165, 162, 160, 162, 160, 164, 160, 162, 162, 164, 156, 164, 156, 158, 151,
-  101, 98, 98, 98, 98, 94, 98, 98, 98, 94, 91, 98, 103, 108, 121, 141,
-  149, 158, 167, 171, 174, 172, 172, 177, 171, 172, 176, 164, 155, 149, 129, 103,
-  79, 66, 66, 66, 71, 74, 71, 79, 89, 81, 86, 84, 96, 76, 81, 94,
-  98, 81, 98, 86, 103, 84, 86, 91, 89, 89, 79, 63, 57, 209, 207, 215,
-  187, 210, 181, 201, 149, 139, 112, 155, 133, 155, 145, 96, 79, 114, 114, 139,
-  125, 133, 133, 131, 112, 110, 119, 123, 117, 119, 125, 131, 135, 119, 108, 135,
-  133, 135, 133, 127, 133, 98, 135, 135, 123, 94, 74, 43, 35, 63, 117, 96,
-  57, 38, 38, 20, 41, 29, 35, 131, 121, 141, 105, 18, 18, 32, 57, 143,
-  41, 79, 137, 46, 18, 12, 74, 60, 32, 20, 110, 185, 169, 127, 137, 179,
-  206, 198, 198, 192, 189, 192, 197, 197, 195, 200, 197, 198, 193, 195, 198, 195,
-  198, 198, 201, 197, 198, 201, 204, 204, 203, 207, 209, 207, 207, 201, 145, 71,
-  117, 98, 139, 155, 129, 108, 112, 121, 143, 160, 165, 174, 167, 167, 165, 174,
-  182, 200, 215, 79, 29, 23, 23, 32, 23, 41, 43, 35, 43, 46, 35, 32,
-  18, 26, 35, 49, 76, 41, 43, 41, 114, 145, 155, 151, 143, 141, 165, 174,
-  176, 172, 172, 172, 172, 172, 174, 171, 167, 172, 165, 167, 165, 167, 162, 162,
-  167, 162, 164, 160, 164, 167, 162, 164, 162, 164, 160, 162, 160, 158, 160, 160,
-  103, 101, 89, 91, 105, 96, 98, 91, 89, 94, 91, 86, 101, 108, 121, 137,
-  149, 156, 169, 171, 176, 171, 172, 177, 171, 172, 174, 167, 158, 145, 127, 98,
-  84, 63, 60, 60, 76, 66, 74, 84, 94, 86, 84, 98, 91, 94, 86, 86,
-  84, 94, 94, 84, 86, 84, 86, 86, 91, 91, 84, 68, 60, 129, 225, 193,
-  213, 187, 210, 182, 182, 155, 137, 129, 167, 114, 143, 103, 98, 108, 129, 135,
-  131, 133, 131, 125, 89, 121, 127, 125, 127, 133, 114, 121, 123, 117, 145, 137,
-  131, 129, 131, 139, 153, 110, 112, 131, 84, 63, 43, 41, 103, 121, 43, 32,
-  26, 32, 49, 20, 32, 20, 94, 133, 127, 84, 26, 32, 26, 52, 149, 76,
-  71, 89, 79, 15, 38, 18, 121, 66, 38, 133, 185, 158, 121, 131, 189, 207,
-  204, 201, 195, 190, 189, 190, 192, 193, 190, 192, 195, 198, 197, 190, 195, 198,
-  195, 200, 201, 203, 200, 200, 204, 206, 206, 206, 212, 204, 156, 60, 98, 74,
-  121, 112, 129, 151, 151, 165, 164, 160, 169, 165, 169, 167, 177, 172, 172, 184,
-  200, 219, 96, 20, 18, 12, 29, 35, 49, 41, 41, 49, 29, 29, 35, 29,
-  43, 32, 41, 32, 26, 26, 41, 91, 127, 156, 153, 155, 141, 147, 174, 171,
-  171, 172, 174, 169, 176, 174, 169, 165, 165, 167, 169, 165, 165, 165, 164, 171,
-  165, 164, 162, 164, 165, 162, 158, 158, 164, 165, 164, 156, 160, 156, 158, 156,
-  108, 101, 96, 98, 98, 101, 98, 89, 94, 94, 96, 98, 101, 105, 119, 137,
-  151, 160, 167, 177, 176, 176, 171, 174, 171, 174, 176, 167, 158, 141, 131, 103,
-  79, 63, 49, 57, 79, 71, 84, 89, 91, 89, 86, 89, 86, 89, 86, 94,
-  96, 86, 81, 84, 86, 89, 86, 89, 89, 86, 86, 71, 63, 86, 224, 213,
-  189, 212, 197, 203, 197, 156, 182, 133, 172, 129, 91, 98, 119, 121, 131, 129,
-  137, 133, 114, 89, 114, 119, 121, 119, 123, 129, 121, 119, 103, 133, 133, 94,
-  81, 117, 133, 137, 139, 108, 79, 89, 57, 41, 43, 108, 76, 35, 38, 20,
-  41, 60, 23, 12, 41, 35, 123, 101, 74, 57, 23, 29, 60, 145, 103, 63,
-  91, 55, 18, 35, 26, 32, 153, 35, 139, 187, 151, 114, 143, 193, 203, 207,
-  200, 192, 193, 185, 192, 192, 193, 192, 192, 189, 190, 190, 187, 198, 192, 193,
-  197, 200, 204, 200, 200, 203, 203, 206, 207, 209, 176, 94, 29, 49, 131, 119,
-  96, 110, 110, 147, 158, 167, 160, 171, 171, 171, 167, 174, 176, 182, 192, 206,
-  216, 125, 32, 29, 15, 18, 23, 29, 41, 41, 43, 35, 52, 32, 29, 23,
-  43, 35, 38, 35, 18, 55, 32, 103, 143, 155, 147, 153, 147, 164, 174, 171,
-  172, 169, 171, 172, 176, 172, 169, 167, 171, 164, 169, 171, 169, 165, 162, 169,
-  167, 164, 165, 164, 169, 162, 162, 162, 162, 158, 164, 158, 165, 162, 156, 160,
-  101, 98, 105, 98, 96, 98, 101, 89, 89, 94, 86, 89, 96, 112, 123, 135,
-  149, 156, 164, 171, 177, 176, 174, 176, 174, 177, 174, 164, 158, 145, 127, 108,
-  79, 60, 55, 60, 81, 74, 84, 86, 74, 81, 96, 91, 84, 86, 81, 89,
-  94, 84, 76, 94, 89, 89, 94, 96, 91, 89, 89, 76, 66, 71, 210, 206,
-  218, 201, 206, 200, 155, 185, 162, 179, 135, 160, 86, 114, 121, 127, 139, 135,
-  131, 127, 96, 119, 119, 121, 127, 125, 119, 125, 123, 114, 119, 141, 133, 141,
-  119, 96, 60, 117, 129, 117, 84, 46, 55, 91, 79, 55, 49, 43, 41, 29,
-  74, 29, 9, 18, 35, 105, 121, 46, 46, 23, 29, 38, 133, 71, 89, 129,
-  96, 12, 23, 133, 3, 20, 165, 153, 177, 139, 123, 145, 197, 189, 204, 206,
-  198, 190, 179, 190, 197, 193, 197, 185, 192, 190, 187, 192, 189, 190, 198, 198,
-  198, 195, 198, 197, 203, 204, 204, 203, 203, 91, 35, 86, 91, 52, 147, 137,
-  105, 127, 101, 147, 155, 165, 162, 171, 172, 174, 174, 179, 185, 192, 200, 213,
-  131, 20, 20, 20, 26, 26, 32, 29, 46, 32, 43, 38, 43, 32, 26, 26,
-  32, 32, 32, 38, 35, 38, 66, 123, 149, 149, 145, 145, 151, 167, 176, 172,
-  172, 172, 171, 167, 174, 172, 171, 171, 169, 172, 174, 167, 167, 165, 169, 165,
-  169, 162, 162, 164, 165, 165, 160, 162, 164, 164, 164, 160, 164, 158, 160, 156,
-  94, 98, 94, 98, 96, 94, 96, 91, 94, 91, 91, 108, 89, 101, 121, 135,
-  147, 160, 171, 172, 179, 171, 174, 174, 172, 174, 174, 171, 160, 143, 137, 108,
-  84, 52, 60, 68, 71, 86, 79, 86, 84, 86, 86, 81, 79, 81, 94, 98,
-  84, 89, 81, 91, 86, 79, 98, 96, 98, 94, 91, 86, 91, 79, 114, 228,
-  209, 212, 212, 189, 167, 172, 193, 160, 127, 86, 89, 123, 129, 117, 121, 133,
-  114, 89, 125, 127, 123, 133, 108, 119, 105, 121, 112, 121, 137, 143, 135, 133,
-  103, 91, 114, 84, 68, 76, 68, 66, 52, 79, 81, 74, 55, 43, 32, 91,
-  71, 15, 15, 20, 49, 71, 123, 26, 46, 43, 38, 141, 63, 81, 127, 81,
-  23, 29, 143, 84, 12, 63, 172, 184, 123, 121, 147, 197, 207, 204, 197, 200,
-  200, 189, 189, 190, 190, 192, 189, 189, 189, 182, 182, 189, 184, 187, 192, 203,
-  195, 204, 201, 203, 198, 207, 204, 184, 86, 29, 23, 96, 121, 68, 98, 158,
-  117, 133, 121, 139, 156, 151, 153, 169, 172, 177, 179, 185, 190, 206, 200, 103,
-  29, 18, 20, 20, 26, 29, 38, 32, 38, 43, 35, 41, 43, 32, 29, 23,
-  20, 41, 35, 38, 26, 35, 94, 137, 151, 149, 141, 149, 162, 169, 169, 176,
-  174, 177, 172, 172, 172, 171, 172, 174, 169, 165, 169, 169, 167, 169, 164, 162,
-  167, 165, 162, 165, 165, 162, 160, 165, 160, 162, 162, 158, 162, 156, 162, 156,
-  98, 105, 98, 112, 103, 98, 96, 91, 98, 89, 101, 91, 84, 108, 125, 135,
-  149, 160, 167, 176, 174, 174, 174, 176, 174, 176, 177, 162, 160, 147, 129, 112,
-  81, 55, 49, 57, 74, 76, 76, 76, 86, 76, 86, 86, 84, 84, 81, 86,
-  84, 94, 84, 81, 86, 84, 91, 96, 91, 98, 89, 94, 86, 74, 76, 207,
-  219, 218, 203, 195, 165, 181, 174, 184, 165, 84, 98, 141, 125, 129, 121, 129,
-  114, 108, 125, 117, 131, 121, 121, 117, 121, 121, 112, 141, 133, 135, 139, 119,
-  94, 35, 38, 52, 74, 86, 55, 71, 84, 86, 57, 60, 23, 20, 81, 108,
-  23, 18, 26, 29, 86, 43, 57, 20, 26, 38, 46, 89, 60, 52, 108, 49,
-  15, 108, 164, 15, 26, 158, 156, 125, 121, 158, 197, 203, 207, 204, 200, 198,
-  200, 197, 193, 195, 190, 187, 190, 190, 185, 185, 184, 192, 197, 187, 192, 200,
-  203, 203, 201, 200, 193, 192, 176, 112, 74, 71, 84, 60, 108, 123, 94, 123,
-  153, 114, 139, 101, 151, 158, 155, 171, 169, 177, 172, 193, 212, 185, 32, 23,
-  20, 6, 23, 23, 23, 29, 32, 43, 52, 35, 66, 41, 43, 32, 35, 29,
-  35, 29, 46, 38, 35, 60, 108, 141, 141, 141, 133, 149, 169, 176, 172, 169,
-  171, 177, 171, 172, 169, 169, 172, 169, 172, 169, 169, 169, 167, 171, 167, 164,
-  169, 165, 167, 160, 165, 167, 165, 164, 164, 165, 162, 160, 158, 158, 158, 158,
-  94, 103, 105, 108, 112, 105, 96, 96, 84, 91, 94, 94, 91, 108, 123, 137,
-  145, 160, 167, 169, 174, 177, 172, 177, 176, 179, 176, 164, 155, 147, 131, 108,
-  71, 63, 60, 63, 71, 66, 81, 84, 84, 84, 94, 91, 86, 91, 86, 86,
-  86, 94, 84, 89, 89, 86, 91, 91, 96, 105, 91, 89, 89, 84, 68, 98,
-  225, 209, 222, 195, 187, 177, 185, 198, 151, 96, 127, 131, 125, 127, 119, 117,
-  101, 112, 123, 133, 127, 129, 117, 125, 112, 117, 137, 133, 112, 96, 101, 121,
-  103, 110, 81, 76, 68, 49, 52, 103, 71, 63, 35, 26, 20, 49, 121, 110,
-  9, 15, 20, 43, 98, 32, 26, 20, 41, 41, 43, 35, 32, 55, 125, 15,
-  15, 153, 119, 57, 105, 135, 121, 103, 172, 200, 206, 203, 203, 203, 201, 195,
-  195, 189, 192, 185, 192, 193, 195, 193, 182, 176, 189, 195, 190, 193, 197, 198,
-  197, 200, 195, 192, 190, 197, 192, 172, 91, 60, 81, 112, 71, 96, 98, 84,
-  151, 131, 123, 105, 127, 160, 151, 164, 176, 185, 200, 212, 151, 38, 23, 43,
-  32, 20, 26, 29, 32, 32, 35, 46, 38, 57, 43, 38, 23, 49, 20, 29,
-  38, 41, 43, 41, 57, 76, 123, 141, 135, 137, 127, 155, 174, 176, 174, 177,
-  167, 176, 167, 172, 169, 167, 171, 169, 172, 172, 172, 171, 169, 167, 169, 169,
-  167, 167, 169, 167, 165, 169, 165, 165, 162, 162, 165, 162, 164, 156, 156, 160,
-  103, 105, 103, 94, 96, 98, 98, 94, 86, 91, 76, 81, 89, 101, 117, 131,
-  147, 160, 167, 167, 177, 177, 177, 177, 176, 177, 177, 176, 158, 147, 131, 110,
-  76, 55, 60, 63, 68, 76, 81, 81, 76, 94, 89, 94, 89, 89, 86, 91,
-  89, 81, 84, 86, 94, 94, 86, 96, 96, 98, 98, 94, 94, 81, 79, 68,
-  155, 228, 212, 195, 203, 187, 192, 181, 91, 131, 135, 110, 129, 131, 127, 112,
-  114, 121, 125, 123, 133, 125, 121, 110, 108, 108, 137, 131, 121, 121, 127, 114,
-  119, 86, 91, 68, 49, 60, 98, 96, 55, 29, 18, 20, 23, 52, 121, 76,
-  18, 23, 29, 29, 68, 52, 41, 20, 46, 35, 29, 35, 20, 55, 119, 18,
-  43, 155, 101, 153, 151, 55, 105, 139, 203, 197, 203, 200, 200, 201, 190, 192,
-  190, 189, 190, 192, 189, 197, 193, 185, 179, 182, 192, 195, 192, 192, 195, 195,
-  193, 187, 182, 193, 197, 198, 192, 176, 127, 81, 68, 57, 133, 89, 103, 94,
-  105, 156, 127, 127, 125, 155, 155, 181, 190, 209, 195, 117, 32, 32, 15, 23,
-  32, 23, 38, 38, 38, 46, 32, 32, 38, 43, 46, 35, 32, 26, 26, 23,
-  32, 43, 46, 46, 63, 98, 133, 145, 133, 123, 135, 160, 174, 174, 174, 176,
-  171, 167, 171, 165, 176, 167, 171, 172, 171, 171, 171, 169, 167, 165, 167, 171,
-  164, 160, 169, 169, 171, 169, 165, 165, 164, 165, 164, 162, 162, 158, 160, 160,
-  101, 98, 105, 98, 98, 96, 98, 94, 84, 89, 86, 81, 81, 98, 114, 135,
-  141, 162, 169, 177, 176, 174, 172, 174, 179, 184, 172, 174, 164, 147, 127, 103,
-  79, 60, 57, 60, 68, 84, 74, 79, 79, 91, 94, 81, 81, 86, 86, 91,
-  86, 96, 86, 96, 89, 91, 91, 98, 98, 96, 103, 98, 105, 98, 81, 74,
-  76, 219, 209, 200, 204, 197, 204, 158, 96, 156, 119, 103, 127, 123, 114, 117,
-  127, 119, 129, 125, 117, 127, 114, 133, 127, 129, 112, 86, 129, 129, 103, 81,
-  49, 89, 60, 74, 76, 81, 96, 76, 41, 35, 38, 20, 26, 79, 117, 41,
-  12, 18, 96, 23, 38, 43, 35, 46, 68, 84, 79, 84, 35, 96, 81, 55,
-  101, 127, 129, 125, 137, 76, 164, 164, 195, 198, 198, 195, 203, 198, 197, 193,
-  193, 187, 197, 185, 195, 189, 184, 184, 189, 181, 189, 192, 192, 192, 197, 187,
-  193, 190, 197, 197, 203, 201, 197, 184, 147, 98, 79, 89, 63, 149, 112, 101,
-  91, 143, 145, 147, 129, 153, 167, 190, 200, 153, 41, 38, 35, 26, 32, 20,
-  18, 23, 35, 35, 49, 38, 32, 46, 35, 43, 35, 23, 20, 29, 29, 35,
-  41, 41, 41, 49, 66, 123, 139, 141, 133, 129, 145, 167, 174, 181, 174, 177,
-  172, 171, 172, 172, 171, 169, 172, 171, 174, 165, 171, 171, 171, 167, 167, 167,
-  169, 165, 167, 167, 167, 162, 171, 165, 162, 165, 165, 160, 162, 156, 164, 155,
-  98, 101, 103, 103, 96, 89, 98, 101, 94, 91, 84, 81, 81, 91, 119, 127,
-  145, 164, 165, 171, 176, 176, 182, 179, 174, 179, 179, 174, 160, 149, 137, 108,
-  79, 60, 43, 57, 60, 68, 76, 79, 84, 84, 84, 86, 89, 86, 86, 86,
-  91, 84, 89, 89, 86, 98, 96, 101, 96, 103, 108, 96, 103, 98, 94, 76,
-  68, 165, 227, 207, 197, 198, 210, 158, 131, 123, 119, 108, 112, 110, 91, 110,
-  125, 127, 133, 112, 117, 98, 105, 119, 127, 131, 131, 139, 112, 112, 55, 41,
-  76, 66, 60, 86, 71, 108, 103, 57, 41, 35, 41, 20, 41, 79, 66, 63,
-  29, 38, 112, 20, 35, 41, 29, 32, 43, 55, 57, 41, 41, 84, 46, 74,
-  52, 110, 81, 149, 127, 164, 181, 176, 197, 193, 189, 193, 197, 192, 190, 184,
-  182, 184, 184, 185, 184, 190, 189, 184, 182, 181, 185, 189, 190, 187, 195, 197,
-  197, 201, 197, 200, 200, 206, 203, 197, 169, 137, 84, 84, 71, 55, 139, 79,
-  81, 55, 149, 143, 145, 145, 160, 158, 131, 74, 15, 20, 15, 32, 20, 38,
-  38, 26, 29, 43, 41, 41, 41, 41, 41, 49, 35, 23, 23, 35, 35, 35,
-  38, 20, 35, 55, 84, 131, 137, 137, 131, 129, 155, 174, 179, 177, 174, 172,
-  171, 171, 174, 174, 169, 177, 172, 172, 167, 167, 165, 171, 172, 171, 171, 169,
-  167, 165, 169, 169, 169, 169, 165, 164, 167, 165, 167, 162, 160, 162, 156, 160,
-  101, 101, 103, 94, 94, 103, 91, 91, 86, 84, 91, 79, 81, 98, 110, 135,
-  149, 156, 160, 165, 174, 179, 176, 174, 179, 176, 177, 169, 158, 145, 127, 112,
-  79, 66, 52, 55, 68, 60, 76, 76, 89, 81, 86, 86, 89, 84, 84, 79,
-  81, 86, 91, 89, 89, 94, 94, 101, 91, 98, 108, 103, 98, 101, 89, 84,
-  68, 135, 222, 228, 206, 204, 200, 172, 139, 121, 121, 127, 112, 94, 108, 123,
-  119, 129, 125, 108, 98, 121, 133, 119, 121, 114, 81, 141, 129, 105, 71, 57,
-  66, 41, 43, 60, 55, 86, 89, 68, 41, 32, 29, 23, 60, 55, 55, 96,
-  86, 57, 20, 29, 26, 23, 26, 29, 32, 35, 32, 20, 12, 55, 49, 71,
-  74, 89, 81, 125, 125, 149, 155, 176, 190, 187, 182, 193, 192, 187, 184, 184,
-  177, 184, 189, 181, 184, 181, 189, 185, 181, 189, 181, 185, 187, 195, 203, 195,
-  197, 195, 200, 201, 197, 201, 201, 201, 185, 149, 103, 81, 46, 49, 49, 127,
-  101, 57, 133, 143, 147, 139, 156, 141, 117, 84, 15, 20, 29, 32, 26, 26,
-  35, 20, 38, 46, 43, 41, 38, 41, 52, 46, 32, 32, 20, 32, 43, 35,
-  32, 32, 55, 66, 112, 137, 139, 129, 121, 135, 160, 174, 174, 172, 176, 174,
-  174, 172, 176, 169, 171, 174, 172, 172, 176, 169, 165, 171, 171, 172, 167, 169,
-  167, 174, 171, 167, 162, 165, 171, 167, 162, 165, 162, 162, 164, 160, 156, 162,
-  98, 101, 96, 98, 103, 91, 101, 94, 91, 91, 89, 76, 71, 96, 108, 129,
-  147, 151, 165, 171, 172, 174, 176, 176, 179, 176, 176, 167, 162, 149, 127, 110,
-  84, 60, 52, 66, 55, 68, 84, 84, 81, 86, 91, 91, 98, 94, 96, 86,
-  84, 84, 89, 89, 94, 94, 98, 94, 101, 110, 103, 103, 108, 108, 94, 86,
-  68, 123, 224, 218, 219, 206, 207, 189, 131, 121, 121, 121, 119, 98, 119, 119,
-  117, 117, 96, 129, 127, 133, 121, 117, 127, 114, 86, 114, 101, 96, 52, 57,
-  52, 38, 46, 23, 49, 101, 76, 55, 71, 52, 52, 35, 63, 46, 38, 112,
-  105, 63, 18, 29, 38, 38, 35, 29, 41, 38, 32, 26, 23, 55, 84, 123,
-  79, 94, 94, 156, 153, 171, 176, 185, 189, 184, 192, 195, 193, 179, 182, 172,
-  179, 185, 185, 190, 189, 184, 177, 185, 187, 182, 171, 193, 192, 197, 204, 198,
-  198, 201, 203, 203, 200, 198, 207, 198, 189, 153, 110, 81, 74, 46, 23, 55,
-  81, 71, 55, 143, 139, 160, 165, 149, 110, 57, 32, 23, 20, 18, 35, 23,
-  43, 49, 41, 35, 43, 57, 46, 43, 57, 41, 41, 35, 20, 26, 29, 35,
-  32, 43, 46, 89, 133, 145, 133, 127, 131, 145, 160, 171, 176, 174, 174, 172,
-  174, 176, 172, 167, 172, 171, 169, 169, 169, 174, 171, 167, 171, 171, 164, 165,
-  167, 171, 169, 165, 169, 162, 167, 165, 164, 169, 165, 160, 164, 158, 165, 158,
-  105, 105, 103, 96, 91, 98, 96, 89, 89, 81, 89, 74, 79, 98, 121, 129,
-  141, 156, 162, 174, 181, 172, 179, 177, 179, 176, 177, 174, 160, 151, 137, 114,
-  81, 57, 49, 57, 63, 71, 84, 79, 89, 84, 84, 89, 96, 91, 86, 89,
-  84, 89, 79, 79, 89, 89, 94, 94, 96, 103, 101, 108, 108, 94, 91, 89,
-  74, 121, 222, 218, 224, 216, 201, 131, 101, 112, 125, 121, 110, 121, 117, 119,
-  98, 101, 114, 135, 131, 129, 131, 125, 114, 94, 66, 91, 66, 38, 81, 74,
-  35, 29, 29, 26, 38, 68, 76, 84, 63, 94, 46, 15, 68, 52, 26, 86,
-  135, 94, 20, 32, 23, 35, 41, 26, 35, 26, 9, 26, 43, 79, 145, 74,
-  74, 108, 133, 162, 174, 192, 182, 190, 190, 193, 201, 195, 193, 182, 171, 179,
-  179, 182, 189, 193, 184, 181, 167, 184, 174, 179, 192, 201, 201, 201, 206, 198,
-  201, 198, 203, 201, 204, 200, 200, 203, 187, 169, 129, 81, 63, 57, 29, 20,
-  117, 81, 84, 145, 147, 145, 156, 151, 125, 46, 23, 18, 20, 23, 26, 23,
-  23, 52, 38, 49, 41, 49, 49, 41, 43, 35, 60, 35, 23, 23, 32, 32,
-  26, 29, 68, 112, 137, 147, 135, 125, 131, 158, 169, 169, 169, 176, 172, 172,
-  171, 171, 169, 169, 169, 172, 171, 169, 165, 171, 171, 172, 167, 169, 167, 169,
-  172, 169, 165, 167, 169, 165, 176, 165, 164, 165, 160, 164, 164, 158, 155, 156,
-  103, 103, 96, 105, 103, 101, 91, 96, 96, 96, 86, 86, 76, 94, 121, 125,
-  143, 155, 165, 169, 171, 176, 176, 179, 177, 176, 176, 172, 160, 151, 133, 110,
-  76, 66, 55, 55, 79, 71, 86, 84, 94, 91, 86, 96, 91, 89, 86, 86,
-  86, 86, 96, 89, 91, 96, 96, 101, 103, 110, 112, 108, 108, 105, 96, 81,
-  66, 125, 221, 224, 213, 224, 177, 110, 86, 114, 123, 110, 119, 117, 117, 103,
-  91, 108, 135, 125, 137, 127, 110, 110, 127, 89, 38, 43, 26, 46, 98, 38,
-  23, 38, 23, 29, 38, 68, 86, 49, 63, 84, 49, 32, 66, 55, 18, 66,
-  125, 137, 46, 23, 29, 32, 38, 29, 29, 9, 15, 20, 96, 127, 123, 60,
-  119, 176, 129, 162, 193, 189, 187, 192, 195, 197, 197, 192, 179, 174, 169, 169,
-  172, 181, 190, 190, 182, 162, 172, 172, 187, 190, 193, 200, 204, 204, 207, 201,
-  204, 200, 200, 203, 207, 206, 207, 200, 193, 169, 129, 91, 63, 52, 29, 29,
-  41, 79, 63, 91, 155, 143, 156, 162, 86, 20, 38, 32, 32, 29, 32, 26,
-  35, 29, 49, 52, 46, 71, 57, 55, 41, 29, 29, 35, 20, 26, 35, 32,
-  26, 41, 89, 125, 153, 143, 133, 127, 147, 162, 162, 169, 171, 171, 177, 176,
-  174, 171, 171, 172, 169, 171, 169, 167, 174, 167, 171, 171, 171, 174, 169, 165,
-  167, 165, 169, 169, 162, 162, 165, 165, 160, 165, 167, 162, 162, 164, 162, 158,
-  94, 98, 96, 98, 94, 98, 105, 94, 86, 86, 89, 84, 71, 91, 114, 129,
-  143, 156, 164, 171, 172, 176, 176, 177, 176, 172, 174, 169, 164, 149, 133, 112,
-  86, 60, 46, 63, 68, 76, 76, 86, 86, 91, 91, 96, 79, 98, 91, 86,
-  86, 86, 96, 86, 91, 98, 98, 94, 101, 101, 108, 103, 108, 103, 101, 86,
-  76, 101, 227, 218, 218, 221, 137, 91, 91, 105, 110, 103, 108, 117, 108, 108,
-  114, 121, 117, 123, 127, 127, 105, 125, 119, 89, 26, 20, 46, 60, 63, 35,
-  32, 23, 29, 35, 29, 35, 89, 76, 52, 74, 68, 26, 52, 79, 12, 41,
-  81, 147, 108, 91, 89, 38, 12, 26, 15, 15, 15, 89, 162, 117, 74, 117,
-  189, 172, 127, 160, 195, 192, 189, 195, 201, 204, 198, 189, 177, 174, 171, 174,
-  181, 182, 193, 189, 176, 169, 174, 172, 189, 187, 193, 203, 198, 200, 207, 203,
-  203, 203, 207, 207, 206, 207, 209, 209, 200, 177, 145, 98, 71, 57, 26, 26,
-  15, 89, 68, 66, 156, 139, 167, 162, 79, 26, 23, 20, 23, 29, 32, 32,
-  29, 35, 35, 43, 43, 52, 52, 49, 20, 26, 29, 26, 32, 41, 29, 35,
-  29, 52, 105, 139, 147, 141, 131, 145, 153, 162, 155, 160, 160, 164, 177, 172,
-  174, 172, 172, 172, 171, 171, 169, 172, 169, 169, 167, 172, 172, 172, 172, 169,
-  164, 165, 169, 162, 165, 165, 165, 169, 162, 165, 165, 160, 160, 162, 155, 155,
-  91, 103, 103, 94, 98, 86, 96, 89, 94, 96, 79, 79, 79, 94, 117, 131,
-  145, 160, 165, 167, 182, 177, 174, 181, 172, 177, 177, 169, 156, 153, 133, 117,
-  94, 55, 57, 71, 68, 74, 84, 79, 89, 86, 96, 94, 89, 89, 96, 94,
-  84, 86, 86, 91, 96, 96, 94, 103, 101, 110, 112, 112, 101, 101, 101, 96,
-  94, 86, 213, 222, 222, 209, 96, 96, 98, 96, 101, 117, 110, 119, 105, 121,
-  121, 129, 123, 101, 117, 105, 110, 117, 103, 105, 26, 20, 46, 101, 23, 20,
-  15, 26, 35, 23, 32, 38, 43, 84, 60, 55, 68, 52, 63, 86, 29, 49,
-  32, 158, 86, 52, 74, 55, 23, 20, 15, 9, 84, 162, 133, 105, 121, 190,
-  164, 169, 137, 155, 198, 185, 172, 197, 197, 198, 190, 179, 171, 171, 171, 169,
-  189, 193, 187, 167, 156, 169, 167, 177, 190, 189, 193, 201, 198, 203, 206, 206,
-  206, 204, 206, 206, 212, 213, 212, 212, 207, 189, 164, 103, 71, 60, 20, 20,
-  32, 52, 81, 49, 155, 153, 181, 160, 63, 23, 38, 20, 29, 23, 23, 35,
-  32, 41, 46, 57, 49, 55, 63, 43, 29, 23, 32, 38, 29, 52, 18, 26,
-  41, 74, 123, 151, 141, 137, 131, 155, 164, 162, 158, 158, 164, 160, 162, 165,
-  169, 169, 176, 171, 169, 169, 171, 174, 167, 169, 167, 171, 171, 171, 169, 167,
-  171, 167, 167, 167, 164, 162, 167, 165, 167, 169, 167, 164, 162, 158, 162, 153,
-  98, 101, 98, 101, 103, 96, 96, 96, 89, 94, 86, 86, 84, 101, 112, 129,
-  143, 158, 167, 169, 176, 172, 176, 172, 179, 176, 179, 171, 165, 158, 137, 112,
-  89, 68, 46, 66, 66, 74, 81, 84, 79, 89, 98, 89, 86, 86, 94, 89,
-  91, 91, 94, 94, 91, 96, 94, 94, 105, 119, 103, 108, 103, 101, 103, 108,
-  89, 76, 174, 227, 225, 192, 105, 103, 108, 105, 103, 112, 101, 86, 119, 139,
-  112, 114, 125, 103, 81, 84, 63, 49, 52, 55, 38, 23, 84, 98, 26, 18,
-  18, 35, 23, 43, 35, 32, 35, 55, 68, 52, 60, 55, 63, 74, 29, 46,
-  26, 149, 91, 20, 15, 23, 15, 6, 9, 57, 174, 133, 91, 137, 189, 181,
-  171, 169, 151, 139, 181, 182, 167, 200, 192, 179, 182, 182, 179, 172, 169, 171,
-  187, 189, 143, 162, 164, 181, 179, 190, 189, 197, 198, 209, 204, 204, 206, 207,
-  204, 206, 207, 210, 212, 213, 215, 216, 209, 197, 167, 119, 86, 63, 23, 12,
-  29, 29, 57, 55, 121, 164, 184, 164, 66, 29, 29, 29, 26, 57, 43, 41,
-  46, 32, 38, 46, 57, 41, 55, 35, 38, 32, 23, 35, 35, 43, 20, 26,
-  38, 98, 135, 155, 139, 125, 149, 162, 171, 164, 156, 164, 160, 156, 153, 162,
-  160, 160, 167, 165, 172, 164, 165, 171, 169, 167, 167, 171, 177, 171, 174, 165,
-  169, 167, 167, 169, 164, 162, 160, 164, 165, 165, 160, 164, 164, 158, 155, 156,
-  86, 94, 105, 91, 108, 101, 91, 96, 94, 91, 94, 86, 84, 91, 110, 129,
-  145, 156, 164, 172, 171, 177, 177, 176, 177, 177, 174, 177, 162, 149, 133, 110,
-  94, 76, 52, 63, 57, 68, 81, 76, 89, 84, 101, 91, 94, 103, 91, 101,
-  86, 96, 89, 89, 94, 86, 96, 101, 193, 101, 98, 112, 112, 105, 96, 101,
-  101, 86, 123, 231, 228, 169, 108, 96, 112, 114, 110, 94, 89, 129, 129, 127,
-  127, 121, 63, 84, 74, 63, 84, 38, 32, 71, 32, 23, 108, 66, 29, 20,
-  29, 63, 46, 49, 20, 26, 29, 38, 38, 52, 46, 38, 89, 101, 63, 41,
-  26, 84, 137, 23, 26, 15, 15, 12, 38, 169, 141, 98, 121, 187, 179, 172,
-  172, 172, 158, 153, 187, 177, 187, 203, 198, 190, 176, 174, 177, 181, 181, 182,
-  177, 147, 164, 162, 171, 177, 177, 190, 192, 200, 195, 200, 203, 204, 204, 204,
-  204, 206, 210, 213, 209, 213, 210, 213, 209, 200, 181, 131, 96, 74, 26, 29,
-  26, 20, 38, 76, 55, 160, 171, 174, 98, 41, 57, 32, 35, 35, 29, 41,
-  43, 41, 43, 49, 60, 60, 52, 43, 29, 23, 32, 32, 35, 38, 23, 23,
-  43, 121, 151, 147, 139, 135, 151, 167, 171, 164, 158, 158, 158, 156, 155, 158,
-  156, 158, 160, 158, 160, 158, 172, 167, 167, 169, 167, 171, 167, 164, 169, 171,
-  172, 165, 169, 162, 169, 160, 167, 164, 162, 165, 164, 158, 164, 158, 160, 155,
-  101, 98, 94, 101, 91, 96, 98, 96, 94, 96, 84, 79, 79, 89, 112, 133,
-  143, 155, 164, 172, 176, 176, 179, 179, 174, 181, 176, 177, 162, 149, 133, 117,
-  96, 71, 66, 46, 63, 74, 86, 91, 89, 89, 91, 94, 98, 101, 89, 98,
-  96, 89, 94, 91, 84, 84, 98, 176, 110, 105, 112, 108, 110, 101, 112, 110,
-  105, 108, 108, 198, 228, 176, 96, 108, 110, 110, 117, 89, 125, 121, 129, 117,
-  127, 135, 117, 105, 98, 79, 57, 26, 29, 20, 18, 38, 114, 55, 23, 29,
-  57, 60, 26, 46, 26, 41, 55, 41, 29, 57, 41, 35, 52, 117, 127, 76,
-  20, 41, 149, 23, 18, 18, 9, 43, 156, 151, 121, 119, 192, 176, 190, 181,
-  172, 182, 158, 155, 192, 182, 182, 198, 201, 192, 176, 181, 182, 177, 179, 167,
-  147, 149, 165, 171, 169, 176, 185, 195, 195, 189, 198, 204, 204, 201, 206, 206,
-  206, 206, 212, 210, 215, 212, 215, 216, 209, 198, 189, 151, 103, 63, 35, 29,
-  12, 15, 35, 68, 32, 165, 165, 174, 119, 43, 32, 55, 29, 41, 38, 41,
-  41, 43, 46, 49, 60, 57, 38, 35, 29, 20, 38, 43, 46, 46, 26, 20,
-  68, 127, 145, 145, 135, 145, 162, 171, 174, 167, 164, 162, 160, 160, 158, 162,
-  160, 156, 155, 156, 164, 160, 164, 160, 160, 162, 165, 165, 165, 167, 172, 167,
-  167, 169, 167, 165, 165, 169, 162, 164, 164, 162, 160, 167, 164, 158, 156, 153,
-  98, 96, 101, 96, 94, 96, 91, 96, 89, 91, 89, 84, 79, 101, 112, 131,
-  139, 153, 164, 176, 172, 179, 179, 174, 174, 184, 181, 169, 156, 153, 133, 129,
-  96, 74, 55, 71, 74, 74, 79, 91, 96, 91, 91, 94, 94, 89, 89, 89,
-  94, 86, 89, 89, 101, 98, 98, 114, 105, 105, 105, 114, 110, 108, 105, 112,
-  112, 103, 89, 119, 231, 207, 105, 112, 105, 91, 110, 119, 127, 114, 108, 131,
-  119, 125, 96, 96, 66, 46, 35, 38, 57, 20, 20, 12, 89, 52, 23, 20,
-  55, 26, 41, 32, 32, 41, 41, 35, 26, 46, 26, 49, 81, 89, 57, 103,
-  76, 46, 181, 117, 12, 9, 23, 145, 160, 117, 121, 182, 190, 179, 189, 182,
-  184, 187, 172, 156, 176, 177, 190, 207, 210, 185, 176, 184, 176, 171, 164, 143,
-  155, 158, 167, 174, 172, 174, 187, 192, 197, 195, 197, 201, 204, 207, 206, 207,
-  207, 207, 212, 213, 212, 213, 213, 213, 212, 206, 190, 160, 103, 68, 52, 18,
-  20, 12, 15, 57, 52, 155, 169, 181, 96, 43, 35, 38, 43, 46, 29, 41,
-  46, 41, 49, 57, 57, 60, 55, 32, 41, 35, 26, 38, 41, 32, 29, 41,
-  96, 139, 151, 143, 133, 149, 164, 177, 176, 164, 164, 162, 162, 158, 160, 160,
-  156, 160, 153, 153, 156, 156, 155, 160, 160, 151, 156, 160, 160, 164, 165, 167,
-  169, 167, 167, 164, 164, 162, 164, 162, 160, 164, 164, 160, 158, 153, 156, 153,
-  101, 101, 96, 103, 94, 84, 89, 98, 81, 96, 86, 81, 89, 91, 108, 123,
-  143, 153, 165, 167, 174, 179, 179, 181, 179, 181, 177, 174, 162, 147, 135, 119,
-  89, 76, 71, 74, 81, 81, 84, 89, 89, 86, 98, 96, 98, 94, 89, 98,
-  96, 98, 86, 86, 98, 86, 103, 112, 105, 105, 105, 110, 108, 112, 110, 105,
-  112, 108, 98, 98, 207, 212, 121, 114, 103, 101, 119, 125, 119, 123, 137, 123,
-  127, 94, 84, 91, 38, 49, 29, 79, 29, 20, 12, 18, 63, 86, 63, 76,
-  23, 29, 57, 32, 29, 41, 35, 35, 63, 46, 12, 23, 110, 52, 55, 79,
-  43, 38, 174, 76, 12, 9, 129, 176, 117, 114, 169, 187, 174, 179, 190, 197,
-  187, 190, 158, 156, 176, 171, 193, 207, 200, 181, 172, 169, 174, 155, 153, 158,
-  165, 171, 171, 174, 171, 184, 185, 192, 198, 200, 201, 203, 203, 204, 207, 207,
-  210, 207, 210, 210, 213, 215, 216, 216, 218, 210, 198, 162, 117, 81, 60, 32,
-  23, 20, 23, 32, 94, 98, 172, 177, 94, 71, 35, 26, 35, 43, 38, 35,
-  49, 52, 41, 49, 57, 52, 41, 26, 26, 41, 32, 46, 55, 29, 26, 71,
-  127, 149, 147, 145, 137, 155, 172, 172, 171, 172, 169, 174, 169, 169, 164, 162,
-  162, 162, 162, 156, 158, 160, 158, 156, 151, 156, 158, 156, 153, 155, 164, 165,
-  165, 164, 165, 164, 158, 165, 160, 158, 164, 162, 160, 162, 155, 158, 155, 153,
-  98, 96, 94, 101, 91, 91, 94, 91, 84, 86, 86, 81, 68, 89, 110, 125,
-  143, 155, 167, 176, 179, 179, 179, 181, 181, 179, 179, 169, 156, 145, 135, 112,
-  94, 66, 66, 57, 81, 76, 84, 89, 96, 96, 94, 89, 94, 89, 91, 101,
-  89, 96, 94, 91, 89, 94, 96, 129, 110, 112, 105, 117, 114, 108, 121, 119,
-  110, 105, 114, 110, 129, 216, 121, 119, 89, 103, 131, 139, 121, 125, 129, 131,
-  125, 101, 55, 20, 46, 26, 119, 108, 15, 20, 29, 18, 38, 114, 41, 23,
-  32, 76, 66, 23, 38, 43, 23, 35, 81, 32, 18, 23, 86, 23, 71, 52,
-  20, 6, 71, 131, 9, 105, 165, 117, 125, 153, 177, 172, 182, 181, 197, 195,
-  195, 195, 153, 135, 185, 185, 200, 201, 185, 174, 164, 177, 147, 158, 156, 156,
-  169, 169, 176, 176, 176, 179, 189, 187, 200, 195, 193, 203, 201, 203, 210, 209,
-  206, 209, 212, 213, 212, 210, 216, 216, 218, 210, 204, 171, 135, 86, 74, 38,
-  32, 23, 23, 35, 79, 66, 177, 184, 86, 41, 23, 38, 41, 49, 35, 43,
-  43, 41, 52, 43, 52, 41, 32, 35, 23, 26, 49, 41, 32, 32, 26, 79,
-  137, 151, 145, 139, 147, 164, 174, 177, 176, 172, 169, 171, 172, 167, 165, 164,
-  169, 167, 162, 162, 160, 158, 160, 153, 158, 156, 156, 153, 158, 155, 155, 155,
-  158, 156, 158, 162, 160, 160, 158, 160, 160, 158, 162, 160, 156, 155, 158, 155,
-  94, 96, 101, 86, 91, 96, 89, 91, 91, 91, 79, 84, 76, 98, 119, 131,
-  145, 149, 158, 172, 177, 179, 181, 176, 179, 174, 179, 172, 162, 155, 139, 110,
-  91, 60, 57, 60, 76, 84, 91, 89, 98, 89, 89, 89, 98, 98, 98, 98,
-  91, 96, 91, 94, 91, 101, 94, 110, 112, 110, 103, 105, 117, 108, 112, 117,
-  123, 117, 110, 121, 125, 158, 103, 117, 98, 131, 135, 123, 145, 125, 119, 123,
-  89, 57, 26, 71, 32, 18, 60, 63, 20, 35, 38, 29, 15, 43, 98, 26,
-  49, 86, 46, 20, 41, 43, 23, 52, 52, 60, 35, 38, 26, 49, 76, 52,
-  9, 9, 29, 137, 89, 162, 133, 103, 133, 184, 167, 160, 171, 189, 198, 193,
-  200, 193, 169, 121, 177, 197, 201, 184, 171, 160, 162, 155, 155, 153, 165, 162,
-  171, 174, 171, 177, 177, 179, 184, 184, 197, 198, 201, 198, 203, 200, 203, 204,
-  206, 206, 209, 210, 215, 215, 216, 215, 215, 213, 207, 181, 141, 96, 86, 63,
-  35, 23, 23, 18, 66, 52, 169, 181, 103, 55, 60, 32, 52, 35, 46, 43,
-  60, 57, 46, 52, 49, 38, 32, 41, 35, 35, 43, 35, 23, 32, 60, 119,
-  141, 149, 141, 131, 147, 172, 171, 172, 172, 171, 172, 172, 167, 167, 174, 176,
-  165, 172, 171, 169, 167, 165, 160, 162, 162, 149, 151, 155, 160, 156, 156, 149,
-  151, 149, 156, 149, 153, 156, 160, 160, 158, 158, 160, 162, 160, 156, 156, 155,
-  91, 96, 89, 94, 101, 91, 94, 86, 89, 101, 89, 79, 79, 86, 112, 127,
-  141, 153, 165, 179, 179, 176, 179, 176, 179, 184, 177, 172, 158, 155, 135, 108,
-  86, 66, 71, 68, 68, 79, 84, 91, 96, 84, 96, 89, 101, 96, 101, 98,
-  98, 91, 94, 96, 98, 98, 96, 98, 110, 112, 108, 98, 98, 101, 103, 96,
-  89, 91, 125, 151, 74, 74, 119, 94, 131, 119, 127, 131, 121, 131, 123, 94,
-  68, 26, 32, 89, 18, 15, 81, 63, 23, 103, 23, 43, 15, 18, 38, 71,
-  110, 49, 41, 18, 43, 26, 20, 84, 26, 26, 46, 41, 29, 26, 103, 96,
-  9, 6, 12, 52, 155, 131, 108, 137, 198, 160, 167, 164, 167, 179, 195, 195,
-  197, 197, 187, 153, 182, 198, 174, 174, 169, 156, 156, 165, 164, 156, 162, 160,
-  169, 172, 176, 177, 176, 182, 179, 187, 193, 195, 200, 201, 200, 198, 204, 200,
-  207, 206, 206, 207, 210, 210, 213, 213, 216, 210, 207, 193, 153, 105, 76, 63,
-  35, 15, 23, 23, 41, 55, 158, 182, 135, 79, 41, 26, 20, 46, 35, 46,
-  41, 63, 55, 57, 46, 35, 20, 35, 32, 46, 43, 38, 23, 35, 81, 129,
-  147, 149, 141, 137, 153, 167, 171, 174, 169, 169, 167, 167, 165, 169, 171, 174,
-  172, 169, 176, 172, 167, 167, 164, 162, 160, 155, 153, 155, 160, 158, 156, 153,
-  155, 151, 151, 151, 147, 147, 153, 155, 156, 164, 164, 156, 158, 158, 155, 153,
-  94, 94, 96, 91, 86, 91, 96, 84, 89, 89, 96, 71, 76, 94, 112, 133,
-  145, 160, 167, 176, 172, 176, 179, 177, 182, 182, 174, 172, 160, 147, 131, 105,
-  86, 74, 52, 66, 74, 68, 89, 84, 94, 94, 94, 91, 89, 86, 98, 91,
-  86, 96, 91, 94, 101, 101, 103, 101, 108, 112, 112, 112, 110, 110, 108, 114,
-  119, 119, 149, 52, 91, 153, 137, 94, 121, 114, 123, 137, 131, 119, 123, 108,
-  74, 26, 101, 71, 18, 15, 91, 89, 52, 35, 20, 23, 52, 43, 63, 119,
-  41, 41, 12, 32, 46, 20, 15, 114, 15, 26, 94, 43, 46, 26, 131, 20,
-  23, 12, 26, 131, 123, 86, 121, 195, 167, 169, 171, 160, 165, 174, 198, 203,
-  193, 197, 193, 182, 195, 181, 176, 176, 153, 162, 171, 164, 165, 162, 164, 169,
-  174, 184, 176, 177, 179, 179, 174, 179, 192, 193, 197, 201, 198, 200, 197, 197,
-  204, 204, 206, 207, 207, 212, 210, 215, 213, 212, 209, 201, 162, 105, 84, 71,
-  35, 15, 26, 20, 35, 57, 123, 177, 153, 86, 43, 32, 46, 68, 52, 55,
-  49, 46, 63, 57, 49, 46, 29, 43, 29, 38, 38, 38, 26, 38, 108, 143,
-  145, 143, 131, 145, 158, 171, 169, 171, 171, 172, 167, 174, 171, 169, 167, 172,
-  172, 174, 176, 176, 174, 169, 167, 167, 165, 160, 158, 158, 158, 158, 155, 151,
-  155, 149, 153, 155, 151, 153, 149, 149, 153, 156, 158, 158, 158, 156, 155, 156,
-  91, 94, 89, 91, 96, 89, 94, 86, 76, 86, 81, 81, 81, 91, 112, 131,
-  143, 156, 167, 174, 177, 172, 176, 181, 184, 182, 182, 177, 160, 153, 135, 108,
-  94, 74, 52, 68, 68, 76, 86, 84, 94, 86, 84, 89, 86, 96, 101, 89,
-  89, 91, 94, 86, 96, 101, 103, 105, 105, 114, 103, 108, 112, 114, 114, 114,
-  112, 108, 174, 141, 127, 131, 193, 151, 108, 117, 131, 133, 119, 110, 125, 81,
-  23, 43, 94, 52, 20, 15, 79, 101, 41, 6, 41, 15, 41, 79, 117, 76,
-  60, 35, 26, 26, 52, 35, 26, 121, 18, 12, 105, 43, 15, 96, 20, 35,
-  32, 15, 103, 158, 79, 98, 189, 181, 174, 182, 181, 172, 167, 176, 197, 200,
-  197, 200, 193, 192, 185, 182, 145, 129, 145, 149, 158, 160, 164, 164, 177, 167,
-  177, 179, 179, 182, 184, 182, 179, 184, 187, 189, 193, 198, 198, 198, 200, 197,
-  200, 203, 206, 207, 203, 210, 213, 215, 215, 209, 209, 200, 165, 119, 84, 49,
-  26, 15, 18, 32, 38, 49, 129, 184, 155, 66, 57, 41, 52, 71, 60, 32,
-  46, 52, 60, 52, 38, 32, 38, 29, 38, 57, 43, 29, 43, 68, 121, 141,
-  143, 139, 133, 153, 164, 171, 174, 169, 172, 171, 172, 167, 171, 171, 172, 169,
-  172, 169, 179, 176, 172, 172, 171, 164, 164, 165, 164, 158, 162, 156, 160, 156,
-  153, 153, 153, 153, 147, 153, 147, 147, 145, 149, 149, 149, 149, 156, 158, 156,
-  98, 98, 108, 89, 89, 89, 86, 89, 89, 89, 84, 84, 71, 96, 105, 135,
-  131, 158, 167, 176, 176, 176, 177, 177, 177, 177, 174, 171, 165, 147, 135, 110,
-  81, 68, 55, 68, 74, 66, 76, 86, 86, 89, 91, 105, 94, 89, 94, 96,
-  91, 96, 98, 98, 94, 94, 103, 103, 101, 112, 105, 114, 110, 108, 105, 117,
-  176, 158, 165, 26, 43, 49, 74, 112, 133, 129, 131, 123, 105, 125, 108, 29,
-  35, 94, 131, 9, 20, 32, 94, 112, 12, 12, 43, 38, 68, 55, 35, 63,
-  18, 15, 23, 26, 35, 43, 35, 63, 12, 29, 110, 49, 15, 117, 60, 49,
-  12, 57, 164, 112, 94, 177, 193, 174, 177, 185, 181, 160, 153, 172, 192, 201,
-  200, 200, 201, 192, 179, 63, 66, 110, 117, 133, 139, 145, 155, 158, 172, 176,
-  171, 182, 182, 182, 181, 174, 179, 181, 182, 184, 192, 200, 203, 198, 198, 192,
-  198, 201, 203, 207, 204, 207, 212, 210, 212, 207, 204, 192, 162, 117, 49, 32,
-  29, 23, 23, 29, 20, 81, 94, 184, 160, 94, 57, 38, 55, 49, 74, 52,
-  52, 57, 84, 57, 41, 32, 43, 32, 38, 52, 29, 38, 35, 84, 133, 145,
-  143, 133, 139, 155, 167, 171, 165, 164, 167, 171, 165, 167, 167, 171, 165, 169,
-  172, 174, 171, 176, 171, 174, 167, 165, 165, 165, 164, 164, 162, 160, 164, 156,
-  156, 155, 156, 155, 155, 153, 153, 147, 149, 153, 153, 149, 151, 143, 149, 147,
-  86, 96, 91, 94, 94, 94, 89, 96, 94, 89, 84, 89, 79, 91, 108, 133,
-  145, 155, 165, 167, 177, 179, 181, 179, 179, 181, 177, 176, 164, 151, 137, 117,
-  91, 84, 57, 63, 76, 68, 79, 81, 84, 91, 101, 94, 98, 105, 94, 91,
-  96, 91, 94, 89, 98, 91, 96, 101, 101, 114, 112, 110, 114, 114, 108, 181,
-  207, 103, 76, 18, 12, 18, 15, 151, 156, 182, 114, 101, 94, 101, 32, 35,
-  91, 57, 98, 15, 23, 49, 143, 110, 6, 26, 23, 26, 35, 49, 35, 46,
-  23, 23, 41, 43, 35, 41, 26, 60, 18, 43, 68, 46, 38, 63, 15, 6,
-  26, 145, 131, 81, 147, 201, 171, 181, 187, 200, 181, 165, 164, 182, 198, 203,
-  206, 201, 200, 127, 68, 76, 89, 94, 79, 98, 94, 91, 110, 119, 141, 164,
-  177, 182, 185, 182, 179, 179, 176, 176, 177, 189, 190, 198, 197, 197, 192, 195,
-  200, 193, 198, 203, 203, 204, 209, 209, 209, 201, 182, 169, 131, 94, 46, 35,
-  18, 15, 18, 23, 26, 94, 46, 193, 164, 125, 32, 35, 63, 66, 38, 41,
-  60, 63, 66, 46, 41, 35, 32, 35, 38, 41, 32, 35, 46, 101, 139, 145,
-  139, 131, 147, 158, 171, 167, 167, 167, 164, 165, 169, 167, 167, 165, 164, 162,
-  167, 167, 172, 169, 171, 174, 172, 169, 162, 165, 167, 164, 169, 165, 160, 162,
-  158, 155, 158, 155, 158, 153, 147, 153, 145, 147, 147, 149, 143, 145, 143, 141,
-  91, 96, 96, 91, 98, 91, 98, 86, 91, 91, 81, 86, 76, 86, 108, 127,
-  145, 155, 160, 169, 176, 176, 179, 179, 179, 181, 181, 172, 165, 155, 139, 108,
-  84, 66, 66, 68, 79, 74, 91, 89, 91, 96, 91, 91, 94, 98, 98, 101,
-  94, 94, 98, 91, 96, 96, 96, 112, 108, 108, 108, 117, 114, 114, 119, 181,
-  184, 98, 35, 23, 15, 23, 76, 145, 189, 201, 121, 74, 52, 68, 35, 55,
-  101, 141, 23, 26, 20, 89, 133, 123, 9, 26, 12, 35, 52, 63, 52, 68,
-  43, 23, 46, 32, 23, 29, 55, 105, 57, 52, 29, 76, 29, 29, 20, 15,
-  125, 165, 81, 125, 193, 171, 179, 184, 200, 204, 174, 164, 164, 190, 197, 203,
-  204, 195, 119, 117, 135, 137, 139, 123, 112, 103, 81, 46, 55, 60, 76, 103,
-  141, 165, 179, 177, 177, 182, 182, 174, 172, 181, 189, 197, 197, 198, 192, 192,
-  195, 197, 198, 206, 203, 204, 209, 203, 193, 171, 139, 119, 96, 71, 43, 38,
-  18, 15, 20, 23, 29, 71, 35, 184, 177, 135, 29, 26, 46, 68, 46, 55,
-  52, 52, 43, 49, 32, 26, 46, 29, 49, 35, 35, 35, 63, 110, 139, 141,
-  141, 131, 151, 162, 177, 171, 165, 167, 167, 164, 164, 167, 164, 167, 162, 165,
-  167, 167, 169, 169, 171, 169, 171, 164, 158, 162, 165, 167, 164, 165, 162, 164,
-  158, 164, 160, 160, 153, 156, 158, 155, 155, 149, 149, 145, 147, 143, 139, 139,
-  98, 91, 94, 96, 98, 86, 91, 98, 94, 94, 89, 81, 71, 84, 108, 127,
-  141, 156, 169, 174, 179, 171, 179, 177, 182, 179, 176, 174, 162, 147, 141, 119,
-  91, 60, 63, 74, 76, 74, 76, 79, 84, 94, 108, 89, 94, 86, 91, 84,
-  94, 89, 96, 89, 91, 96, 101, 105, 105, 101, 110, 117, 119, 125, 131, 135,
-  155, 151, 55, 29, 12, 26, 68, 141, 147, 79, 105, 43, 63, 79, 35, 57,
-  76, 81, 32, 41, 63, 89, 52, 139, 12, 20, 20, 76, 57, 26, 91, 38,
-  84, 18, 52, 20, 23, 9, 23, 76, 84, 117, 15, 91, 32, 15, 18, 74,
-  167, 110, 114, 198, 172, 176, 185, 197, 206, 189, 164, 162, 179, 197, 201, 206,
-  189, 110, 125, 143, 151, 151, 143, 162, 149, 141, 114, 86, 68, 63, 49, 35,
-  66, 94, 151, 172, 172, 174, 167, 171, 177, 176, 189, 189, 195, 195, 193, 187,
-  197, 198, 193, 198, 190, 192, 176, 147, 112, 81, 79, 60, 76, 84, 74, 71,
-  29, 23, 26, 26, 29, 52, 29, 182, 169, 139, 55, 38, 38, 74, 57, 57,
-  57, 55, 43, 23, 41, 35, 32, 23, 43, 43, 35, 32, 71, 137, 145, 139,
-  129, 137, 155, 172, 165, 171, 167, 167, 167, 165, 164, 162, 165, 169, 164, 162,
-  160, 165, 167, 171, 167, 171, 171, 160, 164, 165, 162, 165, 165, 164, 169, 162,
-  165, 162, 164, 162, 160, 164, 156, 153, 151, 155, 153, 147, 151, 139, 141, 141,
-  94, 89, 94, 89, 101, 105, 96, 89, 96, 86, 91, 81, 74, 86, 108, 125,
-  147, 153, 162, 174, 177, 172, 181, 177, 176, 181, 182, 176, 162, 155, 137, 121,
-  84, 63, 66, 74, 74, 68, 81, 86, 91, 91, 96, 96, 96, 86, 94, 86,
-  79, 94, 86, 96, 98, 98, 98, 96, 91, 103, 114, 117, 141, 156, 143, 141,
-  137, 129, 29, 49, 55, 15, 79, 131, 141, 63, 63, 105, 57, 41, 52, 108,
-  96, 26, 35, 41, 123, 76, 29, 151, 26, 20, 18, 66, 55, 32, 26, 43,
-  96, 46, 29, 12, 20, 18, 18, 32, 91, 145, 12, 74, 18, 6, 38, 151,
-  153, 105, 176, 192, 171, 184, 193, 207, 206, 177, 160, 177, 195, 203, 209, 169,
-  101, 127, 125, 131, 145, 147, 108, 141, 164, 153, 121, 135, 74, 74, 71, 63,
-  66, 60, 84, 131, 167, 167, 169, 169, 174, 177, 184, 187, 195, 193, 193, 190,
-  190, 193, 189, 190, 171, 141, 89, 79, 94, 76, 98, 96, 137, 114, 105, 84,
-  41, 38, 18, 15, 20, 52, 32, 179, 171, 137, 81, 41, 43, 68, 46, 49,
-  49, 57, 41, 35, 29, 29, 38, 46, 43, 46, 43, 38, 91, 137, 143, 137,
-  129, 145, 160, 167, 172, 164, 167, 171, 164, 164, 162, 164, 162, 162, 162, 164,
-  162, 160, 162, 165, 167, 165, 165, 162, 167, 160, 167, 162, 162, 162, 165, 165,
-  162, 165, 165, 160, 160, 158, 164, 158, 155, 153, 153, 149, 149, 143, 143, 141,
-  89, 101, 91, 91, 103, 89, 94, 91, 91, 89, 89, 79, 68, 84, 105, 121,
-  145, 153, 165, 176, 177, 177, 176, 182, 181, 184, 185, 176, 162, 156, 137, 117,
-  89, 68, 55, 76, 76, 79, 98, 84, 96, 98, 94, 89, 94, 89, 91, 89,
-  86, 94, 84, 86, 89, 94, 98, 98, 103, 98, 101, 143, 156, 156, 151, 145,
-  137, 193, 129, 105, 145, 71, 103, 125, 147, 119, 46, 76, 32, 32, 63, 117,
-  105, 52, 60, 91, 103, 15, 15, 123, 60, 32, 23, 84, 32, 18, 23, 35,
-  103, 89, 18, 20, 18, 29, 15, 20, 29, 46, 101, 18, 18, 12, 131, 158,
-  103, 165, 201, 169, 177, 193, 200, 207, 197, 171, 167, 192, 203, 210, 137, 84,
-  103, 103, 110, 121, 108, 125, 68, 79, 149, 135, 81, 119, 68, 108, 103, 89,
-  86, 89, 91, 114, 149, 153, 155, 165, 165, 172, 187, 187, 195, 197, 197, 193,
-  193, 190, 174, 174, 129, 103, 91, 110, 123, 86, 105, 112, 103, 79, 63, 71,
-  38, 68, 29, 32, 20, 63, 23, 164, 177, 135, 89, 35, 38, 46, 35, 60,
-  55, 55, 35, 46, 32, 32, 35, 35, 41, 26, 46, 57, 117, 139, 145, 135,
-  129, 145, 164, 167, 165, 167, 165, 164, 165, 164, 160, 162, 162, 162, 160, 158,
-  165, 160, 165, 164, 164, 167, 169, 165, 164, 167, 162, 165, 162, 160, 162, 162,
-  165, 165, 165, 164, 167, 164, 160, 156, 160, 160, 156, 153, 149, 145, 145, 141,
-  81, 94, 91, 94, 96, 94, 89, 94, 91, 89, 86, 68, 63, 84, 108, 121,
-  143, 153, 164, 174, 179, 181, 174, 177, 181, 177, 179, 174, 164, 155, 139, 112,
-  94, 63, 55, 63, 71, 68, 81, 81, 86, 91, 98, 91, 91, 89, 86, 86,
-  86, 98, 76, 89, 96, 86, 96, 98, 105, 121, 133, 141, 149, 160, 155, 149,
-  147, 193, 190, 172, 169, 139, 98, 68, 81, 35, 55, 20, 35, 76, 103, 139,
-  20, 84, 79, 108, 98, 12, 12, 86, 117, 32, 29, 81, 29, 32, 15, 41,
-  96, 117, 38, 32, 23, 23, 35, 29, 20, 29, 23, 52, 6, 49, 167, 98,
-  125, 206, 169, 172, 184, 200, 207, 212, 189, 176, 181, 198, 212, 101, 74, 89,
-  89, 91, 60, 52, 68, 68, 29, 35, 101, 60, 23, 52, 76, 119, 66, 121,
-  117, 103, 105, 112, 127, 143, 155, 160, 155, 167, 176, 193, 197, 203, 200, 193,
-  192, 195, 171, 141, 135, 127, 119, 71, 57, 29, 35, 43, 43, 55, 49, 49,
-  55, 49, 29, 15, 26, 68, 20, 164, 185, 117, 105, 26, 29, 52, 49, 57,
-  57, 41, 32, 29, 26, 26, 32, 41, 41, 26, 35, 86, 129, 143, 143, 129,
-  137, 160, 167, 164, 162, 165, 167, 158, 160, 162, 164, 162, 164, 160, 158, 160,
-  164, 164, 164, 165, 165, 165, 164, 165, 165, 162, 164, 158, 162, 162, 165, 164,
-  167, 162, 164, 165, 162, 156, 155, 153, 158, 155, 156, 155, 153, 147, 145, 143,
-  89, 98, 94, 94, 91, 86, 86, 89, 94, 86, 89, 79, 68, 81, 110, 129,
-  143, 153, 160, 169, 177, 179, 177, 187, 179, 182, 181, 174, 164, 155, 137, 119,
-  94, 71, 74, 57, 63, 74, 81, 84, 89, 89, 89, 94, 91, 94, 89, 84,
-  89, 81, 98, 86, 89, 86, 89, 141, 149, 162, 143, 143, 149, 156, 151, 147,
-  151, 153, 117, 114, 158, 121, 20, 23, 12, 20, 57, 76, 76, 84, 151, 60,
-  46, 74, 74, 117, 68, 26, 23, 96, 79, 26, 20, 101, 29, 18, 12, 35,
-  49, 139, 105, 32, 15, 26, 43, 29, 18, 15, 23, 15, 23, 156, 135, 94,
-  197, 174, 176, 182, 195, 207, 209, 203, 197, 192, 200, 210, 84, 66, 60, 52,
-  43, 41, 35, 38, 26, 26, 35, 35, 29, 23, 23, 15, 18, 49, 101, 137,
-  119, 110, 121, 110, 131, 141, 147, 156, 158, 169, 181, 195, 197, 200, 201, 201,
-  197, 187, 155, 112, 89, 60, 23, 32, 41, 26, 26, 20, 38, 35, 46, 57,
-  60, 20, 32, 15, 15, 66, 20, 165, 184, 127, 112, 76, 32, 49, 66, 55,
-  63, 49, 26, 35, 43, 29, 32, 43, 41, 18, 29, 96, 139, 147, 139, 139,
-  143, 156, 164, 167, 164, 165, 164, 162, 162, 162, 160, 164, 171, 162, 160, 164,
-  162, 160, 164, 164, 167, 169, 167, 158, 156, 162, 162, 156, 164, 164, 158, 158,
-  164, 165, 162, 162, 162, 164, 153, 158, 155, 155, 155, 151, 151, 149, 149, 149,
-  91, 101, 96, 84, 91, 91, 84, 86, 81, 94, 84, 74, 66, 66, 101, 127,
-  141, 156, 167, 171, 176, 176, 182, 181, 181, 179, 176, 172, 160, 149, 139, 114,
-  89, 84, 60, 57, 68, 71, 74, 74, 96, 81, 101, 86, 86, 86, 89, 86,
-  86, 91, 76, 76, 76, 81, 117, 165, 210, 197, 133, 145, 151, 149, 153, 153,
-  156, 149, 108, 55, 74, 103, 15, 18, 15, 55, 125, 89, 74, 112, 96, 101,
-  60, 112, 66, 135, 81, 20, 18, 98, 18, 84, 29, 94, 26, 26, 12, 15,
-  9, 41, 129, 123, 55, 18, 15, 32, 38, 9, 29, 9, 89, 181, 96, 160,
-  203, 171, 185, 189, 192, 207, 204, 203, 198, 195, 207, 84, 43, 57, 23, 38,
-  26, 29, 41, 20, 29, 23, 23, 35, 55, 68, 32, 20, 18, 29, 23, 103,
-  133, 121, 125, 117, 119, 139, 141, 143, 155, 164, 182, 193, 200, 201, 206, 206,
-  192, 162, 79, 41, 46, 38, 41, 41, 43, 23, 32, 29, 35, 60, 32, 46,
-  26, 26, 29, 29, 26, 66, 23, 156, 187, 133, 103, 63, 68, 38, 49, 49,
-  55, 35, 26, 29, 38, 26, 41, 32, 41, 23, 23, 105, 149, 145, 137, 139,
-  155, 171, 169, 171, 162, 164, 167, 158, 165, 160, 160, 158, 158, 155, 167, 162,
-  158, 158, 164, 158, 164, 164, 162, 162, 162, 162, 165, 162, 160, 162, 164, 164,
-  160, 162, 160, 158, 160, 153, 160, 153, 156, 153, 151, 153, 153, 153, 147, 145,
-  84, 81, 91, 81, 81, 81, 84, 79, 86, 89, 79, 63, 60, 68, 103, 121,
-  141, 151, 169, 174, 176, 179, 177, 181, 177, 181, 181, 172, 162, 153, 133, 117,
-  86, 63, 63, 57, 71, 76, 74, 79, 89, 86, 84, 94, 81, 79, 86, 81,
-  89, 84, 74, 71, 66, 103, 213, 181, 216, 131, 137, 139, 143, 149, 158, 147,
-  139, 147, 86, 32, 74, 26, 9, 12, 41, 141, 94, 26, 81, 105, 43, 91,
-  74, 84, 76, 162, 74, 18, 38, 81, 23, 49, 81, 101, 63, 29, 35, 15,
-  23, 23, 57, 129, 119, 76, 20, 18, 18, 12, 12, 35, 153, 108, 127, 209,
-  172, 174, 182, 195, 203, 212, 201, 197, 206, 206, 81, 57, 38, 49, 26, 35,
-  23, 23, 23, 26, 20, 26, 26, 60, 147, 160, 103, 41, 18, 20, 20, 52,
-  110, 131, 121, 119, 127, 129, 137, 145, 149, 160, 182, 192, 207, 207, 212, 207,
-  165, 35, 43, 29, 43, 32, 43, 76, 129, 86, 23, 20, 32, 29, 38, 41,
-  23, 38, 35, 20, 29, 74, 18, 155, 192, 155, 89, 63, 52, 55, 71, 46,
-  46, 29, 29, 32, 29, 32, 43, 35, 41, 29, 55, 127, 151, 143, 143, 141,
-  160, 167, 165, 165, 164, 162, 165, 160, 158, 160, 155, 160, 162, 160, 160, 167,
-  165, 158, 158, 165, 164, 160, 164, 160, 164, 158, 165, 162, 160, 167, 162, 160,
-  160, 160, 160, 160, 158, 155, 153, 155, 153, 149, 149, 145, 149, 145, 145, 143,
-  84, 91, 89, 84, 81, 86, 79, 79, 79, 76, 63, 84, 60, 68, 94, 125,
-  139, 155, 164, 176, 179, 177, 177, 182, 179, 179, 181, 172, 164, 151, 139, 117,
-  89, 71, 55, 57, 68, 74, 84, 76, 86, 84, 86, 91, 89, 89, 84, 89,
-  81, 79, 74, 71, 63, 131, 203, 193, 189, 114, 133, 143, 151, 155, 155, 91,
-  127, 129, 74, 81, 26, 15, 32, 26, 141, 98, 15, 43, 131, 18, 9, 52,
-  112, 98, 105, 131, 46, 32, 26, 57, 20, 32, 26, 74, 105, 32, 32, 29,
-  35, 23, 35, 52, 26, 57, 91, 29, 15, 9, 12, 117, 165, 86, 184, 185,
-  172, 187, 182, 192, 210, 209, 203, 207, 206, 103, 68, 74, 49, 23, 15, 32,
-  49, 49, 23, 41, 15, 20, 84, 84, 182, 210, 185, 167, 55, 20, 63, 41,
-  98, 121, 110, 108, 129, 133, 141, 141, 151, 164, 169, 197, 209, 218, 216, 189,
-  71, 29, 23, 35, 26, 35, 162, 57, 171, 139, 66, 20, 20, 38, 35, 41,
-  23, 26, 35, 15, 20, 74, 12, 147, 190, 153, 84, 86, 55, 55, 57, 46,
-  49, 32, 23, 32, 38, 46, 32, 29, 26, 29, 94, 133, 151, 145, 139, 149,
-  164, 167, 164, 165, 165, 164, 165, 160, 158, 162, 158, 158, 155, 160, 162, 160,
-  158, 158, 165, 153, 158, 158, 162, 160, 158, 160, 156, 164, 164, 160, 162, 156,
-  156, 162, 160, 156, 153, 149, 147, 149, 147, 153, 141, 141, 143, 141, 145, 145,
-  89, 94, 86, 81, 94, 86, 79, 86, 79, 71, 66, 71, 52, 68, 103, 131,
-  135, 155, 165, 179, 176, 184, 179, 179, 181, 179, 182, 182, 160, 153, 135, 119,
-  86, 60, 57, 68, 74, 84, 89, 91, 81, 91, 94, 79, 86, 86, 96, 96,
-  84, 79, 81, 71, 66, 81, 200, 197, 187, 147, 135, 147, 149, 149, 153, 98,
-  155, 129, 29, 74, 32, 20, 66, 119, 46, 32, 46, 110, 57, 20, 20, 81,
-  143, 84, 84, 119, 38, 29, 32, 26, 12, 38, 26, 41, 153, 38, 38, 15,
-  18, 26, 26, 35, 23, 26, 55, 23, 29, 63, 43, 156, 94, 147, 209, 171,
-  190, 193, 193, 200, 213, 207, 209, 212, 127, 84, 74, 46, 38, 32, 20, 38,
-  86, 81, 43, 91, 23, 23, 119, 38, 164, 207, 201, 200, 149, 49, 79, 101,
-  74, 114, 105, 101, 123, 129, 129, 131, 149, 165, 182, 201, 221, 222, 209, 110,
-  52, 35, 60, 43, 18, 43, 103, 60, 185, 167, 86, 41, 26, 68, 23, 49,
-  35, 26, 23, 18, 15, 96, 18, 141, 181, 155, 68, 103, 55, 66, 52, 46,
-  41, 29, 29, 55, 26, 38, 26, 26, 38, 57, 110, 145, 145, 149, 145, 160,
-  172, 162, 160, 160, 164, 164, 160, 160, 160, 160, 156, 158, 158, 160, 158, 160,
-  156, 162, 158, 156, 160, 158, 153, 165, 158, 160, 158, 160, 155, 156, 155, 153,
-  158, 156, 158, 153, 149, 153, 151, 149, 145, 137, 141, 143, 141, 139, 135, 141,
-  89, 91, 91, 79, 94, 81, 84, 84, 81, 74, 74, 63, 55, 68, 103, 127,
-  137, 153, 169, 176, 179, 179, 179, 184, 185, 184, 182, 177, 164, 151, 137, 117,
-  98, 68, 52, 57, 76, 86, 79, 91, 91, 91, 94, 86, 98, 91, 105, 86,
-  94, 81, 86, 76, 23, 66, 197, 74, 117, 200, 187, 149, 147, 153, 137, 84,
-  114, 52, 20, 23, 12, 43, 129, 71, 18, 46, 86, 32, 74, 32, 32, 57,
-  137, 71, 108, 119, 29, 35, 23, 32, 29, 26, 20, 32, 135, 63, 23, 26,
-  23, 26, 35, 26, 15, 18, 26, 20, 18, 29, 108, 114, 103, 198, 176, 156,
-  156, 181, 198, 210, 212, 201, 209, 158, 94, 108, 98, 68, 68, 41, 12, 43,
-  86, 123, 55, 81, 79, 91, 57, 55, 207, 212, 216, 212, 189, 101, 49, 119,
-  74, 103, 96, 108, 110, 123, 131, 135, 155, 164, 187, 203, 218, 216, 176, 74,
-  101, 41, 94, 86, 49, 110, 60, 79, 182, 158, 112, 41, 18, 20, 20, 26,
-  26, 15, 32, 18, 23, 98, 18, 127, 182, 160, 68, 105, 68, 91, 35, 60,
-  29, 26, 35, 38, 38, 38, 38, 35, 38, 63, 121, 147, 147, 139, 145, 158,
-  165, 167, 169, 162, 162, 167, 162, 160, 164, 155, 162, 156, 155, 158, 158, 158,
-  158, 162, 156, 156, 162, 160, 158, 158, 158, 156, 155, 158, 155, 156, 155, 155,
-  155, 158, 149, 153, 149, 149, 145, 139, 141, 139, 131, 141, 137, 147, 153, 160,
-  98, 89, 91, 89, 91, 91, 101, 84, 84, 76, 68, 63, 49, 66, 94, 123,
-  141, 156, 165, 172, 182, 181, 179, 185, 184, 185, 182, 179, 165, 151, 133, 117,
-  91, 76, 52, 71, 66, 74, 86, 86, 91, 98, 91, 91, 98, 79, 101, 98,
-  108, 105, 57, 49, 29, 20, 167, 114, 147, 182, 216, 213, 185, 160, 35, 20,
-  20, 32, 18, 32, 52, 98, 60, 41, 26, 57, 49, 41, 63, 43, 49, 86,
-  149, 91, 141, 125, 32, 35, 32, 29, 43, 29, 23, 18, 86, 74, 26, 32,
-  23, 23, 43, 29, 29, 20, 23, 32, 18, 52, 147, 74, 147, 176, 160, 181,
-  197, 203, 206, 207, 204, 209, 164, 94, 105, 121, 121, 110, 105, 91, 20, 23,
-  79, 112, 114, 49, 38, 41, 71, 172, 213, 213, 213, 203, 181, 127, 76, 119,
-  108, 101, 108, 105, 110, 117, 129, 135, 153, 169, 190, 216, 221, 221, 131, 98,
-  129, 119, 52, 105, 94, 74, 63, 169, 177, 155, 101, 52, 20, 38, 20, 20,
-  18, 23, 29, 18, 41, 105, 18, 105, 172, 162, 79, 91, 68, 84, 43, 41,
-  32, 55, 32, 32, 55, 38, 26, 29, 35, 86, 135, 155, 143, 141, 149, 160,
-  164, 167, 165, 164, 165, 162, 158, 160, 156, 158, 164, 156, 162, 158, 156, 160,
-  153, 164, 158, 155, 156, 160, 162, 164, 158, 156, 156, 151, 151, 155, 151, 158,
-  151, 155, 151, 143, 143, 143, 143, 139, 139, 137, 137, 143, 153, 158, 167, 176,
-  91, 101, 91, 86, 84, 91, 96, 84, 81, 81, 68, 63, 49, 71, 101, 119,
-  141, 155, 162, 174, 181, 181, 184, 184, 181, 182, 182, 177, 164, 155, 137, 112,
-  98, 76, 66, 63, 79, 84, 91, 89, 84, 101, 103, 96, 91, 86, 96, 91,
-  110, 38, 49, 26, 43, 79, 149, 155, 171, 187, 227, 246, 215, 38, 68, 20,
-  35, 15, 18, 35, 101, 74, 81, 89, 35, 55, 86, 66, 76, 101, 91, 101,
-  112, 66, 119, 147, 43, 23, 41, 29, 55, 23, 26, 20, 52, 43, 18, 55,
-  18, 18, 32, 35, 18, 32, 12, 26, 57, 143, 91, 98, 204, 153, 181, 185,
-  197, 203, 209, 207, 206, 167, 101, 110, 101, 117, 127, 125, 133, 112, 63, 52,
-  89, 112, 121, 123, 96, 119, 176, 203, 207, 210, 210, 204, 149, 141, 145, 96,
-  127, 103, 110, 114, 114, 121, 121, 127, 143, 171, 201, 221, 225, 213, 123, 84,
-  127, 155, 114, 84, 66, 96, 167, 187, 177, 153, 96, 49, 43, 26, 20, 26,
-  41, 18, 43, 26, 38, 86, 32, 86, 174, 172, 96, 76, 84, 98, 66, 35,
-  38, 38, 35, 23, 41, 46, 38, 23, 35, 103, 143, 143, 143, 137, 155, 171,
-  165, 164, 160, 162, 164, 160, 162, 160, 158, 158, 160, 156, 172, 164, 164, 162,
-  165, 162, 162, 165, 160, 160, 164, 160, 155, 162, 160, 158, 160, 155, 153, 149,
-  149, 147, 149, 149, 143, 141, 141, 135, 137, 143, 153, 160, 171, 172, 179, 190,
-  89, 86, 96, 91, 86, 94, 91, 79, 79, 81, 79, 55, 60, 68, 101, 121,
-  137, 155, 167, 177, 179, 181, 184, 184, 185, 184, 184, 177, 165, 153, 131, 123,
-  91, 74, 74, 66, 79, 71, 89, 91, 96, 101, 91, 101, 96, 125, 43, 26,
-  18, 35, 68, 123, 137, 155, 171, 195, 160, 221, 230, 147, 55, 38, 119, 26,
-  20, 29, 55, 127, 139, 114, 29, 32, 12, 60, 41, 89, 79, 55, 66, 112,
-  129, 26, 127, 145, 89, 71, 29, 18, 46, 15, 18, 35, 26, 23, 46, 43,
-  26, 29, 71, 26, 23, 20, 15, 23, 117, 153, 91, 181, 200, 169, 181, 195,
-  206, 210, 209, 203, 155, 86, 114, 117, 123, 121, 131, 145, 137, 139, 121, 96,
-  91, 52, 114, 135, 151, 156, 172, 184, 195, 201, 189, 167, 155, 137, 112, 105,
-  119, 117, 108, 110, 117, 121, 117, 137, 151, 174, 197, 224, 227, 209, 123, 91,
-  81, 114, 143, 141, 147, 167, 177, 182, 162, 119, 84, 26, 32, 46, 38, 32,
-  43, 35, 41, 35, 38, 84, 43, 89, 171, 187, 110, 84, 84, 66, 49, 35,
-  29, 29, 26, 35, 38, 43, 23, 29, 57, 123, 143, 141, 139, 145, 164, 165,
-  162, 160, 162, 160, 160, 160, 162, 160, 155, 158, 162, 160, 160, 171, 158, 160,
-  156, 160, 160, 162, 158, 155, 155, 155, 160, 153, 153, 153, 149, 156, 153, 151,
-  147, 143, 149, 147, 139, 143, 141, 145, 167, 167, 171, 181, 185, 189, 192, 197,
-  103, 98, 89, 96, 89, 103, 86, 79, 81, 71, 74, 60, 52, 63, 89, 123,
-  139, 153, 169, 174, 182, 181, 184, 189, 184, 185, 184, 182, 165, 156, 137, 117,
-  98, 74, 63, 74, 86, 86, 91, 98, 98, 108, 103, 103, 98, 182, 12, 9,
-  35, 66, 133, 164, 145, 158, 156, 171, 151, 185, 74, 46, 26, 15, 71, 94,
-  94, 123, 147, 84, 68, 86, 15, 18, 20, 98, 29, 103, 79, 74, 74, 96,
-  164, 74, 143, 119, 123, 43, 101, 26, 29, 20, 23, 29, 43, 32, 29, 20,
-  20, 26, 26, 15, 15, 18, 12, 43, 162, 79, 133, 209, 171, 177, 189, 198,
-  210, 210, 204, 147, 86, 105, 123, 114, 133, 129, 127, 137, 137, 137, 139, 112,
-  121, 123, 96, 94, 101, 117, 131, 156, 151, 165, 165, 167, 176, 174, 179, 147,
-  123, 121, 117, 112, 110, 117, 121, 135, 145, 172, 193, 222, 228, 206, 179, 171,
-  169, 133, 141, 139, 123, 155, 162, 137, 114, 79, 43, 23, 79, 66, 38, 29,
-  41, 18, 71, 41, 46, 68, 23, 79, 160, 190, 133, 66, 86, 66, 63, 35,
-  35, 35, 29, 18, 46, 43, 29, 46, 86, 125, 151, 137, 137, 145, 165, 165,
-  164, 164, 162, 158, 158, 162, 162, 156, 158, 156, 158, 160, 165, 189, 158, 156,
-  153, 164, 164, 160, 165, 162, 158, 155, 149, 156, 155, 149, 145, 155, 151, 143,
-  139, 149, 141, 143, 139, 143, 151, 171, 176, 182, 185, 190, 193, 193, 198, 198,
-  91, 96, 96, 98, 86, 98, 79, 74, 76, 68, 63, 68, 49, 55, 91, 119,
-  143, 155, 169, 177, 177, 182, 182, 189, 189, 182, 187, 179, 171, 160, 137, 123,
-  96, 71, 66, 68, 81, 94, 94, 91, 105, 103, 101, 96, 103, 177, 18, 35,
-  105, 137, 165, 156, 133, 127, 131, 177, 167, 55, 55, 63, 35, 32, 41, 127,
-  127, 43, 29, 66, 133, 20, 15, 26, 41, 98, 41, 79, 112, 29, 74, 112,
-  139, 117, 145, 101, 96, 141, 76, 15, 26, 26, 18, 20, 26, 29, 35, 18,
-  49, 29, 23, 18, 15, 15, 18, 133, 127, 81, 187, 182, 179, 187, 192, 203,
-  212, 209, 164, 68, 94, 119, 125, 127, 137, 133, 137, 137, 141, 135, 145, 135,
-  137, 125, 98, 123, 98, 127, 137, 141, 108, 119, 127, 155, 158, 165, 153, 133,
-  117, 108, 114, 125, 112, 119, 119, 133, 143, 165, 184, 219, 230, 210, 174, 162,
-  151, 143, 139, 125, 108, 108, 91, 81, 38, 38, 76, 74, 74, 68, 35, 23,
-  29, 9, 32, 49, 68, 79, 38, 68, 158, 198, 147, 79, 96, 79, 41, 23,
-  29, 41, 29, 38, 43, 41, 32, 57, 108, 135, 143, 139, 145, 151, 172, 171,
-  164, 165, 158, 160, 162, 160, 162, 158, 158, 155, 155, 155, 158, 160, 156, 156,
-  156, 156, 156, 164, 162, 158, 155, 155, 147, 151, 149, 149, 149, 149, 145, 143,
-  149, 141, 143, 145, 158, 162, 176, 182, 187, 193, 197, 197, 198, 198, 197, 197,
-  94, 98, 96, 101, 86, 98, 79, 79, 68, 74, 71, 57, 55, 49, 91, 123,
-  137, 155, 167, 172, 179, 185, 181, 187, 187, 185, 192, 181, 169, 156, 141, 125,
-  98, 76, 63, 68, 79, 84, 94, 103, 103, 108, 110, 96, 98, 143, 96, 121,
-  137, 123, 121, 149, 156, 114, 49, 84, 79, 86, 49, 32, 26, 32, 15, 55,
-  167, 137, 74, 141, 108, 74, 66, 43, 18, 81, 57, 71, 114, 74, 43, 121,
-  103, 129, 123, 121, 151, 127, 15, 35, 35, 23, 35, 35, 20, 35, 23, 23,
-  41, 35, 26, 20, 6, 15, 89, 169, 89, 110, 193, 169, 187, 187, 197, 209,
-  209, 172, 68, 79, 94, 119, 125, 125, 141, 133, 141, 147, 151, 145, 139, 139,
-  147, 139, 123, 131, 114, 123, 133, 125, 112, 147, 145, 153, 151, 149, 141, 151,
-  125, 110, 121, 123, 114, 123, 112, 125, 139, 160, 193, 218, 230, 215, 187, 160,
-  151, 139, 131, 119, 125, 121, 125, 112, 74, 84, 68, 91, 79, 68, 35, 38,
-  23, 9, 35, 32, 74, 79, 20, 74, 160, 197, 151, 91, 79, 52, 29, 41,
-  26, 29, 18, 49, 41, 43, 23, 76, 127, 143, 139, 133, 143, 167, 169, 160,
-  165, 162, 162, 158, 162, 160, 162, 160, 164, 158, 158, 162, 155, 158, 155, 162,
-  160, 158, 158, 155, 160, 155, 155, 156, 145, 156, 149, 147, 147, 149, 139, 143,
-  143, 137, 143, 162, 171, 182, 192, 195, 197, 200, 200, 201, 201, 200, 195, 195,
-  91, 94, 89, 91, 86, 86, 86, 81, 71, 76, 71, 55, 41, 63, 86, 112,
-  141, 151, 171, 176, 177, 179, 184, 187, 184, 189, 184, 184, 167, 160, 141, 125,
-  96, 63, 52, 66, 76, 84, 89, 91, 98, 98, 94, 94, 86, 110, 164, 137,
-  165, 169, 167, 125, 86, 74, 79, 57, 108, 79, 29, 32, 29, 41, 15, 41,
-  55, 164, 153, 139, 137, 137, 63, 41, 18, 35, 84, 57, 105, 112, 66, 89,
-  66, 123, 121, 147, 133, 89, 41, 26, 20, 23, 29, 23, 32, 32, 38, 29,
-  23, 20, 18, 26, 9, 26, 139, 131, 94, 174, 176, 179, 192, 190, 209, 212,
-  182, 55, 76, 101, 103, 119, 133, 133, 145, 145, 151, 153, 151, 147, 153, 145,
-  139, 141, 145, 137, 135, 137, 139, 149, 149, 151, 156, 164, 165, 158, 164, 151,
-  121, 119, 125, 129, 125, 119, 119, 117, 129, 164, 192, 213, 227, 215, 190, 181,
-  165, 156, 143, 135, 129, 129, 117, 119, 86, 94, 96, 94, 86, 81, 38, 46,
-  18, 18, 35, 32, 49, 60, 26, 63, 158, 193, 145, 94, 49, 68, 49, 41,
-  35, 32, 32, 60, 41, 29, 26, 71, 137, 141, 141, 135, 151, 167, 165, 167,
-  162, 156, 164, 160, 162, 155, 155, 156, 162, 158, 156, 156, 156, 153, 158, 153,
-  156, 162, 158, 158, 153, 151, 155, 155, 155, 151, 151, 151, 145, 141, 147, 139,
-  137, 145, 167, 182, 189, 193, 201, 201, 201, 203, 200, 198, 197, 200, 197, 197,
-  96, 91, 94, 79, 84, 79, 79, 79, 68, 74, 66, 43, 32, 38, 79, 127,
-  133, 147, 164, 174, 176, 181, 185, 185, 184, 187, 189, 177, 169, 158, 139, 125,
-  94, 63, 74, 66, 81, 79, 86, 98, 98, 101, 101, 96, 103, 98, 143, 165,
-  172, 137, 114, 110, 60, 52, 60, 110, 89, 41, 20, 18, 52, 49, 49, 57,
-  76, 101, 117, 114, 101, 66, 35, 20, 12, 52, 71, 63, 41, 127, 125, 71,
-  96, 108, 89, 160, 52, 94, 55, 35, 32, 29, 26, 29, 23, 29, 38, 32,
-  35, 32, 23, 12, 15, 103, 165, 89, 121, 197, 190, 187, 193, 206, 213, 200,
-  38, 66, 86, 101, 110, 121, 129, 135, 147, 151, 151, 149, 153, 162, 162, 156,
-  151, 149, 149, 151, 145, 158, 155, 165, 164, 165, 172, 169, 162, 167, 169, 139,
-  121, 123, 133, 127, 112, 119, 119, 119, 133, 158, 184, 209, 225, 219, 195, 190,
-  174, 165, 153, 153, 141, 125, 121, 119, 114, 98, 103, 108, 101, 89, 35, 43,
-  32, 23, 35, 46, 38, 79, 35, 60, 169, 197, 145, 98, 60, 71, 46, 26,
-  35, 23, 35, 46, 32, 20, 23, 103, 135, 143, 137, 131, 147, 164, 165, 162,
-  162, 160, 158, 164, 155, 162, 156, 158, 156, 156, 158, 160, 158, 156, 156, 160,
-  160, 156, 156, 160, 153, 151, 151, 155, 149, 151, 143, 151, 139, 143, 133, 133,
-  149, 174, 187, 198, 200, 201, 203, 203, 203, 201, 200, 198, 198, 200, 198, 198,
-  96, 84, 81, 76, 86, 71, 71, 66, 66, 74, 57, 52, 43, 43, 76, 117,
-  137, 155, 165, 172, 182, 181, 184, 182, 182, 184, 185, 181, 169, 156, 143, 121,
-  94, 81, 55, 63, 81, 84, 86, 105, 103, 101, 98, 108, 101, 98, 112, 129,
-  108, 98, 108, 66, 52, 66, 91, 101, 32, 49, 26, 35, 84, 60, 71, 110,
-  119, 117, 49, 35, 117, 84, 18, 23, 35, 26, 55, 91, 41, 46, 147, 162,
-  143, 98, 55, 71, 125, 149, 26, 29, 23, 20, 35, 26, 32, 29, 32, 55,
-  32, 35, 29, 29, 46, 149, 103, 91, 167, 177, 189, 198, 206, 216, 209, 49,
-  55, 84, 103, 105, 105, 125, 131, 129, 147, 149, 155, 147, 162, 167, 164, 164,
-  172, 172, 167, 165, 164, 162, 171, 176, 171, 177, 165, 174, 164, 177, 158, 133,
-  127, 139, 137, 127, 125, 117, 119, 114, 131, 167, 181, 210, 225, 219, 200, 189,
-  181, 164, 156, 153, 151, 135, 125, 125, 123, 108, 105, 101, 105, 84, 35, 43,
-  35, 35, 32, 52, 43, 52, 23, 49, 165, 193, 158, 96, 52, 81, 29, 32,
-  35, 18, 35, 46, 23, 23, 38, 110, 141, 141, 141, 139, 158, 165, 160, 160,
-  165, 158, 160, 160, 158, 160, 158, 160, 156, 158, 158, 156, 160, 156, 156, 158,
-  156, 155, 155, 156, 155, 158, 155, 151, 153, 151, 149, 145, 141, 141, 139, 153,
-  176, 187, 197, 203, 203, 204, 203, 201, 201, 201, 200, 198, 198, 200, 198, 198,
-  89, 81, 86, 74, 84, 71, 76, 63, 74, 68, 49, 49, 38, 57, 79, 112,
-  133, 155, 160, 169, 177, 182, 181, 184, 187, 182, 187, 179, 171, 164, 139, 123,
-  96, 74, 57, 68, 79, 86, 81, 94, 96, 105, 98, 105, 101, 108, 117, 91,
-  110, 145, 105, 114, 158, 156, 127, 52, 43, 32, 29, 38, 117, 68, 112, 125,
-  123, 94, 55, 117, 117, 32, 15, 20, 32, 46, 98, 139, 86, 52, 71, 84,
-  143, 76, 91, 123, 187, 49, 41, 35, 35, 35, 38, 46, 23, 26, 29, 29,
-  38, 29, 41, 18, 119, 162, 103, 133, 201, 187, 200, 197, 204, 215, 74, 49,
-  71, 86, 101, 114, 110, 117, 133, 131, 143, 145, 147, 155, 158, 172, 158, 160,
-  174, 182, 172, 162, 164, 164, 176, 176, 176, 167, 167, 176, 172, 164, 151, 137,
-  129, 135, 131, 123, 119, 123, 114, 114, 127, 147, 184, 204, 224, 221, 203, 184,
-  185, 174, 165, 151, 149, 137, 133, 133, 119, 114, 114, 119, 108, 89, 49, 38,
-  29, 26, 35, 41, 46, 66, 9, 41, 164, 189, 172, 112, 46, 71, 15, 41,
-  23, 29, 41, 41, 23, 26, 55, 117, 145, 139, 139, 145, 165, 172, 172, 164,
-  164, 164, 158, 155, 156, 160, 160, 158, 156, 156, 158, 156, 155, 153, 155, 156,
-  158, 156, 153, 153, 151, 147, 151, 147, 145, 149, 149, 143, 145, 137, 153, 176,
-  190, 198, 204, 207, 209, 204, 203, 201, 201, 201, 198, 197, 197, 198, 198, 200,
-  74, 84, 81, 74, 71, 74, 74, 76, 74, 66, 43, 35, 41, 49, 76, 108,
-  131, 149, 167, 176, 181, 179, 182, 182, 184, 182, 187, 179, 171, 156, 137, 123,
-  91, 79, 63, 63, 84, 84, 84, 84, 96, 96, 98, 105, 110, 133, 129, 145,
-  160, 177, 177, 164, 155, 108, 68, 49, 55, 66, 57, 52, 133, 63, 119, 123,
-  86, 117, 108, 123, 68, 23, 23, 18, 35, 32, 46, 96, 121, 103, 114, 91,
-  71, 165, 176, 169, 66, 112, 94, 76, 68, 15, 23, 35, 20, 35, 23, 32,
-  32, 29, 23, 63, 162, 103, 98, 169, 172, 197, 195, 206, 216, 135, 29, 52,
-  66, 96, 101, 110, 110, 119, 125, 135, 137, 149, 147, 155, 158, 165, 169, 169,
-  176, 177, 176, 177, 177, 177, 171, 172, 165, 177, 181, 181, 169, 155, 151, 143,
-  131, 133, 139, 129, 125, 119, 110, 108, 119, 153, 177, 204, 224, 227, 207, 187,
-  181, 177, 165, 147, 139, 139, 129, 133, 125, 117, 119, 114, 108, 101, 63, 32,
-  35, 32, 43, 29, 41, 46, 9, 35, 165, 177, 174, 125, 35, 46, 15, 57,
-  23, 23, 43, 32, 26, 26, 89, 133, 145, 141, 137, 153, 167, 164, 167, 164,
-  167, 158, 164, 162, 156, 164, 164, 156, 162, 158, 160, 160, 160, 156, 151, 155,
-  158, 153, 156, 155, 151, 151, 151, 149, 147, 145, 143, 143, 135, 153, 171, 192,
-  200, 203, 207, 206, 206, 204, 204, 200, 198, 201, 200, 198, 200, 200, 198, 201,
-  79, 81, 101, 76, 74, 74, 74, 71, 60, 55, 55, 41, 35, 52, 94, 119,
-  137, 153, 162, 171, 177, 181, 182, 182, 185, 187, 182, 181, 165, 156, 135, 127,
-  98, 68, 60, 71, 84, 74, 86, 89, 86, 105, 151, 169, 164, 160, 155, 156,
-  151, 147, 55, 41, 68, 89, 43, 46, 52, 57, 60, 79, 110, 68, 129, 76,
-  101, 137, 129, 86, 32, 23, 20, 20, 18, 23, 29, 57, 79, 66, 125, 135,
-  133, 114, 57, 38, 38, 143, 137, 98, 96, 29, 38, 38, 52, 32, 35, 29,
-  35, 23, 20, 119, 153, 96, 117, 201, 187, 197, 203, 218, 184, 26, 26, 57,
-  74, 103, 105, 110, 117, 112, 129, 135, 139, 143, 149, 155, 162, 165, 176, 174,
-  174, 184, 176, 169, 179, 179, 184, 179, 179, 176, 179, 179, 172, 164, 151, 141,
-  145, 139, 139, 135, 123, 121, 112, 121, 123, 139, 169, 204, 222, 224, 209, 190,
-  177, 171, 169, 160, 147, 135, 129, 119, 121, 114, 119, 114, 110, 98, 49, 35,
-  32, 32, 66, 43, 46, 41, 35, 23, 162, 185, 164, 149, 29, 49, 29, 46,
-  20, 26, 46, 23, 26, 32, 105, 145, 139, 143, 135, 160, 167, 167, 165, 164,
-  158, 160, 165, 158, 158, 156, 158, 158, 155, 156, 164, 160, 158, 151, 153, 147,
-  153, 155, 158, 153, 149, 153, 143, 147, 147, 145, 153, 141, 147, 174, 189, 198,
-  201, 206, 206, 204, 203, 201, 203, 200, 201, 200, 201, 200, 200, 200, 201, 203,
-  81, 68, 79, 81, 71, 57, 66, 63, 63, 55, 60, 41, 41, 52, 81, 117,
-  143, 151, 167, 172, 177, 176, 179, 181, 184, 189, 189, 184, 171, 160, 147, 123,
-  96, 71, 63, 71, 68, 76, 91, 114, 141, 137, 123, 108, 127, 133, 129, 112,
-  71, 41, 35, 91, 74, 55, 60, 49, 71, 35, 66, 103, 63, 94, 127, 119,
-  149, 158, 46, 43, 41, 41, 20, 38, 29, 26, 35, 35, 66, 86, 43, 60,
-  117, 29, 20, 38, 57, 133, 147, 121, 57, 43, 29, 38, 32, 32, 32, 35,
-  20, 23, 49, 153, 112, 117, 147, 176, 200, 203, 213, 213, 29, 12, 32, 74,
-  86, 103, 117, 112, 119, 119, 117, 127, 143, 141, 147, 155, 155, 165, 167, 176,
-  172, 177, 177, 177, 182, 184, 176, 177, 181, 181, 181, 171, 167, 160, 155, 153,
-  143, 143, 143, 135, 117, 125, 119, 119, 114, 137, 167, 207, 218, 224, 212, 187,
-  174, 165, 165, 164, 151, 141, 131, 127, 123, 121, 117, 112, 117, 96, 52, 49,
-  29, 23, 46, 38, 52, 41, 26, 29, 156, 177, 153, 164, 29, 29, 20, 26,
-  18, 32, 29, 23, 26, 57, 119, 139, 147, 139, 145, 158, 169, 165, 165, 167,
-  164, 164, 164, 162, 160, 164, 158, 158, 162, 158, 155, 158, 153, 164, 153, 153,
-  153, 156, 149, 151, 156, 155, 145, 147, 143, 143, 139, 143, 167, 189, 197, 203,
-  203, 204, 206, 203, 204, 204, 203, 203, 203, 200, 200, 201, 201, 204, 204, 209,
-  66, 79, 66, 74, 60, 57, 63, 71, 63, 57, 57, 38, 49, 41, 79, 117,
-  137, 149, 167, 174, 179, 179, 182, 181, 187, 185, 187, 179, 167, 156, 141, 119,
-  101, 79, 52, 71, 71, 84, 86, 98, 103, 103, 110, 110, 129, 121, 101, 105,
-  108, 91, 79, 89, 94, 43, 55, 29, 46, 68, 119, 49, 71, 119, 133, 156,
-  76, 55, 86, 32, 52, 32, 38, 32, 32, 29, 32, 49, 26, 60, 94, 26,
-  96, 23, 23, 15, 94, 108, 149, 108, 103, 41, 23, 23, 35, 18, 38, 38,
-  12, 29, 129, 155, 101, 117, 210, 189, 195, 198, 221, 60, 20, 41, 32, 76,
-  94, 108, 110, 114, 110, 110, 123, 131, 141, 141, 149, 147, 155, 160, 167, 176,
-  176, 177, 181, 184, 182, 179, 174, 176, 181, 176, 172, 177, 167, 162, 153, 141,
-  151, 141, 143, 133, 131, 129, 117, 119, 119, 141, 162, 200, 224, 228, 215, 187,
-  172, 164, 164, 155, 155, 141, 137, 125, 125, 123, 123, 119, 110, 84, 38, 35,
-  26, 41, 35, 38, 79, 35, 20, 18, 147, 177, 129, 169, 55, 38, 9, 20,
-  49, 29, 35, 20, 20, 71, 125, 149, 141, 137, 151, 169, 169, 165, 164, 162,
-  164, 164, 164, 156, 155, 158, 162, 156, 155, 149, 160, 155, 158, 155, 155, 153,
-  151, 149, 155, 147, 151, 151, 147, 141, 141, 139, 137, 153, 182, 195, 201, 203,
-  203, 204, 203, 203, 204, 201, 203, 203, 203, 203, 201, 203, 204, 207, 209, 210,
-  74, 68, 71, 68, 63, 60, 63, 71, 57, 63, 57, 68, 35, 52, 76, 117,
-  131, 151, 162, 172, 177, 182, 182, 184, 184, 184, 182, 177, 171, 151, 143, 133,
-  94, 76, 66, 79, 79, 81, 91, 108, 94, 103, 98, 105, 129, 103, 89, 60,
-  76, 68, 105, 71, 86, 74, 29, 46, 81, 121, 94, 32, 60, 156, 119, 103,
-  60, 60, 117, 43, 35, 18, 20, 49, 38, 35, 35, 49, 29, 55, 38, 46,
-  81, 38, 12, 6, 84, 103, 137, 133, 139, 38, 29, 23, 23, 18, 35, 26,
-  6, 43, 153, 105, 119, 165, 198, 201, 197, 213, 162, 18, 29, 26, 55, 79,
-  91, 103, 103, 114, 121, 108, 119, 123, 129, 141, 145, 141, 149, 158, 167, 169,
-  172, 172, 179, 182, 185, 187, 176, 176, 172, 169, 169, 169, 162, 153, 156, 143,
-  147, 145, 135, 133, 123, 127, 119, 125, 127, 137, 164, 197, 221, 227, 219, 187,
-  172, 165, 165, 158, 149, 149, 133, 127, 127, 119, 121, 121, 110, 84, 41, 41,
-  26, 52, 32, 41, 91, 29, 12, 20, 141, 181, 125, 172, 79, 29, 23, 18,
-  74, 38, 41, 23, 20, 86, 137, 143, 143, 143, 158, 171, 169, 165, 164, 158,
-  156, 158, 158, 160, 158, 156, 153, 158, 156, 160, 156, 155, 153, 156, 156, 155,
-  153, 149, 153, 151, 151, 153, 143, 145, 135, 131, 139, 174, 192, 198, 206, 204,
-  201, 201, 201, 203, 203, 203, 203, 206, 206, 201, 206, 206, 212, 210, 212, 212,
-  71, 76, 60, 55, 55, 57, 60, 57, 57, 46, 46, 43, 32, 52, 74, 121,
-  137, 151, 164, 174, 174, 182, 181, 182, 182, 179, 181, 174, 165, 158, 139, 127,
-  98, 63, 55, 66, 79, 76, 103, 98, 94, 101, 103, 103, 108, 91, 55, 123,
-  105, 143, 96, 60, 129, 89, 60, 91, 127, 81, 29, 38, 81, 112, 139, 94,
-  112, 55, 46, 49, 23, 26, 52, 41, 38, 35, 41, 41, 29, 76, 32, 18,
-  55, 41, 15, 32, 81, 112, 105, 158, 155, 84, 20, 9, 15, 18, 12, 9,
-  18, 121, 145, 112, 112, 204, 195, 204, 207, 206, 43, 23, 46, 38, 41, 76,
-  101, 108, 110, 108, 121, 121, 121, 123, 133, 141, 135, 139, 145, 155, 160, 160,
-  165, 177, 179, 185, 179, 184, 177, 176, 172, 174, 171, 169, 165, 155, 145, 137,
-  135, 143, 137, 133, 125, 117, 117, 117, 119, 141, 160, 181, 218, 224, 219, 197,
-  174, 171, 162, 164, 153, 141, 139, 131, 121, 114, 114, 121, 110, 71, 35, 38,
-  26, 38, 29, 38, 94, 29, 15, 15, 145, 179, 147, 169, 114, 23, 18, 15,
-  57, 43, 38, 20, 26, 108, 141, 141, 149, 151, 158, 176, 169, 167, 164, 160,
-  164, 162, 158, 158, 156, 158, 156, 156, 151, 160, 155, 153, 156, 156, 153, 155,
-  151, 149, 149, 151, 149, 145, 139, 139, 137, 131, 160, 185, 198, 201, 204, 204,
-  201, 204, 200, 204, 204, 204, 203, 204, 206, 209, 210, 210, 212, 213, 213, 213,
-  60, 66, 66, 57, 60, 66, 63, 55, 55, 55, 55, 35, 38, 52, 68, 110,
-  141, 149, 156, 171, 174, 181, 179, 177, 177, 185, 179, 177, 174, 158, 141, 127,
-  91, 66, 60, 68, 91, 91, 81, 91, 91, 101, 101, 103, 105, 68, 133, 160,
-  167, 91, 57, 108, 117, 49, 91, 145, 71, 52, 55, 60, 43, 74, 160, 91,
-  131, 38, 52, 43, 38, 35, 55, 26, 26, 38, 26, 29, 32, 29, 94, 38,
-  15, 57, 26, 18, 71, 114, 91, 76, 171, 160, 57, 23, 23, 23, 12, 18,
-  32, 147, 96, 112, 147, 197, 203, 210, 219, 66, 18, 23, 52, 29, 46, 63,
-  94, 98, 114, 112, 114, 123, 121, 125, 129, 137, 141, 145, 149, 147, 155, 158,
-  165, 174, 174, 179, 177, 179, 176, 172, 172, 174, 167, 165, 160, 155, 143, 137,
-  129, 129, 127, 127, 123, 121, 114, 121, 121, 139, 155, 179, 210, 227, 222, 197,
-  171, 167, 160, 158, 149, 145, 139, 133, 123, 127, 114, 112, 98, 60, 46, 23,
-  35, 20, 26, 43, 96, 26, 12, 6, 125, 184, 153, 160, 153, 15, 20, 15,
-  55, 46, 35, 23, 55, 123, 149, 143, 137, 147, 182, 189, 162, 164, 165, 160,
-  165, 158, 164, 158, 160, 156, 156, 156, 155, 158, 155, 155, 153, 153, 151, 147,
-  149, 153, 155, 153, 151, 145, 141, 133, 139, 153, 177, 192, 200, 204, 206, 203,
-  203, 201, 201, 201, 201, 203, 206, 207, 210, 212, 213, 213, 212, 212, 212, 212,
-  57, 66, 76, 66, 66, 68, 68, 57, 60, 63, 41, 43, 38, 35, 76, 112,
-  139, 156, 160, 177, 177, 179, 179, 174, 177, 177, 184, 171, 165, 147, 143, 125,
-  103, 60, 49, 74, 79, 133, 94, 91, 98, 91, 89, 110, 139, 165, 156, 84,
-  29, 66, 114, 133, 74, 86, 149, 49, 41, 49, 63, 86, 52, 76, 156, 119,
-  149, 60, 41, 46, 52, 38, 66, 38, 38, 23, 23, 26, 20, 35, 74, 35,
-  29, 46, 26, 23, 91, 123, 137, 63, 143, 153, 160, 35, 32, 23, 23, 15,
-  96, 156, 94, 119, 201, 204, 209, 218, 184, 15, 18, 38, 63, 38, 55, 68,
-  89, 96, 103, 119, 121, 114, 119, 127, 133, 131, 147, 147, 147, 153, 153, 153,
-  172, 176, 172, 177, 176, 174, 177, 167, 174, 167, 167, 162, 156, 153, 139, 131,
-  131, 125, 129, 127, 117, 121, 114, 110, 129, 135, 145, 171, 206, 224, 222, 206,
-  164, 164, 160, 155, 147, 145, 127, 133, 125, 125, 123, 110, 98, 55, 32, 32,
-  41, 35, 38, 55, 94, 20, 12, 9, 112, 176, 162, 158, 149, 35, 18, 20,
-  46, 49, 26, 18, 89, 133, 147, 143, 139, 164, 167, 172, 167, 165, 165, 162,
-  156, 162, 160, 160, 156, 156, 158, 155, 158, 153, 155, 153, 155, 153, 149, 158,
-  153, 149, 151, 147, 149, 145, 141, 139, 141, 162, 185, 198, 203, 203, 203, 197,
-  203, 198, 203, 203, 203, 206, 207, 210, 212, 218, 216, 215, 215, 210, 212, 209,
-  79, 68, 57, 63, 63, 76, 60, 66, 57, 46, 38, 29, 23, 49, 84, 112,
-  137, 147, 160, 169, 172, 176, 177, 174, 179, 184, 185, 179, 164, 153, 139, 119,
-  103, 63, 63, 57, 86, 139, 81, 84, 94, 108, 169, 177, 153, 110, 23, 41,
-  38, 108, 165, 119, 81, 137, 35, 38, 26, 127, 71, 86, 43, 169, 143, 141,
-  98, 117, 35, 35, 49, 55, 60, 23, 15, 18, 23, 23, 18, 26, 76, 68,
-  57, 41, 38, 63, 86, 169, 155, 86, 35, 114, 184, 101, 9, 20, 9, 18,
-  147, 125, 103, 149, 213, 212, 213, 213, 35, 20, 18, 18, 79, 26, 32, 71,
-  91, 101, 103, 119, 121, 117, 127, 123, 125, 129, 143, 143, 149, 149, 155, 162,
-  156, 160, 162, 181, 169, 172, 174, 172, 174, 165, 158, 167, 158, 153, 141, 125,
-  127, 125, 127, 125, 119, 112, 108, 112, 121, 121, 153, 174, 206, 224, 225, 210,
-  167, 167, 156, 156, 141, 143, 133, 125, 125, 119, 119, 114, 91, 49, 29, 18,
-  41, 38, 41, 49, 81, 26, 15, 23, 98, 167, 158, 158, 145, 68, 23, 29,
-  41, 41, 26, 29, 103, 139, 141, 141, 143, 164, 172, 172, 169, 164, 165, 162,
-  167, 158, 160, 160, 164, 158, 156, 156, 155, 153, 155, 155, 151, 153, 155, 151,
-  153, 149, 149, 143, 151, 139, 137, 137, 153, 181, 198, 203, 207, 204, 203, 200,
-  200, 203, 201, 203, 204, 207, 212, 212, 216, 218, 216, 215, 215, 209, 209, 207,
-  74, 63, 66, 71, 74, 71, 68, 66, 49, 57, 41, 29, 26, 41, 71, 114,
-  135, 145, 160, 171, 176, 177, 176, 176, 177, 177, 176, 174, 167, 156, 139, 123,
-  89, 57, 57, 52, 71, 155, 103, 89, 147, 171, 127, 112, 143, 79, 23, 35,
-  91, 133, 137, 76, 131, 46, 46, 49, 46, 123, 76, 112, 76, 162, 105, 156,
-  55, 165, 49, 57, 57, 38, 46, 26, 15, 20, 12, 9, 41, 66, 108, 76,
-  66, 26, 74, 60, 135, 172, 185, 141, 20, 71, 145, 84, 9, 6, 6, 89,
-  169, 110, 110, 172, 207, 210, 216, 68, 15, 12, 18, 23, 86, 43, 35, 68,
-  94, 94, 108, 117, 125, 121, 117, 121, 125, 133, 137, 141, 153, 155, 149, 153,
-  164, 160, 158, 169, 164, 171, 167, 171, 167, 165, 162, 160, 153, 149, 137, 127,
-  125, 123, 127, 121, 114, 112, 108, 114, 114, 131, 151, 172, 195, 216, 230, 221,
-  160, 164, 155, 153, 145, 141, 135, 127, 121, 127, 121, 108, 81, 57, 23, 29,
-  38, 38, 52, 74, 81, 18, 18, 15, 79, 167, 167, 151, 143, 79, 6, 18,
-  46, 38, 15, 41, 114, 147, 137, 145, 149, 162, 167, 169, 164, 164, 162, 160,
-  158, 160, 160, 158, 158, 165, 156, 160, 153, 158, 158, 153, 155, 151, 149, 147,
-  145, 147, 145, 145, 145, 135, 135, 141, 167, 192, 200, 204, 206, 204, 201, 200,
-  203, 201, 203, 206, 209, 212, 215, 215, 216, 216, 218, 215, 215, 209, 209, 209,
-  68, 68, 66, 66, 60, 57, 63, 60, 60, 43, 38, 38, 20, 32, 71, 121,
-  135, 153, 162, 172, 171, 181, 176, 176, 171, 179, 184, 172, 164, 158, 135, 121,
-  86, 68, 46, 55, 55, 101, 162, 133, 139, 103, 105, 135, 119, 76, 41, 71,
-  156, 114, 60, 117, 79, 112, 57, 41, 114, 71, 133, 71, 91, 131, 103, 165,
-  84, 156, 68, 43, 32, 41, 43, 35, 15, 20, 18, 46, 35, 46, 117, 108,
-  41, 41, 60, 123, 119, 189, 192, 160, 23, 26, 121, 12, 12, 9, 15, 139,
-  121, 121, 117, 206, 213, 215, 153, 20, 18, 6, 20, 20, 89, 32, 49, 57,
-  84, 94, 103, 123, 112, 117, 127, 123, 129, 129, 129, 149, 139, 147, 149, 160,
-  160, 158, 158, 162, 162, 169, 164, 169, 165, 169, 167, 158, 153, 141, 131, 133,
-  123, 121, 125, 121, 112, 108, 108, 112, 112, 129, 145, 162, 187, 216, 233, 225,
-  172, 162, 153, 149, 145, 141, 133, 135, 119, 121, 117, 98, 76, 26, 18, 23,
-  32, 43, 57, 68, 57, 29, 12, 12, 60, 158, 172, 133, 147, 86, 9, 29,
-  26, 29, 20, 76, 129, 149, 143, 139, 158, 169, 165, 164, 165, 165, 153, 160,
-  164, 164, 164, 160, 160, 162, 160, 153, 156, 153, 158, 156, 153, 155, 151, 145,
-  145, 145, 147, 149, 139, 141, 139, 153, 184, 197, 203, 204, 204, 203, 201, 203,
-  200, 203, 203, 209, 213, 215, 216, 216, 216, 216, 216, 216, 215, 212, 212, 212,
-  68, 79, 79, 63, 68, 55, 63, 66, 55, 55, 35, 29, 32, 20, 66, 112,
-  131, 151, 158, 169, 176, 177, 174, 181, 181, 181, 181, 177, 167, 158, 141, 121,
-  96, 66, 57, 49, 60, 81, 105, 114, 117, 123, 108, 125, 129, 96, 29, 32,
-  123, 105, 71, 79, 79, 68, 41, 86, 86, 96, 131, 79, 94, 101, 121, 176,
-  89, 71, 81, 29, 26, 18, 32, 32, 26, 29, 12, 38, 43, 68, 76, 91,
-  32, 108, 135, 110, 74, 71, 176, 156, 29, 15, 43, 26, 9, 6, 60, 164,
-  108, 110, 176, 213, 213, 197, 23, 26, 20, 12, 12, 23, 96, 41, 60, 66,
-  86, 94, 108, 110, 117, 119, 117, 125, 125, 131, 149, 139, 137, 149, 149, 149,
-  151, 156, 153, 151, 156, 162, 167, 162, 156, 160, 158, 156, 145, 141, 129, 125,
-  123, 117, 123, 127, 112, 110, 119, 103, 121, 131, 145, 162, 179, 215, 233, 225,
-  192, 156, 155, 149, 147, 155, 133, 137, 129, 123, 114, 91, 57, 26, 26, 23,
-  35, 49, 49, 66, 71, 32, 9, 9, 63, 158, 177, 131, 151, 112, 18, 26,
-  18, 18, 46, 96, 147, 141, 143, 141, 165, 171, 167, 165, 162, 164, 155, 164,
-  153, 160, 158, 160, 165, 156, 156, 158, 158, 156, 160, 156, 151, 149, 147, 151,
-  153, 145, 153, 143, 135, 139, 149, 176, 192, 201, 206, 204, 201, 201, 200, 203,
-  201, 204, 207, 210, 216, 216, 218, 215, 215, 213, 216, 216, 215, 215, 213, 213,
-  74, 71, 71, 60, 63, 68, 68, 71, 49, 46, 38, 26, 26, 26, 74, 108,
-  131, 149, 164, 169, 177, 177, 182, 177, 176, 181, 182, 176, 165, 160, 143, 119,
-  89, 74, 57, 57, 71, 79, 81, 101, 129, 103, 135, 147, 123, 84, 41, 60,
-  81, 74, 103, 98, 105, 43, 98, 84, 52, 135, 66, 74, 98, 81, 114, 165,
-  110, 38, 139, 18, 29, 35, 23, 23, 26, 49, 35, 26, 35, 108, 49, 71,
-  71, 137, 110, 94, 49, 60, 98, 49, 26, 32, 43, 6, 15, 74, 110, 117,
-  129, 125, 207, 210, 167, 55, 9, 18, 23, 18, 12, 26, 110, 41, 49, 66,
-  68, 96, 105, 108, 117, 119, 119, 125, 133, 117, 129, 131, 141, 145, 149, 147,
-  149, 143, 151, 156, 156, 156, 164, 156, 165, 155, 156, 149, 145, 139, 133, 114,
-  101, 114, 127, 133, 123, 114, 112, 114, 117, 127, 141, 160, 177, 209, 233, 228,
-  200, 153, 151, 151, 151, 141, 129, 129, 119, 119, 125, 101, 32, 20, 26, 23,
-  20, 43, 52, 76, 52, 57, 15, 9, 55, 141, 171, 141, 158, 137, 23, 32,
-  20, 15, 55, 105, 145, 151, 141, 145, 162, 165, 162, 164, 162, 158, 162, 160,
-  158, 156, 153, 160, 164, 160, 156, 156, 155, 155, 158, 153, 155, 151, 153, 151,
-  153, 149, 143, 135, 137, 135, 160, 181, 198, 206, 204, 203, 204, 201, 203, 203,
-  204, 209, 212, 216, 216, 216, 216, 213, 215, 215, 215, 216, 215, 216, 215, 215,
-  74, 63, 66, 63, 71, 71, 66, 55, 49, 38, 32, 26, 15, 23, 66, 112,
-  125, 149, 162, 169, 177, 176, 172, 177, 181, 179, 184, 176, 167, 158, 141, 117,
-  98, 63, 49, 55, 71, 94, 121, 125, 101, 105, 103, 108, 105, 35, 55, 84,
-  79, 66, 137, 98, 55, 94, 60, 52, 68, 160, 35, 49, 127, 81, 105, 155,
-  141, 46, 151, 26, 18, 35, 23, 76, 52, 20, 12, 18, 43, 89, 41, 114,
-  68, 179, 167, 112, 94, 110, 91, 32, 15, 18, 20, 6, 74, 137, 121, 101,
-  108, 151, 185, 147, 165, 86, 26, 15, 12, 20, 9, 29, 114, 49, 55, 63,
-  84, 91, 103, 105, 117, 110, 112, 121, 123, 131, 127, 137, 141, 137, 153, 147,
-  149, 151, 147, 155, 156, 162, 153, 158, 162, 160, 153, 149, 143, 135, 119, 101,
-  101, 119, 125, 129, 131, 133, 123, 112, 117, 127, 133, 158, 177, 209, 233, 227,
-  200, 147, 143, 147, 149, 139, 131, 129, 127, 121, 110, 89, 29, 29, 23, 49,
-  26, 57, 60, 66, 60, 32, 9, 12, 23, 135, 179, 165, 165, 143, 18, 23,
-  15, 26, 76, 121, 151, 155, 143, 145, 164, 165, 164, 162, 162, 160, 156, 155,
-  160, 162, 155, 155, 160, 153, 158, 162, 160, 160, 158, 155, 153, 151, 162, 149,
-  149, 145, 147, 139, 143, 141, 167, 195, 201, 207, 204, 203, 203, 204, 203, 204,
-  206, 210, 213, 215, 216, 215, 215, 212, 213, 216, 212, 213, 215, 215, 215, 215,
-  79, 76, 68, 68, 68, 71, 63, 57, 49, 43, 32, 20, 20, 18, 63, 114,
-  129, 149, 162, 169, 174, 174, 179, 179, 179, 181, 179, 179, 172, 158, 145, 117,
-  86, 63, 41, 68, 103, 139, 129, 98, 98, 98, 108, 110, 101, 55, 49, 91,
-  60, 127, 141, 52, 96, 68, 81, 29, 133, 98, 32, 43, 123, 101, 68, 165,
-  156, 32, 89, 63, 35, 49, 74, 41, 20, 43, 15, 12, 38, 76, 176, 167,
-  46, 52, 81, 112, 49, 26, 23, 12, 15, 32, 12, 29, 185, 171, 160, 156,
-  133, 121, 172, 198, 153, 26, 12, 20, 35, 12, 18, 23, 117, 86, 52, 55,
-  74, 98, 105, 114, 105, 119, 114, 125, 121, 125, 131, 139, 137, 139, 143, 147,
-  147, 145, 162, 156, 155, 156, 158, 162, 156, 155, 158, 147, 141, 135, 117, 86,
-  103, 125, 135, 135, 131, 135, 137, 123, 108, 114, 133, 153, 182, 203, 225, 225,
-  197, 139, 149, 141, 139, 129, 129, 121, 123, 119, 112, 49, 15, 23, 18, 26,
-  32, 49, 52, 60, 63, 26, 20, 9, 12, 123, 181, 165, 149, 143, 52, 32,
-  15, 15, 89, 129, 149, 149, 145, 151, 167, 167, 164, 165, 165, 162, 158, 160,
-  162, 155, 155, 156, 158, 160, 155, 155, 155, 155, 151, 158, 153, 155, 155, 153,
-  149, 143, 139, 135, 137, 151, 174, 198, 203, 206, 206, 204, 203, 204, 200, 204,
-  209, 213, 215, 215, 216, 213, 213, 213, 216, 213, 216, 216, 216, 216, 216, 213,
-  84, 76, 71, 63, 68, 60, 66, 57, 49, 49, 49, 20, 18, 35, 74, 110,
-  127, 149, 164, 171, 174, 172, 179, 174, 181, 181, 185, 177, 179, 156, 139, 121,
-  105, 79, 108, 129, 129, 96, 81, 91, 91, 108, 114, 112, 81, 71, 55, 86,
-  94, 108, 117, 81, 66, 38, 46, 57, 160, 74, 38, 32, 117, 105, 55, 143,
-  176, 43, 60, 153, 35, 46, 43, 35, 35, 74, 20, 12, 26, 68, 43, 32,
-  20, 20, 57, 139, 119, 26, 15, 20, 32, 9, 3, 103, 165, 179, 184, 179,
-  181, 187, 197, 145, 68, 23, 18, 23, 20, 38, 12, 35, 108, 79, 32, 68,
-  79, 98, 105, 114, 117, 114, 117, 119, 123, 119, 139, 125, 135, 135, 147, 145,
-  141, 145, 147, 151, 153, 151, 155, 156, 156, 155, 153, 147, 143, 135, 119, 91,
-  112, 125, 127, 129, 121, 135, 123, 123, 105, 101, 123, 145, 176, 200, 209, 215,
-  174, 145, 143, 143, 139, 141, 131, 121, 121, 114, 79, 32, 23, 29, 23, 46,
-  32, 49, 66, 46, 68, 18, 26, 15, 12, 105, 172, 174, 149, 127, 71, 29,
-  23, 15, 89, 149, 149, 149, 149, 164, 165, 165, 164, 162, 160, 162, 164, 160,
-  162, 158, 158, 155, 164, 158, 160, 156, 155, 158, 155, 158, 155, 156, 151, 149,
-  147, 145, 145, 135, 137, 169, 185, 200, 207, 203, 203, 203, 201, 201, 204, 209,
-  213, 213, 213, 215, 216, 213, 215, 215, 213, 213, 215, 218, 216, 218, 216, 215,
-  79, 86, 68, 74, 71, 66, 66, 71, 49, 49, 38, 32, 29, 38, 84, 110,
-  139, 149, 162, 169, 172, 176, 174, 176, 179, 181, 184, 177, 169, 155, 135, 123,
-  98, 98, 68, 63, 79, 81, 84, 94, 89, 101, 112, 151, 89, 60, 46, 81,
-  94, 119, 125, 74, 60, 9, 46, 162, 117, 76, 79, 23, 94, 117, 81, 125,
-  197, 91, 46, 181, 43, 38, 26, 71, 43, 96, 20, 18, 46, 46, 71, 35,
-  26, 81, 151, 60, 15, 18, 18, 29, 18, 6, 6, 179, 182, 182, 187, 192,
-  192, 187, 174, 46, 15, 6, 9, 23, 32, 15, 18, 29, 114, 86, 66, 74,
-  86, 94, 105, 108, 112, 112, 117, 112, 121, 129, 131, 129, 137, 137, 143, 141,
-  151, 147, 155, 151, 153, 156, 156, 156, 156, 155, 158, 155, 141, 135, 129, 105,
-  127, 125, 133, 68, 29, 52, 89, 101, 119, 110, 117, 121, 158, 190, 204, 197,
-  156, 149, 141, 143, 135, 131, 125, 119, 123, 110, 41, 20, 18, 38, 29, 49,
-  35, 55, 74, 35, 71, 26, 35, 12, 15, 86, 160, 174, 147, 149, 96, 23,
-  23, 26, 110, 151, 153, 147, 149, 164, 169, 167, 162, 162, 165, 164, 155, 153,
-  158, 158, 156, 156, 158, 158, 156, 147, 155, 156, 153, 151, 153, 153, 155, 153,
-  147, 143, 141, 135, 143, 172, 192, 201, 206, 206, 204, 204, 203, 204, 209, 213,
-  213, 213, 213, 215, 213, 213, 215, 215, 215, 218, 218, 218, 218, 216, 215, 215,
-  71, 71, 76, 74, 60, 66, 68, 57, 52, 52, 52, 38, 38, 49, 94, 123,
-  137, 153, 162, 167, 174, 174, 176, 177, 177, 184, 185, 174, 171, 160, 143, 121,
-  105, 81, 57, 63, 76, 84, 81, 94, 96, 103, 108, 105, 41, 81, 38, 94,
-  79, 149, 119, 71, 52, 9, 49, 176, 79, 35, 117, 26, 71, 117, 101, 123,
-  176, 127, 41, 167, 46, 26, 18, 60, 89, 63, 29, 15, 20, 15, 29, 68,
-  68, 101, 177, 46, 29, 26, 26, 38, 12, 6, 35, 177, 179, 189, 190, 200,
-  200, 185, 38, 9, 20, 15, 18, 23, 32, 29, 12, 26, 114, 103, 57, 79,
-  86, 94, 105, 112, 108, 114, 117, 119, 119, 125, 125, 133, 141, 143, 143, 149,
-  145, 141, 147, 143, 153, 156, 155, 153, 155, 155, 158, 147, 149, 145, 131, 112,
-  110, 121, 123, 74, 38, 66, 79, 68, 74, 103, 105, 114, 145, 184, 203, 174,
-  169, 145, 147, 145, 129, 135, 129, 121, 119, 86, 23, 32, 23, 26, 32, 35,
-  35, 55, 63, 57, 74, 32, 29, 35, 9, 46, 153, 181, 127, 160, 94, 12,
-  49, 52, 127, 153, 149, 145, 155, 164, 165, 164, 160, 162, 164, 160, 155, 158,
-  158, 155, 158, 160, 156, 156, 156, 153, 155, 153, 153, 147, 153, 153, 155, 151,
-  145, 145, 141, 143, 153, 174, 197, 203, 207, 204, 206, 203, 206, 206, 212, 213,
-  213, 215, 213, 215, 213, 215, 215, 218, 218, 218, 218, 219, 218, 218, 216, 213,
-  68, 76, 68, 63, 66, 66, 60, 57, 46, 66, 55, 43, 46, 68, 103, 125,
-  147, 155, 169, 171, 171, 177, 172, 176, 177, 177, 181, 179, 172, 164, 137, 125,
-  96, 74, 57, 71, 68, 81, 86, 94, 103, 103, 110, 103, 63, 91, 52, 91,
-  79, 71, 86, 79, 15, 43, 156, 121, 49, 68, 121, 29, 74, 129, 112, 129,
-  131, 167, 49, 158, 94, 12, 12, 26, 26, 86, 127, 32, 26, 23, 9, 20,
-  89, 141, 79, 23, 35, 52, 38, 18, 29, 43, 112, 141, 158, 179, 184, 201,
-  200, 139, 15, 12, 20, 23, 41, 20, 26, 15, 23, 29, 114, 96, 63, 91,
-  89, 108, 98, 105, 112, 114, 119, 119, 125, 127, 123, 135, 137, 131, 135, 143,
-  147, 145, 155, 151, 155, 151, 151, 156, 160, 155, 156, 155, 149, 147, 139, 121,
-  101, 112, 117, 119, 112, 121, 119, 110, 98, 81, 112, 110, 125, 179, 184, 176,
-  165, 151, 145, 135, 137, 141, 119, 129, 108, 49, 29, 35, 46, 26, 23, 32,
-  46, 57, 79, 41, 68, 23, 23, 52, 18, 32, 155, 177, 151, 162, 114, 32,
-  20, 81, 139, 153, 155, 151, 151, 167, 165, 162, 164, 162, 162, 156, 156, 158,
-  158, 155, 156, 156, 156, 155, 156, 156, 156, 153, 155, 149, 147, 147, 143, 149,
-  149, 141, 137, 139, 160, 182, 201, 203, 204, 206, 204, 200, 207, 207, 215, 215,
-  215, 215, 216, 216, 213, 215, 218, 218, 218, 218, 219, 216, 218, 215, 213, 213,
-  60, 68, 57, 71, 66, 55, 57, 63, 52, 43, 49, 49, 63, 74, 103, 129,
-  141, 153, 165, 169, 172, 171, 176, 176, 176, 179, 184, 182, 172, 156, 141, 127,
-  101, 71, 57, 66, 71, 76, 89, 91, 86, 119, 108, 91, 101, 35, 49, 91,
-  84, 76, 63, 18, 23, 119, 123, 74, 96, 91, 79, 52, 66, 145, 66, 108,
-  121, 185, 86, 139, 135, 9, 26, 41, 12, 108, 169, 68, 38, 12, 20, 18,
-  123, 114, 26, 15, 71, 55, 101, 96, 112, 112, 105, 125, 133, 123, 162, 193,
-  108, 20, 15, 15, 55, 79, 71, 26, 23, 15, 52, 23, 114, 101, 71, 79,
-  91, 98, 105, 105, 114, 114, 117, 127, 125, 123, 125, 131, 133, 141, 139, 149,
-  143, 143, 145, 141, 155, 141, 149, 155, 155, 162, 155, 156, 147, 147, 143, 135,
-  129, 119, 108, 114, 117, 123, 125, 112, 105, 110, 129, 156, 184, 197, 185, 171,
-  162, 156, 145, 137, 133, 129, 131, 121, 101, 26, 32, 32, 41, 35, 32, 32,
-  38, 71, 66, 38, 79, 32, 20, 26, 15, 20, 151, 184, 149, 153, 101, 46,
-  20, 112, 145, 153, 153, 147, 162, 165, 167, 164, 160, 164, 160, 158, 158, 158,
-  155, 155, 160, 158, 158, 160, 160, 151, 155, 153, 155, 151, 149, 153, 147, 153,
-  147, 145, 137, 147, 165, 192, 201, 204, 204, 203, 204, 204, 210, 210, 216, 216,
-  213, 213, 216, 215, 213, 218, 218, 219, 216, 216, 219, 216, 215, 215, 216, 215,
-  57, 71, 74, 68, 57, 74, 74, 57, 49, 43, 60, 63, 76, 79, 121, 135,
-  149, 155, 165, 171, 171, 172, 174, 174, 181, 179, 184, 177, 172, 158, 141, 127,
-  103, 68, 60, 63, 74, 84, 86, 86, 94, 117, 105, 103, 52, 20, 32, 98,
-  89, 71, 49, 15, 89, 131, 68, 32, 68, 94, 63, 112, 68, 123, 81, 129,
-  108, 147, 127, 145, 153, 38, 18, 52, 18, 108, 164, 169, 35, 9, 9, 52,
-  101, 38, 63, 35, 91, 108, 101, 129, 169, 184, 98, 98, 105, 137, 219, 204,
-  18, 26, 15, 20, 32, 52, 41, 29, 29, 15, 15, 26, 123, 89, 55, 74,
-  91, 105, 103, 103, 110, 114, 119, 121, 114, 123, 123, 127, 131, 133, 137, 139,
-  139, 141, 147, 141, 151, 149, 151, 151, 151, 156, 162, 149, 151, 155, 156, 141,
-  137, 135, 125, 133, 117, 125, 139, 139, 125, 160, 190, 204, 198, 193, 176, 167,
-  156, 149, 145, 143, 135, 131, 123, 114, 46, 35, 32, 41, 26, 29, 38, 43,
-  52, 76, 71, 74, 52, 43, 29, 20, 18, 9, 139, 181, 145, 151, 81, 46,
-  29, 129, 149, 149, 149, 151, 165, 167, 162, 167, 165, 160, 153, 160, 160, 164,
-  155, 156, 153, 155, 153, 158, 155, 155, 155, 158, 155, 155, 153, 149, 149, 143,
-  143, 143, 139, 143, 169, 195, 203, 204, 204, 204, 204, 207, 212, 212, 215, 216,
-  215, 213, 216, 213, 215, 216, 218, 216, 218, 218, 225, 216, 216, 215, 216, 216,
-  60, 66, 60, 60, 74, 66, 71, 66, 52, 57, 52, 60, 79, 91, 119, 133,
-  155, 156, 164, 167, 172, 174, 171, 177, 172, 181, 181, 177, 171, 162, 147, 129,
-  103, 84, 57, 60, 74, 94, 86, 89, 89, 91, 112, 145, 81, 15, 35, 91,
-  52, 60, 46, 76, 156, 79, 26, 32, 74, 81, 55, 127, 123, 110, 114, 133,
-  81, 86, 158, 143, 153, 91, 29, 41, 18, 74, 137, 108, 60, 23, 38, 91,
-  35, 71, 101, 101, 117, 110, 145, 185, 197, 84, 114, 103, 125, 179, 221, 46,
-  29, 41, 46, 32, 46, 57, 43, 32, 38, 29, 32, 41, 123, 91, 66, 79,
-  98, 103, 112, 108, 110, 114, 110, 114, 127, 119, 123, 137, 131, 133, 137, 135,
-  135, 137, 145, 141, 149, 151, 153, 158, 155, 160, 155, 156, 153, 155, 149, 149,
-  147, 139, 137, 135, 131, 139, 165, 187, 153, 162, 193, 203, 200, 198, 184, 165,
-  158, 149, 141, 137, 127, 127, 127, 114, 43, 41, 38, 32, 23, 38, 26, 55,
-  38, 91, 55, 79, 71, 38, 49, 18, 26, 6, 117, 174, 155, 149, 79, 60,
-  63, 133, 151, 147, 147, 151, 169, 162, 158, 156, 164, 164, 156, 158, 162, 153,
-  156, 158, 155, 156, 155, 162, 155, 153, 151, 153, 156, 153, 153, 155, 153, 151,
-  145, 145, 139, 151, 179, 193, 203, 204, 203, 203, 204, 209, 212, 215, 218, 215,
-  216, 215, 213, 215, 216, 216, 218, 218, 218, 216, 218, 216, 218, 218, 218, 216,
-  76, 66, 63, 55, 68, 74, 66, 55, 49, 49, 43, 55, 81, 94, 119, 135,
-  145, 158, 164, 169, 172, 174, 171, 177, 179, 179, 184, 177, 174, 160, 147, 133,
-  98, 71, 57, 60, 74, 94, 89, 86, 96, 110, 139, 149, 79, 32, 43, 103,
-  71, 81, 96, 164, 94, 52, 41, 43, 71, 86, 66, 79, 114, 112, 121, 139,
-  112, 76, 176, 96, 164, 139, 71, 60, 71, 66, 108, 110, 46, 55, 79, 29,
-  23, 46, 137, 139, 139, 164, 182, 195, 155, 96, 81, 119, 165, 216, 129, 43,
-  41, 60, 57, 43, 43, 38, 52, 38, 20, 29, 26, 35, 117, 89, 74, 81,
-  96, 105, 112, 108, 121, 117, 117, 121, 123, 121, 133, 129, 133, 137, 129, 137,
-  135, 139, 147, 153, 153, 149, 149, 151, 153, 153, 155, 155, 151, 145, 151, 149,
-  145, 149, 143, 141, 145, 158, 190, 203, 171, 167, 192, 204, 200, 198, 182, 164,
-  151, 141, 139, 139, 129, 133, 129, 52, 41, 41, 41, 43, 43, 41, 41, 66,
-  35, 91, 66, 66, 52, 49, 63, 41, 23, 12, 84, 169, 160, 151, 76, 86,
-  103, 143, 153, 149, 153, 151, 165, 164, 167, 162, 162, 162, 158, 156, 158, 160,
-  156, 156, 156, 158, 156, 151, 155, 158, 155, 153, 156, 153, 155, 149, 151, 149,
-  143, 141, 135, 162, 181, 198, 204, 204, 203, 206, 207, 212, 215, 216, 218, 215,
-  212, 212, 213, 216, 215, 215, 215, 216, 218, 219, 218, 218, 216, 219, 218, 216,
-  63, 66, 52, 57, 60, 55, 66, 60, 52, 49, 41, 49, 76, 94, 125, 135,
-  153, 160, 164, 172, 169, 172, 174, 176, 177, 184, 184, 179, 171, 158, 145, 125,
-  98, 79, 66, 60, 79, 76, 79, 81, 98, 143, 143, 105, 81, 35, 46, 86,
-  52, 123, 137, 103, 46, 20, 35, 35, 74, 57, 74, 49, 98, 66, 89, 98,
-  127, 76, 147, 91, 167, 129, 81, 57, 94, 81, 98, 91, 52, 32, 55, 23,
-  38, 135, 184, 145, 176, 179, 182, 185, 76, 108, 79, 98, 206, 164, 29, 18,
-  38, 38, 26, 35, 26, 41, 55, 52, 26, 26, 20, 12, 117, 114, 94, 86,
-  98, 103, 108, 110, 123, 114, 114, 108, 121, 123, 123, 129, 141, 135, 137, 129,
-  133, 131, 139, 141, 145, 147, 147, 153, 145, 155, 153, 156, 151, 147, 155, 147,
-  143, 145, 141, 145, 147, 171, 203, 206, 185, 171, 197, 204, 200, 204, 177, 164,
-  151, 143, 149, 135, 129, 133, 114, 41, 43, 38, 29, 35, 29, 32, 41, 60,
-  43, 86, 60, 66, 52, 35, 55, 26, 18, 9, 55, 162, 171, 143, 81, 114,
-  108, 145, 153, 143, 155, 158, 165, 162, 162, 160, 158, 158, 156, 164, 155, 156,
-  155, 155, 155, 151, 149, 149, 151, 158, 155, 151, 153, 158, 149, 149, 151, 147,
-  147, 137, 141, 164, 182, 200, 203, 204, 204, 207, 210, 213, 215, 218, 216, 213,
-  215, 213, 213, 215, 216, 216, 216, 216, 218, 218, 218, 224, 216, 219, 218, 218,
-  68, 71, 55, 63, 55, 55, 66, 57, 49, 43, 35, 49, 84, 101, 127, 135,
-  151, 160, 162, 169, 174, 174, 169, 174, 176, 179, 185, 181, 174, 162, 151, 131,
-  96, 81, 52, 60, 68, 74, 81, 94, 137, 139, 103, 125, 71, 38, 52, 63,
-  123, 149, 35, 35, 71, 35, 49, 41, 79, 49, 76, 49, 91, 63, 94, 129,
-  74, 76, 98, 137, 151, 127, 103, 38, 123, 110, 66, 46, 15, 6, 49, 57,
-  81, 160, 160, 151, 176, 190, 203, 143, 110, 84, 81, 151, 195, 32, 15, 23,
-  35, 32, 26, 32, 26, 32, 68, 41, 29, 35, 15, 29, 121, 110, 112, 81,
-  94, 101, 110, 108, 117, 114, 125, 123, 112, 123, 131, 125, 133, 127, 137, 131,
-  133, 131, 135, 137, 143, 145, 143, 149, 149, 149, 149, 158, 151, 147, 137, 149,
-  155, 139, 151, 155, 160, 172, 210, 210, 192, 176, 201, 210, 203, 200, 182, 162,
-  147, 141, 143, 133, 129, 129, 57, 38, 35, 43, 35, 43, 32, 43, 52, 63,
-  49, 68, 60, 55, 57, 57, 41, 35, 9, 9, 41, 155, 172, 135, 98, 105,
-  119, 147, 151, 149, 153, 158, 165, 162, 162, 164, 162, 158, 158, 160, 156, 156,
-  151, 162, 162, 158, 155, 147, 151, 151, 153, 153, 153, 151, 151, 149, 151, 151,
-  143, 139, 135, 165, 189, 201, 203, 204, 203, 209, 212, 218, 216, 216, 215, 213,
-  215, 215, 216, 215, 216, 215, 215, 216, 218, 219, 219, 218, 219, 218, 216, 219,
-  60, 55, 57, 57, 52, 46, 49, 52, 46, 55, 52, 52, 68, 94, 121, 141,
-  149, 156, 167, 165, 174, 176, 177, 177, 174, 179, 181, 181, 172, 164, 149, 125,
-  101, 71, 55, 63, 76, 63, 68, 119, 147, 105, 117, 117, 43, 52, 57, 114,
-  131, 121, 23, 35, 49, 52, 60, 49, 68, 52, 96, 55, 63, 63, 52, 135,
-  43, 71, 127, 145, 119, 131, 147, 38, 169, 71, 41, 18, 52, 29, 52, 103,
-  96, 117, 151, 169, 184, 204, 190, 89, 79, 81, 117, 206, 52, 20, 26, 32,
-  38, 43, 32, 35, 20, 49, 66, 49, 20, 38, 23, 18, 98, 103, 127, 63,
-  96, 98, 110, 108, 114, 117, 119, 129, 114, 121, 131, 125, 129, 133, 131, 127,
-  131, 129, 135, 133, 135, 145, 141, 145, 145, 147, 143, 155, 141, 151, 139, 141,
-  147, 156, 153, 153, 164, 177, 215, 210, 203, 169, 187, 207, 201, 198, 179, 155,
-  139, 143, 135, 131, 133, 121, 26, 46, 38, 26, 29, 46, 35, 35, 60, 41,
-  79, 86, 60, 57, 41, 63, 29, 29, 18, 18, 60, 145, 182, 119, 101, 121,
-  131, 147, 145, 151, 153, 167, 162, 162, 158, 162, 164, 160, 156, 155, 153, 158,
-  155, 156, 158, 158, 155, 155, 151, 153, 156, 149, 158, 151, 145, 151, 141, 141,
-  139, 143, 133, 172, 190, 204, 206, 203, 206, 212, 213, 218, 218, 215, 215, 215,
-  215, 218, 216, 215, 216, 213, 215, 218, 219, 221, 219, 219, 216, 219, 216, 219,
-  68, 60, 55, 46, 46, 52, 52, 57, 46, 46, 49, 68, 71, 86, 114, 129,
-  151, 160, 165, 167, 174, 169, 176, 177, 182, 179, 185, 182, 176, 160, 145, 127,
-  110, 71, 49, 66, 74, 76, 105, 160, 96, 91, 133, 119, 38, 55, 101, 96,
-  133, 89, 23, 46, 38, 89, 55, 74, 66, 52, 60, 71, 68, 74, 57, 101,
-  103, 46, 41, 125, 147, 114, 131, 133, 164, 18, 29, 20, 20, 121, 108, 91,
-  91, 135, 155, 165, 200, 203, 74, 94, 76, 96, 200, 55, 26, 23, 29, 76,
-  35, 35, 32, 38, 41, 41, 57, 79, 41, 26, 12, 15, 110, 103, 114, 68,
-  86, 91, 96, 123, 108, 121, 121, 119, 114, 123, 129, 125, 127, 135, 129, 129,
-  131, 127, 131, 129, 133, 131, 137, 141, 143, 143, 135, 147, 139, 143, 147, 141,
-  147, 149, 151, 153, 156, 177, 212, 212, 195, 177, 204, 215, 209, 197, 182, 153,
-  133, 139, 137, 135, 125, 66, 23, 29, 32, 52, 38, 35, 29, 63, 52, 46,
-  63, 66, 60, 66, 35, 55, 43, 20, 23, 12, 41, 131, 182, 119, 121, 114,
-  129, 141, 143, 153, 165, 164, 162, 165, 171, 164, 156, 162, 158, 156, 155, 158,
-  158, 156, 158, 160, 155, 151, 153, 151, 153, 155, 153, 153, 155, 147, 145, 141,
-  141, 139, 139, 171, 195, 204, 204, 203, 210, 212, 216, 216, 216, 215, 216, 215,
-  218, 218, 216, 213, 215, 215, 216, 218, 219, 219, 221, 219, 218, 218, 219, 219,
-  66, 46, 38, 43, 43, 46, 52, 63, 49, 46, 55, 46, 68, 86, 121, 133,
-  149, 156, 165, 171, 167, 172, 176, 176, 181, 182, 187, 182, 177, 165, 149, 127,
-  110, 66, 52, 55, 66, 84, 147, 108, 86, 86, 133, 103, 46, 84, 32, 81,
-  110, 63, 43, 38, 71, 57, 57, 84, 46, 81, 76, 94, 74, 49, 68, 86,
-  86, 96, 26, 46, 141, 141, 135, 172, 91, 12, 23, 32, 110, 133, 171, 156,
-  141, 143, 193, 193, 206, 103, 110, 79, 105, 151, 172, 26, 29, 18, 52, 98,
-  41, 35, 23, 52, 29, 35, 57, 79, 63, 32, 20, 15, 98, 98, 114, 86,
-  68, 89, 96, 108, 117, 121, 117, 127, 119, 123, 127, 129, 127, 125, 131, 131,
-  127, 129, 133, 135, 137, 135, 135, 139, 137, 131, 133, 135, 143, 141, 135, 135,
-  145, 153, 158, 164, 165, 171, 182, 193, 209, 212, 195, 177, 174, 189, 185, 137,
-  127, 127, 131, 141, 117, 52, 26, 18, 29, 43, 41, 32, 38, 43, 49, 60,
-  68, 74, 55, 60, 57, 57, 60, 23, 15, 12, 26, 129, 184, 125, 131, 133,
-  145, 149, 143, 153, 160, 164, 165, 162, 162, 158, 158, 160, 160, 162, 151, 156,
-  156, 164, 158, 155, 153, 156, 145, 153, 153, 149, 151, 153, 151, 149, 145, 141,
-  139, 133, 141, 177, 193, 201, 204, 210, 212, 215, 216, 218, 218, 216, 215, 215,
-  216, 218, 216, 216, 215, 215, 218, 218, 222, 221, 219, 219, 221, 218, 218, 218,
-  57, 41, 41, 43, 52, 43, 52, 55, 55, 43, 46, 49, 74, 91, 123, 137,
-  149, 162, 164, 174, 176, 172, 167, 179, 181, 184, 184, 182, 179, 164, 153, 127,
-  96, 68, 60, 57, 68, 133, 117, 86, 79, 86, 129, 103, 60, 43, 20, 123,
-  135, 63, 49, 35, 55, 57, 41, 79, 57, 57, 125, 79, 96, 86, 79, 76,
-  55, 119, 84, 49, 60, 91, 119, 141, 143, 32, 12, 79, 86, 105, 167, 206,
-  204, 198, 209, 209, 135, 91, 84, 86, 133, 209, 23, 23, 18, 23, 49, 117,
-  38, 20, 20, 43, 35, 38, 46, 63, 52, 26, 20, 18, 81, 71, 108, 81,
-  68, 84, 101, 112, 114, 110, 119, 125, 117, 125, 121, 129, 129, 129, 135, 131,
-  135, 131, 127, 135, 129, 125, 129, 121, 125, 131, 131, 135, 137, 141, 143, 145,
-  143, 137, 139, 129, 135, 127, 133, 137, 147, 160, 149, 137, 133, 149, 158, 121,
-  119, 131, 137, 137, 79, 35, 23, 35, 41, 38, 35, 41, 43, 38, 57, 63,
-  46, 66, 60, 57, 71, 49, 60, 35, 15, 12, 26, 133, 172, 119, 139, 127,
-  143, 155, 147, 151, 155, 165, 160, 165, 162, 160, 156, 164, 160, 158, 156, 153,
-  155, 160, 153, 155, 158, 158, 155, 153, 158, 153, 153, 149, 147, 149, 147, 143,
-  139, 131, 147, 171, 197, 203, 206, 210, 213, 216, 218, 216, 218, 215, 215, 216,
-  218, 218, 216, 215, 216, 218, 219, 219, 221, 221, 221, 221, 218, 221, 221, 218,
-  49, 52, 41, 41, 46, 43, 52, 49, 49, 35, 38, 55, 68, 86, 121, 139,
-  156, 165, 165, 172, 172, 179, 179, 177, 181, 184, 185, 182, 174, 162, 147, 129,
-  103, 74, 55, 63, 105, 145, 79, 71, 96, 108, 147, 96, 38, 26, 35, 84,
-  119, 71, 41, 57, 57, 57, 49, 43, 46, 60, 141, 84, 114, 105, 86, 66,
-  63, 60, 133, 74, 52, 117, 103, 141, 98, 133, 86, 143, 135, 121, 165, 195,
-  216, 206, 212, 174, 89, 110, 79, 121, 201, 57, 15, 12, 32, 29, 26, 81,
-  26, 26, 26, 38, 26, 46, 46, 46, 68, 18, 20, 20, 96, 68, 89, 71,
-  68, 84, 101, 103, 105, 119, 117, 117, 117, 114, 123, 123, 123, 123, 129, 137,
-  139, 133, 131, 149, 131, 105, 91, 110, 119, 125, 125, 133, 127, 129, 125, 121,
-  114, 110, 125, 121, 105, 108, 105, 125, 141, 137, 119, 84, 101, 112, 84, 86,
-  112, 135, 145, 129, 32, 35, 26, 26, 43, 32, 29, 29, 46, 32, 79, 38,
-  55, 49, 55, 76, 43, 29, 60, 55, 18, 20, 20, 117, 169, 127, 143, 133,
-  153, 147, 153, 145, 164, 167, 164, 162, 160, 156, 164, 156, 160, 160, 155, 155,
-  155, 155, 153, 156, 156, 156, 153, 156, 155, 151, 153, 151, 155, 151, 147, 145,
-  137, 127, 151, 177, 193, 203, 210, 215, 215, 219, 215, 216, 218, 216, 218, 215,
-  215, 218, 215, 216, 218, 218, 221, 219, 221, 221, 221, 219, 219, 221, 219, 222,
-  38, 41, 43, 41, 46, 46, 60, 46, 38, 38, 52, 66, 74, 91, 125, 143,
-  153, 156, 165, 176, 177, 174, 177, 182, 181, 182, 181, 184, 176, 162, 147, 123,
-  98, 68, 46, 105, 156, 101, 71, 68, 105, 145, 169, 86, 49, 41, 101, 38,
-  41, 63, 49, 63, 71, 79, 52, 35, 49, 79, 160, 133, 117, 96, 110, 91,
-  74, 55, 74, 131, 103, 133, 46, 108, 101, 43, 141, 160, 129, 145, 190, 195,
-  215, 216, 193, 66, 110, 91, 96, 177, 190, 15, 35, 35, 49, 18, 23, 71,
-  46, 15, 35, 20, 26, 41, 32, 55, 74, 18, 15, 23, 81, 43, 84, 84,
-  49, 74, 96, 110, 108, 123, 123, 123, 114, 114, 121, 117, 131, 131, 129, 133,
-  133, 137, 135, 141, 121, 74, 68, 52, 49, 68, 81, 89, 89, 89, 98, 84,
-  76, 79, 76, 57, 68, 79, 96, 103, 114, 103, 76, 66, 86, 101, 103, 105,
-  137, 141, 137, 96, 23, 29, 18, 32, 55, 26, 38, 29, 46, 49, 66, 38,
-  71, 49, 57, 81, 57, 18, 52, 60, 29, 18, 23, 101, 165, 137, 151, 129,
-  149, 143, 151, 155, 162, 160, 174, 162, 162, 156, 162, 158, 158, 158, 156, 160,
-  153, 156, 160, 153, 153, 155, 156, 153, 153, 147, 155, 151, 155, 147, 143, 141,
-  135, 135, 153, 182, 197, 204, 213, 215, 218, 219, 218, 219, 216, 216, 216, 215,
-  215, 218, 218, 218, 218, 218, 219, 218, 218, 224, 221, 221, 221, 221, 221, 218,
-  41, 38, 32, 32, 41, 46, 55, 46, 46, 38, 41, 74, 76, 96, 119, 143,
-  151, 162, 167, 176, 177, 181, 185, 182, 181, 182, 185, 185, 177, 160, 143, 125,
-  103, 63, 71, 162, 114, 74, 66, 74, 137, 158, 133, 79, 26, 79, 52, 29,
-  20, 49, 76, 98, 63, 66, 41, 55, 43, 63, 156, 151, 101, 91, 108, 105,
-  110, 86, 81, 89, 156, 129, 41, 79, 29, 60, 121, 135, 131, 129, 197, 222,
-  218, 210, 143, 86, 76, 86, 158, 209, 41, 35, 26, 35, 35, 26, 26, 41,
-  55, 23, 43, 29, 35, 41, 32, 49, 79, 38, 20, 12, 84, 55, 76, 89,
-  66, 79, 86, 103, 110, 117, 119, 119, 114, 114, 121, 123, 127, 131, 127, 135,
-  137, 141, 143, 141, 121, 112, 114, 103, 94, 76, 74, 79, 91, 98, 101, 91,
-  101, 91, 89, 94, 98, 91, 96, 112, 123, 119, 119, 112, 110, 127, 127, 125,
-  143, 145, 133, 35, 29, 29, 26, 38, 46, 26, 26, 29, 26, 63, 55, 35,
-  84, 60, 46, 79, 55, 18, 38, 74, 32, 15, 23, 76, 160, 149, 145, 139,
-  156, 147, 156, 153, 165, 164, 165, 160, 160, 162, 162, 160, 158, 155, 162, 158,
-  153, 158, 158, 158, 162, 156, 156, 153, 153, 156, 155, 153, 155, 147, 145, 139,
-  135, 135, 156, 182, 200, 209, 215, 218, 221, 219, 219, 218, 218, 216, 218, 216,
-  216, 218, 221, 218, 219, 216, 219, 219, 221, 222, 222, 221, 221, 219, 219, 218,
-  41, 35, 35, 43, 41, 38, 49, 52, 38, 35, 52, 89, 94, 105, 123, 141,
-  153, 162, 169, 174, 181, 179, 177, 181, 179, 185, 181, 181, 171, 158, 147, 123,
-  94, 91, 162, 119, 68, 57, 76, 105, 147, 117, 125, 91, 43, 66, 57, 41,
-  26, 43, 43, 32, 57, 60, 49, 103, 46, 52, 182, 155, 68, 103, 103, 98,
-  108, 112, 108, 98, 86, 84, 105, 57, 68, 103, 151, 141, 121, 117, 145, 231,
-  219, 176, 81, 110, 86, 147, 209, 86, 26, 38, 38, 41, 32, 29, 23, 43,
-  43, 26, 29, 32, 41, 38, 49, 46, 71, 55, 23, 20, 76, 55, 74, 81,
-  66, 71, 86, 101, 105, 110, 114, 110, 112, 117, 119, 117, 123, 125, 131, 127,
-  141, 145, 143, 141, 137, 129, 114, 117, 119, 108, 105, 101, 101, 110, 121, 125,
-  112, 127, 133, 129, 141, 141, 151, 162, 172, 179, 158, 125, 119, 141, 147, 139,
-  147, 141, 66, 29, 32, 32, 26, 43, 26, 38, 35, 35, 52, 76, 32, 43,
-  98, 55, 76, 76, 71, 23, 46, 98, 32, 35, 20, 74, 156, 158, 137, 141,
-  158, 145, 151, 156, 165, 164, 165, 162, 155, 165, 164, 160, 162, 156, 160, 156,
-  156, 156, 153, 153, 153, 155, 156, 156, 155, 156, 153, 149, 160, 147, 151, 141,
-  135, 129, 158, 185, 203, 210, 216, 219, 219, 221, 219, 216, 216, 218, 218, 216,
-  218, 219, 219, 218, 219, 221, 219, 221, 219, 221, 218, 219, 219, 218, 219, 218,
-  43, 49, 49, 41, 43, 43, 49, 46, 41, 32, 49, 81, 94, 96, 119, 139,
-  153, 156, 165, 174, 176, 179, 182, 182, 185, 184, 189, 184, 174, 162, 149, 119,
-  110, 151, 129, 66, 57, 63, 79, 131, 141, 108, 108, 94, 60, 55, 81, 71,
-  60, 23, 38, 23, 66, 68, 49, 103, 29, 57, 197, 147, 71, 49, 101, 119,
-  117, 91, 74, 108, 52, 52, 123, 81, 121, 137, 145, 149, 125, 112, 117, 222,
-  198, 108, 105, 108, 131, 195, 174, 46, 46, 26, 43, 46, 29, 18, 18, 32,
-  35, 35, 20, 35, 52, 29, 52, 38, 52, 43, 20, 32, 76, 68, 81, 68,
-  66, 63, 86, 96, 103, 105, 105, 105, 108, 125, 121, 112, 119, 121, 127, 131,
-  141, 145, 141, 139, 145, 135, 123, 123, 112, 117, 110, 110, 101, 103, 108, 125,
-  123, 145, 169, 187, 174, 195, 187, 200, 206, 198, 158, 123, 127, 141, 141, 137,
-  135, 119, 26, 23, 23, 29, 35, 38, 26, 23, 20, 35, 32, 35, 32, 52,
-  103, 52, 71, 74, 32, 23, 57, 91, 35, 20, 20, 74, 164, 165, 143, 151,
-  155, 145, 155, 156, 162, 165, 169, 165, 156, 164, 162, 156, 158, 162, 158, 158,
-  158, 165, 160, 156, 164, 155, 155, 156, 156, 158, 151, 155, 149, 153, 141, 143,
-  137, 135, 160, 190, 206, 213, 219, 221, 218, 218, 218, 218, 218, 218, 218, 216,
-  218, 219, 219, 219, 219, 219, 221, 219, 221, 219, 219, 219, 218, 218, 218, 216,
-  35, 41, 38, 41, 41, 35, 38, 46, 49, 32, 55, 81, 86, 96, 117, 141,
-  155, 160, 165, 171, 177, 179, 185, 174, 187, 182, 182, 177, 172, 164, 153, 123,
-  145, 123, 60, 55, 60, 71, 101, 153, 98, 96, 91, 79, 63, 38, 155, 63,
-  26, 20, 35, 23, 108, 60, 43, 86, 49, 66, 193, 139, 74, 26, 79, 91,
-  119, 131, 96, 101, 52, 49, 89, 94, 153, 139, 153, 143, 127, 103, 160, 219,
-  108, 108, 110, 169, 189, 172, 35, 41, 26, 41, 32, 41, 35, 26, 20, 23,
-  46, 38, 35, 20, 38, 41, 52, 49, 63, 60, 23, 18, 55, 57, 89, 86,
-  41, 66, 76, 94, 98, 108, 108, 108, 108, 110, 105, 108, 114, 127, 119, 129,
-  129, 127, 139, 141, 145, 143, 131, 131, 114, 110, 103, 117, 117, 121, 105, 108,
-  112, 137, 141, 149, 156, 156, 147, 153, 162, 158, 135, 127, 141, 151, 149, 141,
-  139, 41, 23, 20, 23, 26, 60, 23, 23, 23, 20, 23, 66, 26, 18, 41,
-  117, 52, 71, 79, 63, 41, 43, 89, 38, 32, 23, 74, 156, 164, 145, 156,
-  164, 145, 158, 155, 167, 169, 164, 162, 164, 165, 165, 162, 156, 158, 162, 160,
-  156, 164, 155, 160, 155, 151, 155, 153, 155, 151, 147, 153, 149, 149, 147, 137,
-  143, 129, 164, 190, 209, 216, 222, 221, 219, 219, 219, 216, 218, 218, 218, 219,
-  219, 219, 219, 221, 221, 219, 221, 221, 221, 218, 216, 218, 216, 216, 216, 215,
-  43, 41, 32, 29, 38, 26, 43, 46, 32, 32, 57, 68, 91, 89, 117, 137,
-  151, 156, 162, 172, 176, 181, 181, 184, 184, 184, 187, 182, 177, 169, 185, 158,
-  117, 68, 43, 49, 66, 76, 143, 137, 98, 98, 110, 38, 52, 63, 165, 66,
-  38, 41, 32, 32, 114, 43, 98, 41, 96, 105, 187, 119, 143, 41, 71, 94,
-  57, 94, 141, 91, 121, 98, 108, 103, 151, 158, 137, 156, 105, 119, 222, 200,
-  89, 125, 181, 206, 158, 41, 29, 35, 29, 32, 41, 43, 49, 32, 26, 38,
-  43, 49, 41, 29, 32, 68, 46, 43, 57, 66, 26, 26, 71, 84, 68, 81,
-  41, 60, 79, 89, 98, 101, 110, 103, 108, 112, 110, 119, 119, 125, 121, 123,
-  121, 133, 135, 139, 143, 139, 133, 129, 125, 129, 114, 112, 110, 114, 117, 112,
-  108, 127, 125, 127, 137, 139, 133, 131, 129, 137, 125, 137, 147, 153, 143, 137,
-  101, 29, 32, 32, 32, 32, 49, 32, 35, 26, 38, 20, 60, 26, 26, 49,
-  110, 43, 60, 79, 52, 55, 46, 81, 43, 32, 38, 66, 153, 169, 156, 160,
-  164, 149, 156, 158, 162, 164, 165, 164, 164, 164, 165, 164, 160, 160, 165, 158,
-  164, 158, 160, 162, 158, 156, 155, 158, 153, 155, 153, 155, 155, 149, 147, 141,
-  131, 131, 164, 197, 213, 219, 222, 222, 219, 221, 219, 219, 216, 218, 221, 219,
-  221, 219, 221, 222, 222, 222, 219, 218, 218, 216, 215, 215, 216, 213, 213, 213,
-  35, 26, 32, 38, 35, 43, 41, 38, 35, 38, 63, 68, 94, 84, 110, 135,
-  149, 158, 164, 171, 179, 184, 184, 185, 185, 182, 190, 184, 169, 156, 153, 125,
-  96, 60, 57, 57, 66, 137, 164, 98, 89, 110, 105, 43, 32, 105, 153, 35,
-  18, 43, 23, 63, 121, 26, 94, 68, 94, 153, 156, 112, 153, 86, 74, 121,
-  76, 49, 89, 139, 121, 149, 149, 129, 117, 160, 174, 153, 98, 121, 200, 149,
-  127, 162, 174, 197, 108, 35, 49, 29, 43, 35, 52, 38, 63, 49, 38, 49,
-  35, 32, 38, 35, 43, 35, 57, 46, 63, 60, 38, 23, 57, 84, 57, 60,
-  43, 49, 63, 79, 91, 94, 96, 98, 105, 105, 112, 123, 114, 125, 127, 125,
-  127, 127, 125, 131, 135, 139, 137, 129, 131, 123, 123, 117, 121, 117, 108, 112,
-  110, 114, 123, 121, 131, 133, 129, 121, 119, 117, 131, 151, 143, 143, 139, 125,
-  63, 18, 32, 29, 38, 38, 43, 43, 55, 32, 43, 29, 55, 41, 23, 57,
-  103, 41, 60, 84, 71, 57, 38, 91, 38, 41, 35, 55, 151, 167, 153, 164,
-  160, 155, 162, 171, 162, 169, 160, 165, 158, 162, 164, 162, 162, 164, 165, 164,
-  162, 158, 160, 156, 160, 155, 156, 155, 156, 153, 149, 145, 153, 149, 141, 141,
-  129, 129, 162, 200, 212, 221, 222, 222, 221, 221, 221, 219, 221, 221, 222, 222,
-  222, 221, 224, 221, 222, 219, 216, 213, 215, 212, 213, 212, 213, 213, 212, 212,
-  60, 38, 23, 32, 38, 49, 38, 46, 32, 29, 60, 94, 81, 74, 108, 127,
-  145, 155, 164, 171, 182, 185, 182, 181, 181, 185, 187, 182, 177, 160, 149, 125,
-  96, 68, 52, 43, 79, 160, 103, 89, 94, 123, 66, 38, 38, 131, 155, 15,
-  35, 29, 12, 101, 101, 41, 35, 76, 79, 185, 145, 101, 94, 153, 114, 135,
-  103, 71, 57, 108, 147, 155, 114, 143, 103, 143, 147, 149, 105, 145, 213, 151,
-  162, 143, 224, 96, 49, 41, 46, 55, 41, 52, 52, 60, 55, 38, 43, 55,
-  43, 38, 43, 49, 60, 43, 66, 46, 52, 55, 43, 32, 49, 74, 43, 81,
-  55, 60, 57, 68, 84, 101, 89, 94, 103, 101, 110, 105, 112, 117, 123, 119,
-  129, 125, 125, 137, 133, 137, 131, 131, 123, 125, 119, 121, 125, 119, 123, 105,
-  108, 98, 108, 105, 108, 105, 103, 94, 119, 149, 149, 147, 139, 139, 129, 38,
-  49, 29, 29, 26, 18, 32, 23, 29, 43, 46, 32, 38, 49, 32, 26, 74,
-  84, 63, 49, 81, 74, 43, 38, 74, 46, 26, 26, 52, 141, 176, 143, 160,
-  158, 155, 158, 169, 164, 162, 164, 165, 160, 162, 162, 158, 164, 164, 160, 165,
-  160, 160, 158, 164, 158, 158, 153, 155, 153, 153, 151, 151, 145, 145, 139, 141,
-  125, 133, 162, 204, 215, 222, 222, 222, 221, 221, 221, 221, 221, 221, 221, 224,
-  222, 224, 222, 219, 218, 216, 215, 215, 213, 213, 213, 213, 215, 216, 216, 216,
-  35, 32, 32, 38, 26, 41, 29, 26, 29, 35, 74, 94, 86, 79, 105, 127,
-  149, 149, 158, 172, 179, 181, 182, 182, 184, 187, 187, 179, 176, 162, 145, 127,
-  101, 66, 41, 46, 94, 167, 96, 94, 108, 105, 32, 41, 46, 123, 127, 29,
-  29, 32, 26, 105, 55, 41, 23, 57, 98, 201, 151, 103, 52, 160, 123, 133,
-  117, 74, 81, 76, 155, 156, 129, 98, 101, 119, 127, 127, 108, 171, 215, 133,
-  187, 210, 151, 35, 32, 35, 23, 43, 32, 32, 46, 38, 46, 29, 20, 43,
-  35, 43, 76, 43, 43, 63, 32, 46, 46, 55, 43, 41, 38, 68, 46, 89,
-  52, 43, 63, 63, 66, 86, 94, 94, 103, 91, 108, 108, 108, 114, 121, 123,
-  123, 127, 135, 131, 133, 137, 135, 129, 125, 127, 125, 119, 125, 119, 127, 121,
-  121, 114, 108, 114, 117, 119, 119, 139, 151, 155, 151, 133, 137, 139, 89, 38,
-  43, 23, 29, 20, 23, 29, 29, 46, 38, 60, 38, 41, 43, 52, 23, 68,
-  86, 55, 49, 103, 60, 46, 46, 71, 55, 43, 35, 49, 141, 185, 153, 169,
-  160, 155, 156, 167, 162, 167, 162, 171, 165, 162, 162, 164, 162, 158, 167, 164,
-  167, 162, 158, 164, 160, 156, 158, 153, 158, 155, 151, 149, 149, 147, 143, 133,
-  127, 123, 164, 206, 218, 224, 225, 224, 221, 221, 222, 221, 221, 222, 224, 224,
-  224, 221, 221, 218, 218, 215, 215, 216, 216, 218, 216, 218, 216, 218, 216, 216,
-  23, 26, 32, 35, 32, 32, 32, 29, 20, 43, 117, 94, 94, 96, 110, 125,
-  137, 149, 158, 174, 181, 177, 182, 181, 181, 184, 185, 179, 174, 160, 149, 129,
-  101, 55, 41, 46, 91, 169, 86, 89, 91, 68, 71, 38, 68, 133, 55, 38,
-  35, 18, 38, 89, 43, 57, 49, 18, 117, 203, 137, 145, 79, 114, 151, 153,
-  125, 103, 123, 125, 86, 129, 127, 110, 68, 129, 145, 105, 101, 156, 213, 172,
-  192, 172, 43, 41, 38, 43, 41, 43, 38, 49, 43, 49, 52, 43, 43, 43,
-  41, 43, 38, 32, 49, 52, 46, 55, 57, 49, 60, 46, 41, 55, 35, 74,
-  66, 43, 63, 74, 76, 81, 89, 96, 101, 98, 103, 114, 117, 117, 121, 119,
-  125, 129, 129, 133, 127, 131, 133, 133, 127, 125, 133, 129, 129, 127, 129, 137,
-  135, 137, 141, 149, 141, 143, 145, 151, 149, 156, 131, 135, 137, 135, 15, 49,
-  41, 32, 26, 29, 32, 32, 43, 43, 41, 60, 38, 32, 20, 43, 20, 60,
-  84, 66, 57, 96, 52, 43, 43, 71, 76, 23, 35, 32, 143, 176, 160, 171,
-  158, 151, 164, 158, 164, 165, 162, 165, 160, 162, 165, 167, 162, 160, 164, 164,
-  164, 160, 162, 162, 156, 155, 153, 156, 153, 155, 153, 151, 153, 149, 137, 133,
-  133, 127, 164, 201, 218, 225, 227, 225, 222, 221, 222, 222, 224, 222, 222, 224,
-  221, 221, 218, 216, 218, 216, 216, 216, 216, 216, 216, 218, 218, 219, 218, 218,
-  38, 38, 26, 41, 26, 29, 29, 32, 15, 60, 96, 108, 98, 98, 105, 131,
-  133, 141, 155, 164, 176, 179, 182, 185, 181, 181, 181, 182, 174, 165, 149, 131,
-  101, 63, 41, 46, 76, 145, 103, 91, 81, 86, 55, 63, 68, 110, 26, 43,
-  32, 20, 43, 103, 41, 57, 38, 68, 117, 203, 143, 96, 149, 86, 179, 145,
-  110, 108, 145, 63, 86, 139, 125, 119, 38, 98, 133, 119, 125, 181, 224, 185,
-  203, 74, 29, 20, 29, 52, 29, 43, 29, 29, 43, 26, 43, 35, 35, 57,
-  23, 38, 43, 32, 32, 43, 46, 41, 38, 43, 46, 41, 23, 38, 49, 55,
-  68, 46, 43, 60, 49, 71, 79, 86, 91, 98, 101, 103, 110, 114, 119, 123,
-  131, 129, 135, 129, 125, 133, 133, 129, 139, 131, 131, 135, 137, 137, 143, 151,
-  149, 158, 160, 162, 156, 155, 156, 155, 155, 147, 141, 141, 143, 81, 23, 81,
-  38, 12, 23, 35, 26, 38, 43, 60, 43, 52, 35, 38, 23, 49, 26, 76,
-  96, 66, 49, 84, 66, 55, 55, 71, 66, 35, 41, 18, 147, 181, 169, 167,
-  155, 149, 165, 162, 169, 165, 169, 165, 164, 158, 165, 162, 164, 162, 162, 164,
-  162, 162, 158, 160, 158, 158, 158, 155, 156, 155, 153, 155, 153, 141, 137, 137,
-  123, 125, 167, 204, 218, 224, 225, 225, 222, 224, 222, 222, 221, 221, 221, 227,
-  219, 219, 216, 216, 216, 218, 219, 219, 219, 218, 218, 218, 218, 218, 218, 215,
-  32, 35, 23, 32, 38, 35, 26, 35, 32, 68, 98, 96, 98, 101, 117, 121,
-  139, 141, 156, 169, 176, 177, 181, 181, 179, 182, 182, 177, 165, 164, 151, 125,
-  101, 79, 55, 46, 76, 121, 121, 103, 84, 71, 57, 96, 89, 98, 41, 38,
-  23, 23, 57, 94, 23, 35, 49, 35, 71, 181, 119, 103, 108, 127, 131, 158,
-  114, 131, 110, 74, 91, 91, 145, 127, 86, 123, 112, 108, 89, 177, 224, 219,
-  79, 32, 29, 41, 43, 55, 55, 43, 26, 38, 43, 43, 41, 29, 29, 57,
-  35, 38, 49, 29, 29, 23, 46, 43, 35, 41, 66, 38, 29, 32, 49, 46,
-  68, 41, 29, 55, 41, 46, 74, 84, 86, 94, 98, 103, 98, 114, 114, 117,
-  123, 133, 131, 127, 135, 133, 137, 137, 135, 133, 141, 147, 145, 141, 139, 151,
-  160, 165, 169, 169, 160, 158, 153, 158, 153, 149, 143, 151, 145, 18, 18, 60,
-  41, 26, 29, 38, 32, 35, 43, 57, 57, 43, 29, 41, 29, 35, 26, 96,
-  94, 63, 63, 66, 66, 55, 68, 84, 55, 38, 43, 29, 139, 185, 172, 172,
-  155, 155, 167, 171, 167, 165, 165, 169, 165, 164, 169, 162, 160, 162, 158, 162,
-  165, 162, 158, 156, 162, 158, 153, 156, 151, 155, 149, 149, 149, 141, 139, 129,
-  129, 121, 172, 207, 221, 227, 227, 225, 225, 221, 221, 221, 221, 218, 218, 219,
-  219, 219, 222, 219, 219, 221, 221, 219, 216, 218, 216, 216, 216, 213, 212, 215,
-  26, 32, 32, 26, 46, 41, 29, 35, 38, 68, 101, 98, 94, 96, 117, 129,
-  139, 153, 158, 167, 177, 177, 181, 179, 182, 181, 181, 184, 171, 167, 149, 127,
-  103, 71, 43, 52, 68, 101, 105, 91, 98, 66, 57, 94, 96, 89, 41, 41,
-  23, 23, 71, 91, 26, 32, 46, 55, 60, 185, 98, 84, 123, 129, 112, 158,
-  133, 131, 119, 117, 76, 74, 149, 127, 81, 125, 105, 81, 105, 125, 197, 129,
-  43, 49, 35, 38, 49, 35, 29, 32, 26, 41, 57, 35, 43, 29, 32, 52,
-  29, 35, 46, 29, 26, 32, 29, 38, 38, 43, 57, 38, 29, 32, 46, 38,
-  43, 35, 26, 57, 55, 23, 49, 57, 79, 81, 91, 96, 96, 105, 114, 121,
-  123, 123, 129, 131, 133, 135, 135, 139, 135, 145, 145, 155, 156, 155, 153, 158,
-  169, 169, 171, 169, 167, 156, 165, 164, 160, 147, 149, 149, 114, 20, 18, 68,
-  29, 35, 29, 26, 32, 46, 55, 49, 46, 29, 43, 66, 26, 32, 20, 89,
-  98, 74, 71, 79, 68, 55, 66, 89, 32, 49, 35, 26, 149, 182, 169, 171,
-  147, 155, 162, 174, 169, 171, 160, 165, 164, 167, 167, 162, 162, 164, 162, 162,
-  164, 162, 155, 162, 156, 160, 158, 153, 155, 151, 149, 153, 143, 149, 137, 131,
-  129, 131, 179, 213, 222, 225, 225, 225, 224, 222, 224, 219, 221, 219, 219, 219,
-  221, 219, 221, 221, 219, 219, 218, 218, 215, 216, 216, 213, 215, 212, 216, 210,
-  32, 29, 23, 23, 32, 26, 41, 32, 32, 79, 98, 105, 101, 89, 110, 133,
-  135, 147, 158, 165, 179, 179, 177, 184, 177, 179, 184, 182, 172, 162, 153, 125,
-  101, 66, 46, 49, 71, 101, 105, 103, 79, 43, 79, 38, 101, 96, 32, 43,
-  41, 18, 60, 81, 23, 29, 43, 68, 74, 169, 119, 66, 60, 68, 135, 131,
-  147, 137, 131, 131, 112, 63, 127, 147, 74, 141, 110, 49, 89, 129, 209, 81,
-  46, 55, 29, 41, 46, 43, 35, 46, 29, 43, 57, 46, 41, 18, 32, 41,
-  38, 29, 38, 38, 35, 32, 35, 32, 35, 49, 49, 52, 35, 38, 60, 43,
-  57, 49, 23, 60, 66, 29, 29, 35, 52, 71, 91, 84, 89, 98, 105, 117,
-  114, 119, 123, 123, 135, 137, 141, 141, 139, 149, 147, 162, 167, 169, 162, 162,
-  164, 167, 162, 160, 169, 165, 165, 169, 158, 139, 156, 147, 43, 26, 35, 55,
-  35, 35, 43, 32, 43, 41, 66, 46, 57, 20, 41, 49, 35, 35, 35, 94,
-  108, 91, 66, 74, 57, 68, 57, 68, 35, 84, 26, 29, 155, 185, 164, 165,
-  145, 162, 156, 167, 167, 169, 167, 164, 156, 160, 158, 162, 158, 158, 160, 160,
-  162, 160, 162, 164, 156, 158, 153, 153, 153, 149, 153, 143, 139, 145, 139, 135,
-  123, 135, 190, 213, 225, 230, 224, 225, 222, 219, 219, 219, 221, 218, 221, 221,
-  221, 222, 221, 219, 216, 215, 218, 215, 213, 213, 213, 215, 213, 213, 212, 212,
-  29, 26, 35, 35, 26, 23, 26, 38, 35, 79, 79, 89, 91, 94, 119, 129,
-  133, 149, 155, 172, 177, 181, 181, 179, 181, 181, 185, 179, 174, 165, 145, 129,
-  105, 71, 55, 57, 71, 91, 91, 76, 66, 52, 63, 29, 131, 81, 43, 55,
-  38, 35, 63, 81, 26, 43, 43, 46, 94, 167, 108, 66, 38, 41, 71, 121,
-  151, 156, 112, 139, 143, 110, 105, 156, 114, 145, 127, 91, 68, 89, 94, 46,
-  119, 38, 43, 41, 57, 38, 29, 46, 43, 43, 46, 49, 52, 32, 29, 52,
-  32, 46, 26, 49, 35, 32, 41, 38, 49, 35, 43, 38, 38, 43, 46, 46,
-  43, 55, 38, 46, 63, 49, 38, 20, 26, 46, 66, 68, 76, 91, 108, 110,
-  119, 123, 127, 127, 133, 127, 139, 139, 141, 143, 155, 156, 169, 179, 167, 165,
-  167, 165, 167, 165, 169, 176, 179, 165, 156, 145, 156, 135, 26, 26, 38, 41,
-  43, 52, 43, 38, 43, 38, 55, 68, 35, 20, 41, 43, 29, 35, 35, 86,
-  105, 68, 71, 68, 66, 74, 63, 84, 26, 81, 43, 18, 139, 184, 165, 171,
-  149, 156, 165, 171, 169, 169, 169, 165, 162, 158, 162, 162, 167, 165, 164, 160,
-  160, 164, 164, 160, 160, 158, 155, 153, 151, 149, 151, 151, 143, 141, 147, 133,
-  127, 137, 195, 216, 225, 228, 227, 222, 219, 219, 218, 218, 219, 221, 221, 222,
-  221, 222, 219, 218, 216, 213, 210, 218, 212, 210, 210, 212, 210, 209, 206, 201,
-  32, 23, 29, 38, 35, 29, 29, 26, 52, 66, 74, 86, 96, 94, 117, 131,
-  141, 145, 160, 174, 176, 184, 181, 181, 182, 181, 182, 182, 172, 162, 149, 125,
-  96, 63, 49, 55, 68, 89, 123, 38, 38, 43, 41, 41, 141, 103, 23, 49,
-  60, 38, 46, 63, 38, 35, 26, 20, 105, 164, 137, 86, 38, 63, 57, 98,
-  112, 141, 131, 139, 147, 121, 119, 135, 143, 147, 101, 105, 86, 133, 49, 63,
-  43, 43, 35, 43, 46, 52, 38, 41, 32, 35, 43, 52, 32, 26, 49, 66,
-  38, 38, 41, 60, 41, 32, 32, 29, 38, 41, 49, 26, 57, 35, 43, 43,
-  38, 63, 41, 35, 55, 55, 20, 29, 23, 26, 41, 66, 71, 79, 96, 110,
-  112, 114, 125, 127, 127, 129, 131, 147, 133, 141, 147, 147, 153, 167, 160, 169,
-  169, 172, 171, 165, 171, 171, 171, 156, 141, 145, 139, 110, 18, 23, 60, 32,
-  46, 49, 52, 46, 41, 49, 49, 74, 38, 32, 41, 41, 35, 23, 46, 108,
-  105, 60, 68, 57, 55, 74, 68, 66, 38, 84, 32, 26, 141, 184, 167, 164,
-  151, 155, 160, 165, 165, 165, 167, 160, 155, 160, 162, 158, 162, 165, 162, 155,
-  164, 156, 160, 156, 153, 153, 153, 153, 147, 147, 149, 145, 145, 137, 133, 131,
-  127, 143, 200, 219, 231, 228, 225, 221, 219, 218, 221, 219, 221, 222, 222, 222,
-  221, 219, 219, 215, 215, 210, 213, 215, 212, 209, 207, 206, 201, 192, 187, 167,
-  38, 38, 29, 32, 26, 20, 26, 46, 35, 43, 74, 86, 91, 105, 127, 125,
-  137, 151, 158, 172, 172, 177, 176, 176, 179, 179, 182, 181, 177, 165, 151, 133,
-  101, 68, 38, 55, 46, 103, 94, 52, 32, 35, 60, 49, 112, 96, 32, 55,
-  66, 43, 71, 60, 38, 35, 41, 23, 74, 165, 133, 125, 46, 74, 71, 108,
-  103, 91, 133, 135, 164, 147, 156, 117, 143, 145, 174, 76, 71, 96, 94, 57,
-  49, 57, 46, 49, 49, 46, 43, 41, 52, 52, 55, 68, 35, 26, 26, 60,
-  29, 35, 49, 35, 43, 29, 29, 38, 29, 35, 52, 38, 49, 63, 38, 49,
-  49, 60, 41, 49, 74, 63, 46, 41, 38, 26, 26, 29, 66, 74, 86, 91,
-  98, 103, 119, 117, 127, 121, 133, 131, 135, 145, 141, 149, 155, 156, 165, 165,
-  164, 174, 164, 165, 165, 165, 158, 151, 143, 147, 141, 101, 26, 32, 55, 43,
-  52, 55, 55, 57, 49, 49, 41, 74, 43, 43, 29, 32, 43, 41, 55, 101,
-  103, 84, 68, 63, 66, 71, 79, 81, 52, 96, 46, 26, 139, 181, 160, 167,
-  147, 151, 149, 156, 155, 156, 156, 156, 162, 160, 156, 160, 162, 160, 160, 155,
-  155, 160, 156, 160, 158, 153, 156, 151, 149, 151, 147, 147, 147, 141, 135, 131,
-  127, 156, 206, 219, 228, 228, 225, 221, 218, 218, 221, 221, 221, 222, 221, 221,
-  219, 219, 216, 216, 212, 213, 212, 210, 209, 203, 190, 182, 158, 135, 98, 46,
-  23, 26, 32, 32, 41, 32, 20, 43, 29, 41, 63, 91, 96, 103, 117, 123,
-  137, 155, 160, 169, 174, 176, 179, 172, 181, 177, 181, 177, 177, 165, 145, 125,
-  94, 71, 32, 49, 98, 133, 81, 86, 35, 26, 63, 98, 74, 71, 52, 46,
-  66, 52, 86, 46, 38, 26, 43, 12, 38, 181, 129, 143, 55, 57, 74, 63,
-  86, 129, 139, 91, 110, 167, 121, 133, 131, 160, 169, 121, 129, 125, 139, 63,
-  43, 35, 41, 57, 41, 38, 43, 38, 41, 41, 52, 74, 29, 35, 35, 71,
-  41, 35, 35, 43, 43, 38, 35, 41, 23, 35, 46, 41, 49, 49, 38, 49,
-  55, 57, 41, 41, 49, 63, 60, 43, 29, 20, 20, 41, 43, 49, 52, 55,
-  46, 60, 84, 84, 108, 117, 117, 114, 131, 129, 137, 145, 147, 149, 155, 162,
-  167, 164, 164, 149, 153, 153, 158, 143, 139, 137, 135, 84, 23, 29, 46, 41,
-  52, 43, 46, 52, 41, 32, 43, 52, 35, 41, 38, 29, 41, 57, 46, 96,
-  103, 81, 68, 71, 63, 81, 76, 86, 35, 89, 43, 26, 153, 179, 158, 162,
-  151, 141, 135, 139, 147, 149, 149, 151, 151, 153, 158, 164, 160, 160, 167, 155,
-  164, 158, 156, 158, 160, 158, 155, 151, 149, 151, 151, 145, 147, 137, 133, 127,
-  129, 174, 209, 221, 227, 227, 222, 221, 218, 219, 219, 219, 221, 219, 221, 218,
-  218, 215, 215, 213, 212, 209, 204, 200, 193, 176, 149, 105, 49, 35, 35, 23,
-  32, 32, 26, 35, 23, 20, 29, 43, 18, 52, 52, 91, 94, 81, 112, 127,
-  135, 149, 160, 167, 176, 179, 177, 174, 177, 179, 184, 179, 169, 162, 145, 123,
-  94, 46, 55, 108, 185, 153, 98, 172, 32, 26, 35, 76, 66, 49, 57, 49,
-  35, 68, 49, 32, 43, 35, 29, 18, 29, 176, 151, 169, 91, 76, 101, 57,
-  57, 125, 123, 114, 74, 149, 94, 141, 155, 179, 156, 149, 164, 185, 165, 143,
-  49, 35, 35, 38, 49, 41, 49, 46, 38, 63, 57, 68, 38, 26, 29, 89,
-  35, 32, 38, 32, 43, 41, 35, 38, 32, 32, 41, 29, 43, 52, 52, 57,
-  49, 49, 52, 38, 38, 57, 71, 60, 57, 41, 38, 49, 38, 49, 52, 66,
-  91, 74, 89, 96, 96, 105, 114, 110, 123, 121, 125, 133, 145, 143, 145, 153,
-  162, 162, 158, 145, 137, 149, 145, 133, 133, 133, 123, 84, 52, 41, 43, 41,
-  49, 52, 49, 60, 43, 49, 43, 55, 46, 41, 26, 41, 29, 57, 46, 89,
-  112, 74, 81, 79, 68, 63, 71, 96, 52, 63, 57, 41, 149, 185, 158, 153,
-  145, 133, 114, 125, 127, 141, 139, 137, 147, 143, 153, 151, 156, 155, 153, 155,
-  158, 160, 156, 160, 156, 156, 155, 149, 153, 145, 143, 143, 139, 131, 129, 123,
-  129, 190, 213, 221, 227, 224, 221, 218, 218, 219, 219, 218, 219, 219, 216, 216,
-  216, 215, 212, 209, 206, 198, 185, 165, 139, 91, 43, 20, 12, 23, 26, 20,
-  26, 29, 32, 26, 20, 20, 26, 23, 18, 32, 63, 79, 89, 89, 94, 121,
-  141, 149, 164, 169, 177, 181, 174, 176, 176, 181, 179, 174, 169, 162, 141, 114,
-  81, 57, 123, 210, 172, 63, 60, 162, 41, 23, 20, 68, 91, 35, 38, 63,
-  43, 68, 49, 41, 29, 32, 26, 20, 32, 165, 145, 164, 151, 81, 84, 60,
-  38, 91, 155, 131, 57, 114, 141, 79, 156, 162, 158, 129, 68, 117, 162, 174,
-  117, 57, 35, 23, 32, 43, 35, 35, 35, 76, 63, 68, 35, 23, 35, 63,
-  41, 35, 38, 29, 43, 46, 23, 38, 35, 20, 38, 35, 41, 46, 49, 52,
-  57, 43, 46, 46, 35, 57, 76, 71, 52, 60, 76, 108, 105, 105, 112, 129,
-  117, 131, 129, 141, 131, 131, 135, 143, 133, 147, 143, 169, 156, 165, 160, 164,
-  167, 171, 172, 174, 177, 177, 177, 162, 165, 171, 153, 112, 66, 57, 46, 46,
-  66, 55, 55, 43, 49, 43, 46, 55, 46, 38, 29, 29, 26, 66, 43, 91,
-  121, 74, 84, 76, 74, 71, 81, 79, 55, 63, 49, 46, 158, 182, 164, 145,
-  127, 133, 114, 112, 119, 125, 127, 129, 131, 151, 135, 139, 147, 145, 149, 149,
-  151, 156, 162, 160, 155, 155, 155, 149, 155, 147, 143, 145, 141, 135, 123, 125,
-  143, 198, 216, 224, 227, 222, 218, 218, 219, 218, 218, 216, 215, 216, 216, 213,
-  216, 212, 207, 200, 190, 176, 143, 94, 49, 38, 23, 23, 23, 23, 29, 35,
-  35, 52, 43, 35, 32, 18, 26, 20, 26, 35, 55, 66, 71, 63, 96, 125,
-  137, 153, 160, 169, 172, 174, 176, 176, 174, 177, 177, 181, 169, 156, 139, 110,
-  94, 137, 215, 171, 91, 49, 94, 155, 60, 66, 18, 63, 91, 63, 60, 60,
-  63, 38, 38, 55, 35, 35, 32, 35, 43, 158, 129, 121, 167, 98, 74, 76,
-  46, 57, 91, 91, 81, 153, 171, 96, 86, 167, 179, 151, 66, 55, 55, 176,
-  172, 160, 68, 26, 29, 29, 29, 41, 38, 63, 74, 57, 29, 20, 41, 74,
-  35, 26, 23, 29, 35, 38, 26, 32, 32, 26, 35, 35, 38, 43, 49, 38,
-  52, 43, 35, 29, 32, 32, 57, 74, 81, 79, 101, 103, 117, 117, 125, 125,
-  123, 129, 143, 135, 135, 137, 135, 139, 135, 137, 135, 151, 155, 160, 155, 153,
-  151, 158, 156, 160, 164, 160, 172, 176, 185, 195, 203, 203, 190, 155, 96, 66,
-  57, 49, 41, 60, 41, 38, 49, 52, 38, 41, 20, 43, 32, 68, 43, 86,
-  112, 79, 84, 74, 66, 76, 74, 94, 66, 71, 55, 57, 164, 164, 169, 135,
-  117, 125, 119, 101, 114, 110, 114, 127, 125, 125, 114, 129, 129, 133, 135, 141,
-  143, 145, 153, 151, 149, 149, 151, 153, 147, 147, 147, 137, 139, 133, 131, 123,
-  155, 201, 219, 224, 224, 216, 215, 216, 216, 215, 221, 216, 215, 215, 215, 212,
-  212, 207, 200, 184, 176, 145, 98, 41, 23, 38, 32, 55, 23, 32, 57, 52,
-  43, 38, 41, 68, 49, 35, 26, 26, 20, 43, 46, 60, 63, 60, 91, 125,
-  135, 151, 156, 169, 174, 176, 177, 179, 174, 182, 182, 177, 171, 155, 135, 123,
-  160, 222, 167, 52, 76, 57, 84, 89, 20, 29, 23, 52, 101, 71, 43, 55,
-  84, 43, 46, 94, 49, 35, 32, 38, 52, 141, 133, 119, 151, 158, 96, 68,
-  23, 26, 79, 137, 119, 172, 123, 86, 101, 137, 169, 125, 147, 89, 43, 89,
-  182, 185, 165, 60, 38, 41, 43, 41, 43, 57, 84, 49, 41, 38, 49, 96,
-  29, 35, 38, 41, 35, 43, 35, 23, 26, 29, 41, 35, 41, 43, 46, 35,
-  29, 55, 38, 23, 38, 23, 55, 71, 74, 96, 105, 112, 125, 123, 123, 117,
-  125, 125, 127, 131, 131, 137, 135, 133, 139, 139, 147, 151, 151, 156, 155, 149,
-  151, 149, 149, 149, 151, 162, 172, 179, 185, 200, 198, 204, 206, 204, 206, 177,
-  114, 66, 43, 49, 41, 29, 35, 46, 29, 29, 23, 32, 38, 38, 49, 86,
-  119, 66, 81, 71, 60, 71, 71, 86, 63, 74, 60, 49, 169, 158, 165, 127,
-  121, 123, 123, 112, 112, 117, 112, 121, 110, 117, 117, 121, 117, 125, 121, 125,
-  131, 139, 137, 141, 143, 147, 149, 147, 143, 151, 143, 135, 137, 133, 125, 123,
-  165, 207, 218, 224, 221, 215, 215, 215, 215, 218, 216, 215, 215, 213, 210, 212,
-  206, 201, 193, 181, 155, 117, 57, 29, 20, 18, 18, 35, 46, 57, 71, 71,
-  55, 52, 71, 60, 43, 32, 35, 29, 23, 23, 43, 66, 57, 63, 81, 114,
-  127, 139, 155, 164, 174, 176, 176, 174, 171, 172, 179, 171, 167, 160, 141, 160,
-  212, 108, 32, 71, 66, 32, 171, 35, 20, 26, 12, 46, 91, 66, 60, 52,
-  63, 29, 41, 63, 89, 52, 26, 38, 49, 86, 143, 143, 108, 147, 149, 74,
-  32, 52, 91, 141, 162, 177, 60, 105, 86, 103, 129, 143, 79, 119, 71, 74,
-  145, 141, 177, 167, 43, 29, 32, 43, 71, 57, 96, 43, 35, 26, 46, 79,
-  41, 32, 43, 41, 29, 35, 46, 46, 26, 41, 43, 52, 46, 35, 49, 55,
-  43, 41, 35, 52, 26, 38, 66, 79, 74, 94, 114, 114, 127, 127, 123, 114,
-  121, 125, 135, 127, 129, 133, 135, 131, 129, 137, 139, 145, 153, 149, 141, 143,
-  145, 141, 139, 143, 149, 162, 177, 177, 190, 200, 203, 204, 204, 204, 210, 212,
-  212, 187, 121, 71, 57, 49, 43, 46, 52, 38, 46, 55, 41, 55, 86, 89,
-  123, 66, 74, 81, 60, 79, 68, 86, 66, 76, 79, 63, 185, 151, 153, 133,
-  133, 139, 129, 137, 119, 125, 114, 117, 119, 117, 114, 117, 114, 114, 112, 114,
-  114, 114, 125, 123, 127, 133, 127, 133, 141, 141, 139, 137, 133, 133, 125, 121,
-  174, 206, 216, 222, 219, 213, 213, 213, 215, 218, 215, 213, 215, 216, 210, 206,
-  198, 197, 182, 165, 123, 66, 26, 15, 29, 35, 43, 46, 63, 79, 79, 66,
-  94, 79, 63, 68, 46, 32, 41, 41, 35, 32, 55, 63, 38, 38, 71, 98,
-  121, 141, 156, 167, 177, 176, 171, 171, 176, 174, 179, 176, 171, 160, 185, 212,
-  117, 57, 38, 63, 38, 105, 179, 38, 23, 26, 15, 43, 91, 71, 26, 41,
-  52, 41, 49, 60, 108, 63, 52, 57, 43, 41, 71, 143, 135, 79, 145, 147,
-  133, 129, 129, 171, 185, 98, 79, 79, 133, 89, 96, 141, 137, 60, 101, 121,
-  174, 125, 86, 184, 139, 57, 32, 41, 43, 52, 74, 32, 20, 23, 49, 94,
-  41, 29, 46, 32, 32, 26, 43, 35, 29, 46, 41, 23, 43, 32, 52, 49,
-  43, 41, 46, 35, 43, 32, 55, 76, 84, 96, 101, 121, 121, 121, 114, 121,
-  114, 119, 119, 127, 127, 131, 129, 135, 135, 137, 137, 147, 141, 135, 143, 139,
-  141, 143, 141, 151, 151, 169, 176, 184, 193, 198, 200, 204, 206, 204, 207, 209,
-  209, 209, 207, 193, 131, 60, 41, 26, 41, 20, 41, 23, 35, 38, 79, 68,
-  125, 57, 68, 76, 66, 74, 76, 74, 57, 74, 68, 68, 189, 155, 151, 131,
-  137, 143, 137, 139, 137, 131, 131, 125, 129, 114, 114, 105, 110, 103, 112, 108,
-  105, 110, 112, 119, 117, 125, 123, 123, 125, 121, 125, 123, 131, 121, 117, 123,
-  172, 207, 215, 218, 213, 212, 213, 213, 215, 216, 218, 215, 216, 215, 212, 204,
-  193, 182, 155, 114, 60, 12, 18, 26, 41, 49, 49, 60, 74, 81, 81, 91,
-  131, 125, 101, 94, 76, 66, 55, 41, 35, 35, 41, 35, 32, 29, 49, 81,
-  110, 133, 155, 165, 171, 171, 172, 169, 176, 177, 172, 179, 184, 193, 176, 125,
-  101, 63, 57, 91, 81, 165, 84, 29, 35, 38, 23, 23, 46, 84, 49, 66,
-  26, 29, 41, 49, 112, 79, 68, 52, 79, 29, 18, 125, 147, 125, 89, 57,
-  96, 133, 135, 176, 147, 52, 79, 112, 71, 123, 119, 112, 127, 103, 127, 160,
-  207, 129, 91, 63, 193, 89, 23, 26, 29, 49, 81, 41, 29, 41, 43, 91,
-  29, 32, 38, 23, 35, 23, 32, 38, 35, 26, 41, 29, 38, 38, 52, 52,
-  43, 43, 35, 41, 46, 32, 46, 63, 74, 103, 117, 119, 103, 121, 117, 121,
-  121, 117, 119, 123, 139, 135, 129, 129, 135, 133, 133, 139, 133, 139, 135, 135,
-  139, 141, 141, 147, 153, 169, 176, 187, 192, 195, 203, 203, 206, 206, 207, 207,
-  209, 207, 209, 212, 212, 193, 129, 57, 38, 23, 26, 18, 23, 32, 76, 68,
-  123, 52, 76, 71, 63, 71, 76, 66, 49, 66, 63, 76, 187, 156, 151, 131,
-  139, 145, 137, 139, 151, 133, 133, 131, 131, 119, 117, 110, 112, 105, 105, 94,
-  96, 101, 96, 89, 98, 105, 105, 105, 103, 110, 110, 112, 110, 101, 108, 98,
-  169, 201, 213, 216, 213, 210, 209, 213, 215, 215, 215, 215, 215, 215, 212, 201,
-  187, 160, 94, 32, 26, 29, 32, 46, 46, 55, 55, 76, 71, 68, 79, 79,
-  139, 137, 137, 117, 94, 84, 76, 60, 46, 55, 46, 29, 29, 29, 52, 76,
-  103, 133, 151, 162, 172, 172, 176, 179, 177, 172, 177, 193, 195, 165, 155, 125,
-  103, 66, 71, 121, 193, 96, 29, 18, 23, 23, 20, 29, 26, 57, 101, 121,
-  6, 18, 35, 41, 127, 101, 74, 57, 117, 15, 12, 46, 145, 143, 129, 89,
-  74, 101, 84, 155, 46, 110, 103, 103, 103, 105, 137, 121, 121, 121, 119, 101,
-  189, 79, 86, 76, 76, 164, 38, 32, 35, 46, 86, 38, 32, 15, 46, 96,
-  29, 29, 32, 23, 38, 32, 38, 41, 43, 35, 32, 26, 35, 46, 38, 52,
-  38, 63, 52, 32, 41, 29, 35, 68, 86, 101, 103, 108, 114, 121, 114, 119,
-  117, 121, 125, 123, 129, 131, 125, 127, 133, 137, 139, 131, 145, 139, 137, 137,
-  147, 141, 147, 153, 160, 176, 182, 190, 193, 200, 200, 203, 201, 203, 207, 206,
-  209, 209, 207, 210, 209, 213, 215, 185, 98, 49, 23, 18, 18, 38, 66, 91,
-  114, 55, 68, 68, 66, 66, 71, 66, 55, 63, 74, 91, 182, 153, 153, 135,
-  151, 147, 143, 145, 143, 143, 143, 141, 139, 131, 139, 131, 123, 112, 117, 105,
-  108, 96, 98, 96, 96, 101, 96, 86, 98, 94, 114, 119, 105, 91, 71, 86,
-  149, 201, 213, 215, 213, 210, 212, 215, 216, 213, 215, 212, 213, 209, 203, 189,
-  165, 105, 20, 23, 23, 55, 49, 57, 55, 71, 74, 79, 74, 71, 74, 74,
-  153, 145, 139, 149, 123, 112, 89, 79, 63, 71, 63, 41, 35, 26, 52, 84,
-  103, 135, 155, 162, 167, 171, 171, 172, 172, 169, 181, 181, 176, 164, 147, 123,
-  96, 76, 131, 81, 218, 41, 32, 29, 23, 35, 29, 26, 23, 43, 79, 137,
-  15, 18, 20, 35, 131, 117, 68, 76, 131, 41, 32, 20, 52, 137, 143, 153,
-  110, 94, 127, 162, 60, 46, 135, 119, 110, 131, 68, 167, 125, 131, 143, 135,
-  149, 179, 76, 26, 108, 108, 137, 38, 35, 49, 76, 41, 26, 18, 49, 71,
-  41, 35, 52, 26, 41, 26, 43, 46, 43, 49, 49, 35, 41, 41, 43, 41,
-  60, 66, 55, 35, 46, 35, 43, 66, 101, 98, 105, 105, 110, 117, 114, 121,
-  125, 123, 131, 129, 125, 135, 127, 135, 129, 139, 135, 131, 135, 137, 135, 139,
-  139, 147, 151, 164, 164, 171, 177, 190, 193, 197, 200, 197, 197, 200, 206, 204,
-  206, 207, 207, 207, 209, 212, 215, 215, 210, 149, 49, 26, 20, 46, 57, 89,
-  105, 55, 63, 63, 66, 63, 60, 43, 68, 55, 60, 103, 172, 149, 141, 143,
-  153, 156, 145, 151, 147, 151, 145, 141, 137, 141, 141, 137, 129, 129, 127, 117,
-  114, 112, 101, 96, 101, 96, 98, 89, 89, 98, 123, 121, 117, 94, 68, 76,
-  151, 203, 213, 215, 213, 209, 213, 218, 216, 213, 215, 212, 210, 200, 187, 162,
-  117, 55, 23, 41, 57, 71, 71, 66, 71, 63, 76, 84, 74, 74, 84, 84,
-  153, 149, 155, 149, 143, 129, 114, 96, 84, 81, 74, 60, 29, 20, 49, 74,
-  103, 133, 156, 165, 169, 174, 176, 174, 172, 176, 177, 177, 172, 165, 149, 125,
-  105, 114, 169, 108, 167, 32, 20, 32, 23, 29, 26, 26, 55, 98, 89, 110,
-  20, 15, 15, 55, 149, 101, 66, 119, 66, 38, 32, 26, 105, 94, 43, 91,
-  117, 131, 149, 76, 57, 84, 57, 143, 125, 121, 96, 119, 179, 125, 143, 129,
-  103, 141, 165, 38, 35, 101, 179, 63, 46, 55, 46, 43, 29, 32, 41, 66,
-  29, 38, 46, 41, 49, 38, 35, 41, 52, 68, 38, 38, 26, 43, 38, 41,
-  49, 60, 79, 43, 41, 35, 41, 81, 84, 91, 117, 114, 105, 108, 110, 114,
-  117, 125, 117, 119, 131, 129, 131, 137, 135, 139, 141, 135, 135, 127, 135, 141,
-  141, 145, 155, 158, 171, 179, 182, 187, 192, 198, 197, 197, 193, 201, 203, 201,
-  204, 206, 207, 210, 209, 212, 213, 213, 218, 216, 177, 68, 35, 23, 43, 43,
-  101, 63, 74, 76, 66, 76, 89, 63, 66, 43, 57, 121, 167, 153, 137, 147,
-  153, 153, 155, 155, 149, 149, 141, 149, 141, 141, 141, 139, 137, 135, 133, 127,
-  129, 121, 117, 105, 103, 114, 94, 79, 108, 103, 135, 131, 112, 108, 63, 74,
-  160, 203, 215, 215, 213, 212, 218, 219, 218, 216, 215, 213, 203, 176, 141, 84,
-  26, 18, 38, 55, 71, 74, 71, 79, 79, 79, 79, 79, 91, 79, 74, 68,
-  149, 139, 155, 155, 156, 145, 135, 119, 96, 98, 79, 68, 26, 18, 41, 74,
-  110, 131, 149, 164, 169, 176, 172, 172, 174, 174, 179, 174, 171, 158, 141, 121,
-  149, 153, 105, 129, 84, 23, 32, 32, 32, 20, 15, 18, 26, 105, 143, 135,
-  114, 91, 108, 147, 114, 49, 57, 60, 81, 32, 29, 98, 127, 46, 46, 84,
-  145, 121, 79, 52, 84, 76, 84, 79, 127, 133, 121, 145, 151, 153, 137, 158,
-  46, 43, 135, 135, 35, 38, 105, 158, 35, 49, 57, 46, 43, 29, 57, 66,
-  46, 46, 52, 41, 41, 29, 52, 49, 46, 60, 46, 43, 38, 35, 52, 55,
-  60, 38, 74, 60, 38, 49, 29, 86, 89, 94, 105, 108, 112, 108, 110, 125,
-  121, 117, 121, 123, 127, 133, 135, 141, 143, 141, 133, 127, 129, 133, 137, 141,
-  145, 151, 160, 165, 167, 172, 177, 184, 189, 197, 193, 195, 197, 197, 198, 201,
-  201, 204, 209, 209, 209, 210, 212, 210, 213, 216, 219, 195, 79, 35, 32, 29,
-  96, 52, 63, 60, 43, 57, 68, 63, 55, 29, 66, 141, 155, 149, 143, 158,
-  155, 156, 156, 155, 155, 149, 147, 153, 151, 145, 145, 143, 145, 139, 145, 135,
-  133, 123, 123, 125, 119, 110, 108, 96, 91, 110, 129, 139, 119, 94, 68, 94,
-  165, 207, 215, 218, 216, 218, 218, 219, 218, 216, 215, 212, 193, 149, 76, 60,
-  15, 35, 71, 76, 84, 71, 68, 63, 71, 81, 81, 98, 79, 79, 63, 74,
-  141, 139, 155, 160, 167, 162, 151, 137, 121, 110, 86, 63, 38, 20, 35, 76,
-  112, 137, 153, 165, 169, 176, 176, 174, 176, 177, 177, 179, 172, 160, 141, 125,
-  200, 207, 55, 94, 79, 43, 38, 23, 20, 23, 35, 20, 23, 52, 63, 68,
-  96, 127, 133, 101, 68, 81, 52, 52, 66, 49, 108, 143, 52, 29, 52, 137,
-  89, 46, 68, 43, 46, 79, 105, 76, 105, 125, 137, 147, 145, 143, 155, 156,
-  112, 23, 49, 192, 101, 26, 89, 192, 60, 52, 41, 32, 38, 38, 41, 66,
-  60, 32, 38, 41, 41, 26, 32, 38, 55, 49, 49, 46, 35, 38, 49, 43,
-  68, 49, 81, 91, 46, 26, 32, 84, 68, 105, 108, 108, 110, 119, 114, 123,
-  119, 119, 131, 133, 127, 129, 137, 137, 135, 135, 143, 135, 137, 137, 137, 141,
-  147, 156, 160, 167, 165, 172, 172, 181, 185, 190, 190, 190, 198, 198, 197, 197,
-  198, 203, 204, 209, 207, 209, 210, 213, 215, 216, 218, 219, 201, 79, 32, 29,
-  86, 49, 43, 66, 49, 63, 76, 49, 49, 18, 35, 141, 155, 155, 139, 155,
-  153, 158, 155, 153, 153, 147, 155, 155, 155, 153, 145, 145, 147, 141, 143, 135,
-  139, 135, 131, 129, 121, 127, 137, 105, 117, 121, 137, 141, 123, 96, 74, 121,
-  185, 212, 219, 218, 218, 218, 219, 219, 216, 215, 210, 206, 172, 123, 43, 20,
-  52, 74, 84, 89, 84, 76, 74, 71, 96, 98, 98, 94, 91, 76, 76, 86,
-  135, 147, 151, 158, 167, 165, 164, 153, 141, 123, 103, 60, 46, 20, 38, 74,
-  105, 131, 158, 167, 176, 174, 179, 174, 179, 176, 181, 177, 169, 160, 137, 137,
-  219, 179, 84, 57, 46, 52, 46, 29, 23, 26, 20, 23, 38, 81, 43, 20,
-  38, 76, 52, 55, 49, 38, 46, 81, 110, 123, 114, 68, 29, 15, 84, 172,
-  38, 41, 55, 86, 57, 55, 108, 110, 89, 91, 123, 145, 145, 143, 181, 147,
-  176, 35, 18, 151, 203, 46, 96, 103, 135, 41, 29, 32, 38, 35, 46, 76,
-  46, 41, 41, 41, 46, 49, 35, 29, 46, 55, 43, 35, 38, 38, 46, 55,
-  41, 60, 84, 89, 55, 26, 38, 68, 60, 110, 110, 105, 114, 127, 123, 103,
-  110, 127, 131, 135, 129, 131, 127, 131, 129, 137, 137, 133, 131, 135, 137, 145,
-  155, 153, 162, 167, 162, 169, 172, 177, 182, 187, 185, 192, 192, 192, 195, 195,
-  198, 203, 203, 203, 206, 210, 212, 209, 213, 213, 218, 219, 221, 201, 76, 41,
-  76, 57, 60, 63, 52, 74, 81, 68, 52, 26, 43, 153, 149, 158, 145, 158,
-  164, 160, 153, 153, 151, 151, 162, 153, 156, 151, 147, 149, 143, 143, 149, 147,
-  139, 137, 141, 135, 129, 129, 131, 117, 121, 129, 137, 139, 117, 112, 89, 143,
-  198, 210, 219, 219, 218, 218, 221, 218, 218, 212, 204, 193, 155, 81, 23, 23,
-  63, 74, 91, 81, 76, 71, 71, 89, 103, 101, 98, 91, 86, 91, 79, 98,
-  141, 133, 139, 156, 167, 169, 167, 162, 143, 145, 119, 84, 52, 15, 38, 71,
-  105, 131, 153, 165, 176, 182, 182, 177, 174, 181, 184, 172, 167, 164, 147, 156,
-  222, 137, 149, 174, 15, 20, 18, 35, 49, 46, 38, 41, 52, 74, 55, 29,
-  43, 101, 57, 41, 55, 57, 60, 41, 52, 41, 35, 35, 35, 26, 89, 160,
-  76, 23, 46, 86, 76, 68, 63, 119, 91, 79, 94, 137, 160, 139, 156, 151,
-  164, 121, 38, 60, 171, 160, 129, 55, 198, 43, 41, 32, 46, 43, 52, 66,
-  41, 43, 41, 52, 52, 43, 52, 55, 55, 60, 46, 43, 46, 49, 55, 68,
-  46, 66, 91, 98, 81, 41, 23, 49, 68, 112, 108, 114, 108, 114, 108, 105,
-  129, 123, 127, 131, 131, 131, 129, 133, 137, 137, 133, 135, 133, 143, 145, 145,
-  155, 156, 165, 165, 165, 174, 171, 171, 181, 182, 185, 182, 187, 193, 195, 197,
-  200, 200, 201, 206, 209, 207, 212, 213, 215, 216, 215, 218, 221, 222, 193, 49,
-  43, 52, 29, 49, 35, 55, 57, 68, 71, 23, 43, 171, 143, 155, 143, 156,
-  155, 156, 156, 156, 155, 149, 155, 149, 149, 151, 147, 145, 145, 149, 149, 143,
-  139, 141, 139, 137, 135, 137, 129, 131, 125, 131, 133, 137, 131, 110, 108, 165,
-  204, 216, 219, 221, 218, 219, 216, 221, 215, 210, 198, 176, 139, 57, 38, 41,
-  79, 81, 79, 86, 94, 84, 76, 96, 103, 112, 103, 89, 89, 76, 81, 89,
-  108, 114, 135, 149, 155, 160, 167, 169, 158, 160, 137, 103, 55, 20, 32, 81,
-  105, 131, 153, 167, 182, 176, 181, 182, 182, 177, 184, 177, 171, 162, 145, 137,
-  215, 103, 74, 207, 15, 20, 26, 32, 41, 43, 26, 38, 79, 63, 60, 41,
-  41, 46, 38, 32, 66, 94, 68, 49, 38, 26, 26, 57, 43, 29, 41, 86,
-  127, 38, 41, 66, 57, 63, 68, 76, 127, 98, 76, 127, 156, 143, 145, 137,
-  112, 141, 125, 96, 129, 165, 94, 35, 185, 86, 35, 41, 32, 29, 46, 63,
-  60, 46, 38, 49, 41, 29, 29, 43, 52, 63, 35, 52, 35, 38, 41, 60,
-  55, 66, 101, 103, 86, 46, 18, 49, 57, 119, 110, 112, 110, 108, 123, 125,
-  127, 123, 129, 131, 131, 135, 133, 135, 145, 129, 137, 141, 137, 141, 149, 147,
-  151, 162, 164, 162, 167, 169, 171, 172, 182, 176, 179, 182, 184, 184, 190, 189,
-  195, 198, 198, 203, 206, 210, 209, 209, 210, 215, 218, 218, 219, 222, 224, 177,
-  32, 41, 18, 29, 41, 68, 43, 57, 63, 29, 57, 179, 143, 143, 149, 160,
-  156, 160, 158, 160, 155, 151, 151, 149, 155, 153, 147, 151, 147, 149, 147, 141,
-  141, 141, 131, 139, 133, 135, 131, 135, 127, 131, 141, 139, 127, 114, 127, 184,
-  209, 219, 219, 219, 218, 221, 221, 221, 215, 206, 187, 155, 119, 57, 46, 74,
-  94, 94, 79, 86, 86, 81, 89, 103, 114, 110, 101, 94, 86, 81, 96, 101,
-  66, 76, 117, 137, 151, 167, 176, 177, 174, 171, 147, 117, 63, 18, 38, 79,
-  105, 135, 158, 167, 181, 181, 181, 179, 176, 182, 187, 174, 172, 160, 145, 137,
-  169, 114, 55, 91, 20, 18, 38, 32, 26, 38, 35, 29, 66, 41, 46, 55,
-  23, 41, 29, 26, 76, 105, 57, 57, 43, 20, 29, 49, 94, 32, 23, 55,
-  121, 110, 32, 49, 76, 74, 66, 66, 108, 127, 86, 123, 167, 137, 143, 151,
-  123, 158, 108, 108, 71, 110, 190, 26, 121, 172, 15, 20, 29, 20, 49, 63,
-  46, 41, 41, 26, 46, 32, 35, 35, 55, 68, 43, 38, 32, 23, 43, 68,
-  66, 68, 98, 117, 103, 46, 32, 29, 79, 103, 101, 105, 101, 117, 129, 125,
-  119, 131, 131, 135, 137, 133, 139, 133, 131, 131, 129, 133, 143, 139, 141, 149,
-  149, 151, 164, 160, 160, 165, 167, 172, 177, 182, 176, 184, 184, 185, 189, 190,
-  193, 197, 201, 203, 207, 209, 209, 212, 213, 215, 215, 218, 221, 221, 222, 224,
-  137, 46, 26, 20, 29, 57, 29, 43, 43, 18, 49, 182, 143, 149, 153, 156,
-  156, 156, 158, 156, 156, 153, 155, 149, 147, 155, 151, 149, 147, 149, 149, 145,
-  141, 145, 139, 143, 133, 135, 133, 135, 129, 135, 143, 139, 131, 121, 135, 198,
-  213, 219, 221, 219, 221, 219, 218, 218, 212, 200, 167, 133, 81, 55, 68, 79,
-  94, 84, 79, 84, 84, 94, 103, 108, 110, 110, 94, 86, 81, 79, 94, 101,
-  38, 43, 101, 127, 147, 162, 179, 177, 177, 167, 149, 131, 84, 18, 35, 74,
-  101, 137, 158, 169, 182, 181, 177, 179, 182, 182, 184, 177, 174, 156, 160, 141,
-  203, 131, 68, 52, 23, 23, 23, 23, 26, 43, 32, 55, 76, 35, 52, 41,
-  41, 26, 32, 35, 98, 112, 35, 76, 60, 20, 26, 43, 129, 38, 35, 35,
-  96, 86, 105, 35, 63, 74, 71, 71, 60, 127, 94, 131, 131, 127, 129, 164,
-  135, 179, 155, 145, 46, 52, 207, 86, 81, 216, 32, 18, 29, 32, 41, 57,
-  55, 46, 41, 41, 46, 29, 41, 49, 55, 60, 41, 52, 41, 23, 43, 66,
-  49, 71, 103, 114, 96, 60, 23, 35, 79, 89, 89, 89, 125, 125, 135, 125,
-  121, 127, 135, 129, 135, 127, 137, 131, 137, 131, 133, 137, 137, 141, 141, 147,
-  153, 153, 158, 164, 158, 162, 165, 167, 171, 179, 174, 182, 187, 184, 187, 197,
-  193, 197, 195, 201, 203, 203, 209, 207, 212, 213, 212, 218, 218, 218, 224, 225,
-  218, 81, 35, 26, 29, 52, 23, 41, 52, 20, 71, 177, 139, 143, 149, 155,
-  153, 156, 158, 155, 153, 153, 153, 158, 156, 151, 155, 149, 151, 155, 149, 143,
-  137, 147, 143, 137, 137, 137, 139, 133, 133, 139, 145, 147, 143, 135, 156, 201,
-  216, 224, 221, 218, 219, 219, 219, 216, 212, 197, 155, 103, 57, 57, 76, 96,
-  86, 81, 98, 86, 96, 105, 110, 119, 112, 96, 89, 91, 84, 101, 96, 103,
-  18, 29, 76, 121, 139, 167, 179, 179, 182, 172, 158, 137, 84, 20, 29, 76,
-  105, 139, 160, 169, 174, 181, 185, 182, 181, 184, 184, 176, 171, 165, 147, 137,
-  219, 112, 60, 101, 18, 15, 35, 23, 23, 46, 32, 84, 41, 41, 32, 71,
-  38, 38, 20, 35, 105, 112, 35, 55, 52, 26, 23, 20, 103, 81, 32, 26,
-  114, 52, 84, 98, 32, 101, 98, 86, 57, 94, 103, 129, 94, 112, 119, 149,
-  131, 181, 174, 123, 26, 20, 86, 153, 79, 219, 29, 15, 15, 18, 43, 49,
-  57, 55, 32, 38, 35, 26, 23, 32, 66, 60, 43, 43, 57, 26, 23, 41,
-  35, 86, 110, 123, 110, 71, 9, 15, 63, 98, 96, 110, 112, 123, 131, 127,
-  133, 127, 133, 129, 127, 131, 135, 137, 139, 137, 139, 133, 133, 137, 141, 147,
-  153, 153, 156, 158, 160, 165, 164, 167, 172, 171, 182, 179, 184, 181, 189, 190,
-  193, 197, 195, 203, 203, 206, 204, 209, 209, 213, 212, 215, 218, 219, 219, 227,
-  227, 192, 35, 18, 23, 49, 23, 32, 32, 15, 91, 171, 145, 147, 151, 158,
-  162, 151, 156, 153, 153, 153, 153, 147, 151, 155, 149, 147, 153, 147, 147, 145,
-  143, 153, 143, 145, 135, 143, 133, 133, 131, 135, 135, 141, 141, 139, 176, 206,
-  218, 222, 221, 218, 221, 218, 218, 215, 210, 189, 139, 76, 60, 68, 76, 91,
-  79, 89, 96, 86, 96, 108, 110, 108, 91, 84, 94, 89, 91, 96, 101, 98,
-  12, 20, 35, 76, 123, 164, 185, 184, 184, 176, 160, 145, 96, 18, 23, 66,
-  105, 139, 156, 169, 177, 182, 181, 179, 181, 185, 184, 182, 172, 167, 147, 129,
-  135, 162, 68, 129, 15, 15, 46, 32, 26, 35, 41, 84, 43, 26, 38, 41,
-  35, 35, 23, 35, 119, 123, 23, 41, 49, 29, 23, 15, 49, 98, 66, 18,
-  105, 60, 46, 105, 86, 74, 105, 110, 94, 55, 84, 127, 94, 119, 143, 112,
-  141, 158, 182, 129, 43, 12, 23, 149, 76, 227, 38, 41, 29, 20, 49, 60,
-  46, 63, 32, 35, 26, 26, 38, 41, 38, 91, 32, 41, 35, 29, 41, 41,
-  55, 94, 114, 112, 96, 71, 18, 20, 55, 103, 110, 101, 121, 125, 131, 121,
-  129, 125, 123, 129, 135, 139, 135, 129, 135, 137, 137, 147, 137, 143, 141, 149,
-  143, 147, 151, 156, 165, 164, 169, 171, 167, 172, 179, 181, 185, 182, 189, 187,
-  192, 198, 200, 200, 203, 203, 207, 209, 209, 212, 213, 215, 213, 218, 222, 227,
-  227, 222, 108, 26, 18, 29, 15, 41, 18, 12, 105, 158, 139, 145, 156, 162,
-  153, 155, 153, 153, 153, 151, 153, 151, 145, 149, 147, 145, 151, 147, 149, 147,
-  147, 149, 145, 143, 139, 135, 137, 129, 123, 135, 145, 156, 169, 171, 190, 206,
-  219, 222, 219, 222, 221, 216, 215, 215, 206, 171, 108, 66, 71, 76, 86, 76,
-  91, 89, 103, 105, 101, 112, 98, 98, 76, 79, 86, 98, 94, 101, 105, 108,
-  6, 9, 32, 46, 112, 160, 182, 182, 184, 176, 167, 139, 103, 15, 15, 52,
-  114, 139, 156, 165, 177, 184, 182, 179, 177, 179, 182, 185, 172, 167, 151, 135,
-  98, 212, 63, 52, 23, 26, 29, 20, 38, 43, 74, 41, 26, 29, 41, 35,
-  29, 35, 32, 29, 125, 123, 26, 35, 84, 52, 23, 12, 29, 26, 98, 89,
-  57, 71, 29, 79, 91, 86, 98, 127, 125, 119, 57, 94, 89, 110, 160, 129,
-  164, 165, 158, 52, 74, 12, 38, 145, 133, 225, 71, 12, 26, 20, 46, 63,
-  43, 71, 43, 26, 38, 29, 41, 41, 49, 60, 38, 43, 41, 26, 32, 32,
-  79, 84, 94, 110, 101, 86, 32, 18, 63, 94, 114, 114, 119, 119, 123, 119,
-  127, 131, 121, 119, 131, 129, 145, 135, 143, 135, 139, 133, 149, 147, 149, 149,
-  143, 149, 155, 155, 158, 167, 167, 162, 171, 174, 179, 177, 179, 184, 189, 185,
-  192, 197, 197, 200, 204, 203, 207, 207, 210, 212, 215, 213, 216, 219, 222, 221,
-  224, 227, 200, 26, 18, 26, 12, 29, 9, 18, 139, 158, 133, 149, 156, 156,
-  151, 153, 153, 155, 156, 153, 156, 155, 147, 153, 149, 147, 145, 141, 149, 149,
-  145, 141, 143, 141, 133, 139, 127, 127, 135, 137, 158, 171, 185, 195, 207, 213,
-  219, 221, 221, 219, 219, 219, 215, 212, 195, 153, 94, 68, 81, 91, 86, 79,
-  84, 96, 101, 108, 110, 114, 101, 84, 81, 86, 76, 98, 98, 103, 101, 96,
-  20, 20, 26, 43, 117, 164, 181, 185, 187, 184, 174, 153, 89, 12, 20, 46,
-  103, 143, 155, 167, 182, 182, 182, 184, 179, 182, 184, 181, 177, 167, 156, 133,
-  96, 127, 121, 29, 23, 29, 38, 26, 35, 52, 52, 49, 35, 41, 41, 43,
-  23, 35, 26, 43, 143, 125, 23, 32, 98, 41, 18, 23, 68, 26, 55, 94,
-  98, 98, 26, 74, 49, 112, 68, 123, 121, 114, 76, 79, 79, 91, 162, 176,
-  158, 169, 164, 49, 26, 81, 29, 114, 182, 219, 41, 12, 15, 12, 63, 46,
-  38, 86, 32, 32, 41, 20, 26, 43, 38, 60, 38, 32, 49, 57, 41, 38,
-  81, 103, 108, 94, 86, 81, 35, 41, 74, 89, 117, 114, 123, 119, 119, 112,
-  127, 123, 129, 129, 139, 133, 137, 131, 135, 137, 133, 139, 139, 149, 141, 139,
-  151, 149, 151, 155, 151, 160, 160, 162, 167, 169, 176, 176, 179, 187, 181, 189,
-  193, 193, 197, 198, 204, 203, 207, 209, 209, 215, 213, 218, 215, 216, 218, 222,
-  224, 225, 224, 98, 18, 23, 18, 20, 9, 18, 156, 155, 137, 147, 162, 156,
-  153, 149, 160, 156, 153, 156, 158, 149, 149, 149, 155, 151, 141, 147, 141, 147,
-  145, 137, 141, 141, 135, 129, 129, 125, 131, 160, 177, 190, 198, 204, 210, 216,
-  222, 224, 222, 221, 222, 215, 218, 206, 182, 127, 81, 86, 84, 94, 86, 81,
-  94, 94, 103, 110, 110, 108, 98, 86, 81, 94, 94, 110, 103, 98, 91, 105,
-  12, 20, 26, 41, 101, 160, 177, 187, 189, 187, 174, 147, 79, 20, 15, 57,
-  108, 141, 156, 164, 177, 187, 185, 184, 181, 182, 184, 179, 177, 169, 156, 143,
-  110, 103, 190, 32, 38, 35, 35, 35, 52, 60, 32, 43, 32, 32, 43, 35,
-  32, 41, 18, 76, 164, 117, 18, 20, 68, 63, 12, 20, 49, 12, 49, 43,
-  43, 74, 26, 79, 49, 89, 86, 110, 108, 105, 66, 98, 68, 103, 158, 160,
-  162, 133, 182, 108, 15, 63, 20, 108, 200, 207, 32, 15, 26, 18, 71, 71,
-  43, 105, 38, 43, 43, 41, 20, 29, 52, 46, 29, 20, 43, 26, 49, 55,
-  89, 108, 89, 89, 101, 91, 29, 32, 76, 76, 108, 114, 131, 129, 125, 119,
-  127, 129, 133, 135, 131, 131, 133, 129, 135, 137, 139, 135, 139, 137, 143, 145,
-  147, 153, 153, 158, 155, 156, 162, 164, 165, 165, 181, 176, 184, 181, 182, 192,
-  189, 193, 195, 197, 200, 206, 207, 209, 209, 213, 212, 215, 216, 218, 219, 222,
-  224, 225, 225, 189, 12, 12, 9, 18, 6, 26, 155, 160, 153, 155, 158, 160,
-  160, 164, 149, 156, 155, 155, 155, 151, 153, 153, 145, 147, 147, 145, 147, 145,
-  143, 141, 137, 141, 133, 129, 129, 127, 155, 181, 195, 204, 201, 209, 213, 219,
-  221, 221, 222, 219, 219, 215, 210, 197, 156, 96, 86, 89, 84, 89, 86, 96,
-  103, 103, 108, 110, 110, 96, 81, 76, 79, 86, 91, 108, 105, 89, 105, 96,
-  12, 12, 32, 57, 101, 155, 171, 185, 187, 182, 169, 143, 79, 9, 9, 43,
-  103, 143, 155, 171, 179, 182, 181, 179, 182, 187, 189, 185, 177, 167, 156, 135,
-  151, 135, 114, 41, 41, 32, 20, 35, 60, 32, 35, 41, 23, 18, 26, 41,
-  35, 38, 38, 112, 162, 103, 15, 18, 57, 74, 23, 38, 57, 38, 55, 49,
-  18, 35, 57, 41, 86, 63, 117, 94, 129, 94, 94, 84, 52, 105, 153, 158,
-  114, 143, 174, 125, 41, 35, 20, 84, 200, 172, 29, 12, 20, 23, 86, 81,
-  46, 81, 26, 43, 38, 43, 35, 32, 60, 55, 41, 23, 26, 46, 29, 76,
-  84, 79, 86, 112, 117, 89, 35, 32, 101, 89, 108, 121, 123, 121, 117, 121,
-  131, 129, 129, 133, 131, 135, 125, 129, 129, 135, 129, 131, 143, 151, 145, 145,
-  143, 147, 149, 155, 151, 153, 160, 164, 167, 171, 174, 177, 172, 181, 185, 187,
-  187, 192, 197, 198, 200, 203, 203, 204, 210, 212, 212, 215, 218, 216, 218, 221,
-  222, 225, 227, 221, 55, 15, 12, 12, 9, 35, 151, 156, 149, 147, 158, 153,
-  156, 162, 156, 158, 151, 153, 151, 149, 151, 151, 149, 149, 141, 141, 143, 141,
-  141, 143, 135, 135, 127, 137, 123, 141, 184, 203, 209, 209, 209, 210, 213, 221,
-  225, 224, 222, 221, 219, 213, 206, 177, 137, 86, 81, 86, 81, 91, 84, 96,
-  101, 108, 105, 117, 108, 86, 89, 84, 89, 94, 91, 105, 101, 96, 121, 114,
-  12, 12, 6, 29, 94, 151, 167, 179, 182, 185, 172, 149, 94, 15, 15, 43,
-  101, 133, 155, 169, 181, 185, 181, 185, 184, 182, 185, 184, 184, 172, 153, 135,
-  160, 117, 123, 26, 49, 32, 23, 60, 38, 32, 29, 41, 35, 23, 49, 20,
-  20, 23, 46, 137, 151, 84, 18, 35, 26, 63, 26, 52, 46, 41, 43, 52,
-  29, 35, 35, 29, 74, 38, 112, 101, 125, 103, 81, 91, 35, 103, 167, 143,
-  114, 171, 174, 137, 127, 38, 29, 108, 189, 86, 117, 23, 26, 20, 76, 68,
-  57, 68, 38, 43, 23, 35, 35, 29, 43, 41, 49, 38, 32, 49, 35, 66,
-  84, 96, 112, 114, 114, 91, 20, 23, 91, 101, 103, 125, 127, 125, 125, 129,
-  131, 127, 129, 133, 129, 131, 133, 125, 129, 127, 127, 135, 141, 141, 139, 145,
-  139, 147, 149, 151, 156, 153, 160, 162, 164, 169, 167, 172, 177, 181, 181, 181,
-  189, 195, 193, 193, 200, 203, 203, 207, 210, 212, 212, 215, 216, 216, 218, 219,
-  219, 224, 224, 227, 167, 23, 12, 6, 6, 43, 153, 143, 143, 158, 160, 158,
-  158, 158, 156, 156, 158, 158, 151, 153, 147, 149, 149, 143, 145, 139, 145, 143,
-  135, 137, 139, 139, 139, 125, 125, 164, 201, 213, 219, 216, 210, 210, 213, 219,
-  225, 222, 222, 221, 219, 210, 195, 158, 110, 86, 86, 86, 81, 79, 96, 94,
-  101, 110, 105, 110, 98, 91, 84, 84, 94, 103, 101, 105, 101, 91, 105, 103,
-  9, 18, 12, 23, 89, 145, 167, 179, 187, 185, 176, 153, 89, 12, 15, 35,
-  103, 131, 158, 171, 179, 182, 185, 185, 182, 187, 190, 181, 174, 169, 153, 135,
-  143, 141, 29, 20, 43, 20, 38, 49, 29, 20, 23, 29, 20, 15, 32, 20,
-  20, 20, 125, 143, 149, 105, 20, 18, 23, 43, 46, 63, 38, 46, 18, 35,
-  29, 43, 29, 35, 68, 41, 103, 76, 149, 127, 49, 49, 43, 74, 176, 151,
-  149, 171, 108, 57, 167, 121, 112, 182, 164, 84, 209, 60, 20, 29, 68, 63,
-  55, 43, 41, 49, 35, 52, 35, 32, 38, 35, 38, 46, 49, 41, 60, 84,
-  105, 110, 114, 129, 108, 94, 20, 35, 76, 98, 105, 125, 123, 127, 131, 131,
-  129, 131, 135, 127, 127, 131, 129, 133, 133, 127, 129, 135, 137, 141, 143, 141,
-  143, 145, 149, 151, 153, 155, 160, 165, 164, 167, 167, 165, 176, 179, 182, 185,
-  185, 193, 193, 195, 198, 201, 204, 207, 209, 210, 215, 216, 213, 219, 218, 221,
-  219, 221, 227, 227, 209, 15, 6, 6, 6, 74, 147, 145, 139, 171, 158, 160,
-  155, 153, 156, 151, 160, 149, 153, 153, 145, 147, 147, 151, 145, 143, 141, 141,
-  135, 135, 139, 127, 135, 125, 131, 182, 212, 219, 222, 222, 216, 212, 215, 221,
-  224, 222, 224, 221, 216, 206, 184, 137, 98, 86, 84, 84, 79, 89, 86, 103,
-  105, 105, 110, 110, 91, 81, 79, 79, 96, 101, 110, 108, 101, 103, 101, 101,
-  9, 15, 9, 23, 71, 135, 167, 181, 187, 184, 174, 156, 98, 15, 12, 32,
-  105, 135, 158, 167, 182, 184, 184, 184, 182, 184, 187, 187, 177, 167, 158, 137,
-  123, 129, 32, 29, 35, 46, 55, 20, 26, 18, 23, 23, 29, 38, 32, 23,
-  26, 81, 156, 76, 127, 55, 15, 23, 29, 29, 49, 74, 18, 49, 9, 20,
-  32, 43, 46, 23, 57, 55, 41, 41, 119, 147, 60, 60, 84, 101, 153, 155,
-  158, 169, 165, 63, 149, 55, 121, 181, 172, 165, 190, 32, 32, 32, 68, 38,
-  46, 29, 60, 46, 43, 66, 29, 41, 35, 29, 43, 55, 57, 43, 74, 105,
-  114, 117, 117, 112, 117, 79, 26, 68, 91, 105, 110, 114, 127, 119, 133, 135,
-  137, 125, 133, 131, 131, 129, 129, 133, 131, 129, 131, 131, 133, 137, 139, 141,
-  143, 143, 147, 149, 156, 158, 160, 162, 165, 171, 164, 167, 179, 181, 174, 187,
-  187, 192, 193, 195, 198, 200, 201, 206, 209, 213, 212, 215, 213, 218, 216, 219,
-  219, 221, 222, 227, 222, 71, 15, 6, 9, 89, 139, 145, 145, 169, 153, 160,
-  155, 156, 145, 151, 155, 153, 151, 153, 147, 147, 149, 149, 141, 139, 149, 137,
-  141, 135, 131, 133, 123, 123, 133, 193, 216, 224, 225, 222, 216, 216, 219, 222,
-  224, 224, 224, 219, 213, 197, 162, 119, 91, 86, 84, 86, 68, 96, 84, 105,
-  110, 114, 108, 96, 94, 86, 81, 94, 108, 101, 103, 105, 110, 98, 112, 81,
-  6, 9, 6, 26, 71, 133, 169, 184, 192, 189, 172, 156, 110, 23, 15, 35,
-  96, 137, 151, 172, 181, 179, 181, 177, 184, 182, 182, 185, 177, 171, 155, 139,
-  123, 119, 41, 38, 63, 38, 38, 26, 35, 57, 26, 23, 32, 26, 18, 26,
-  98, 133, 60, 57, 117, 55, 35, 29, 23, 41, 66, 66, 20, 41, 20, 35,
-  32, 46, 49, 18, 35, 68, 35, 55, 135, 125, 117, 81, 114, 101, 149, 147,
-  164, 143, 155, 149, 141, 131, 203, 179, 57, 23, 23, 20, 74, 46, 71, 32,
-  49, 43, 43, 32, 35, 46, 32, 57, 35, 35, 32, 38, 71, 63, 76, 114,
-  114, 119, 117, 108, 108, 84, 23, 79, 86, 98, 112, 114, 121, 125, 129, 131,
-  131, 131, 131, 129, 133, 135, 133, 133, 137, 141, 135, 129, 139, 139, 143, 141,
-  143, 143, 147, 149, 156, 153, 158, 160, 160, 162, 164, 167, 169, 177, 177, 185,
-  189, 187, 192, 197, 203, 203, 203, 206, 209, 212, 212, 212, 212, 213, 215, 216,
-  221, 218, 221, 224, 224, 164, 9, 6, 18, 121, 131, 145, 151, 167, 155, 153,
-  156, 153, 155, 149, 155, 151, 143, 149, 147, 149, 151, 145, 147, 145, 141, 141,
-  139, 139, 131, 133, 123, 123, 145, 201, 218, 222, 222, 221, 213, 215, 221, 222,
-  222, 221, 219, 215, 206, 184, 147, 108, 98, 96, 94, 86, 81, 89, 96, 101,
-  114, 110, 101, 91, 81, 86, 89, 103, 101, 108, 108, 108, 91, 103, 84, 91,
-  9, 15, 6, 20, 79, 139, 165, 181, 190, 184, 174, 158, 121, 20, 12, 26,
-  91, 135, 162, 171, 182, 182, 181, 182, 181, 184, 184, 184, 177, 165, 156, 145,
-  117, 110, 57, 49, 63, 26, 26, 26, 32, 29, 29, 29, 32, 29, 46, 49,
-  94, 32, 23, 98, 84, 86, 43, 35, 41, 35, 84, 63, 35, 26, 35, 29,
-  23, 43, 74, 18, 29, 101, 32, 38, 79, 81, 123, 139, 141, 121, 143, 156,
-  160, 74, 84, 141, 145, 172, 195, 147, 89, 29, 26, 94, 35, 60, 46, 35,
-  74, 23, 49, 52, 46, 46, 20, 52, 32, 35, 32, 32, 55, 71, 91, 112,
-  117, 112, 117, 121, 110, 57, 20, 81, 81, 96, 110, 121, 119, 125, 119, 125,
-  135, 133, 133, 141, 127, 127, 137, 133, 133, 129, 131, 131, 129, 133, 139, 131,
-  141, 143, 141, 143, 151, 151, 160, 158, 160, 164, 164, 169, 174, 174, 179, 182,
-  182, 185, 195, 197, 198, 201, 201, 203, 207, 213, 212, 213, 212, 215, 216, 216,
-  218, 219, 221, 222, 225, 204, 3, 9, 9, 125, 131, 137, 156, 153, 160, 153,
-  158, 158, 153, 156, 151, 145, 155, 151, 145, 149, 151, 149, 147, 147, 143, 141,
-  141, 135, 137, 129, 127, 133, 153, 204, 218, 222, 221, 215, 212, 215, 219, 224,
-  224, 224, 219, 212, 195, 162, 137, 108, 98, 98, 103, 94, 96, 91, 89, 112,
-  112, 112, 101, 105, 94, 84, 86, 91, 101, 96, 103, 98, 89, 94, 84, 79,
-  12, 15, 15, 20, 57, 141, 165, 181, 187, 184, 176, 160, 127, 41, 12, 43,
-  94, 129, 153, 174, 177, 177, 174, 174, 176, 174, 174, 176, 172, 164, 153, 139,
-  129, 133, 66, 26, 49, 29, 35, 35, 20, 23, 41, 38, 32, 49, 98, 49,
-  41, 20, 49, 105, 74, 96, 46, 49, 18, 43, 84, 60, 43, 26, 32, 18,
-  29, 55, 35, 35, 32, 98, 55, 32, 29, 41, 63, 129, 155, 139, 139, 145,
-  135, 112, 81, 108, 123, 169, 129, 182, 193, 153, 119, 119, 41, 79, 41, 35,
-  52, 38, 43, 84, 38, 43, 29, 46, 35, 35, 29, 52, 49, 71, 94, 112,
-  121, 110, 114, 117, 119, 38, 26, 76, 94, 105, 117, 119, 127, 125, 123, 125,
-  133, 131, 141, 139, 137, 127, 133, 127, 121, 127, 127, 131, 135, 137, 137, 141,
-  139, 141, 141, 143, 145, 153, 151, 158, 164, 158, 162, 165, 169, 174, 176, 172,
-  181, 190, 195, 200, 198, 200, 203, 204, 207, 210, 209, 212, 213, 215, 215, 216,
-  219, 219, 219, 221, 224, 218, 52, 6, 12, 133, 147, 143, 153, 160, 167, 155,
-  149, 155, 149, 149, 151, 145, 158, 151, 149, 149, 149, 149, 149, 141, 149, 135,
-  137, 141, 127, 131, 125, 133, 158, 209, 219, 222, 218, 213, 210, 213, 221, 224,
-  222, 221, 216, 209, 181, 145, 117, 112, 112, 96, 89, 91, 86, 98, 91, 105,
-  110, 112, 96, 84, 79, 84, 96, 103, 98, 108, 91, 94, 101, 86, 81, 74,
-  9, 6, 18, 15, 60, 119, 164, 182, 185, 185, 177, 160, 129, 35, 9, 35,
-  86, 129, 155, 171, 177, 182, 177, 177, 176, 177, 181, 181, 174, 164, 155, 133,
-  137, 153, 49, 76, 35, 23, 29, 23, 26, 26, 29, 35, 26, 46, 68, 23,
-  35, 35, 38, 98, 91, 86, 46, 43, 38, 52, 23, 43, 46, 46, 29, 32,
-  38, 32, 71, 46, 63, 105, 35, 43, 15, 26, 57, 127, 156, 149, 141, 156,
-  133, 101, 121, 18, 20, 43, 89, 52, 84, 66, 149, 151, 149, 141, 117, 110,
-  103, 91, 105, 46, 46, 26, 26, 46, 32, 29, 26, 57, 66, 79, 103, 117,
-  112, 114, 121, 114, 117, 63, 32, 76, 105, 110, 112, 117, 127, 129, 125, 119,
-  125, 133, 139, 133, 129, 137, 131, 131, 121, 127, 129, 131, 135, 139, 141, 137,
-  137, 137, 145, 153, 147, 155, 156, 156, 158, 164, 162, 165, 169, 174, 171, 176,
-  189, 192, 189, 197, 197, 200, 201, 204, 204, 209, 212, 210, 209, 215, 216, 216,
-  218, 219, 221, 222, 221, 222, 125, 9, 12, 133, 145, 145, 149, 158, 162, 155,
-  153, 151, 149, 151, 155, 149, 145, 151, 149, 147, 153, 149, 155, 149, 147, 137,
-  131, 127, 131, 135, 131, 131, 169, 210, 218, 221, 216, 213, 210, 215, 221, 224,
-  224, 219, 216, 198, 162, 127, 114, 114, 112, 101, 94, 96, 89, 89, 101, 110,
-  105, 105, 79, 79, 81, 91, 86, 108, 103, 96, 96, 89, 94, 79, 96, 91,
-  12, 9, 9, 20, 66, 119, 165, 176, 190, 189, 181, 167, 131, 43, 23, 41,
-  94, 129, 156, 167, 177, 177, 185, 181, 182, 182, 185, 179, 181, 171, 155, 137,
-  153, 108, 46, 60, 29, 41, 20, 55, 29, 38, 41, 35, 29, 35, 38, 41,
-  55, 43, 32, 76, 86, 68, 38, 41, 63, 35, 20, 32, 55, 46, 35, 26,
-  18, 46, 52, 23, 86, 112, 20, 71, 12, 49, 57, 103, 151, 86, 155, 117,
-  114, 145, 105, 76, 12, 23, 135, 18, 29, 76, 18, 15, 74, 96, 57, 129,
-  182, 119, 108, 49, 60, 41, 57, 41, 23, 41, 41, 60, 74, 84, 105, 117,
-  112, 123, 119, 123, 110, 60, 43, 79, 101, 108, 127, 117, 127, 131, 129, 127,
-  135, 131, 137, 133, 133, 127, 129, 131, 129, 127, 129, 131, 131, 125, 137, 139,
-  141, 139, 145, 141, 147, 153, 153, 153, 158, 156, 158, 164, 169, 176, 171, 176,
-  187, 187, 189, 192, 195, 198, 200, 203, 203, 207, 210, 210, 212, 215, 213, 215,
-  216, 218, 218, 221, 221, 224, 189, 6, 26, 137, 145, 147, 149, 156, 156, 164,
-  155, 153, 149, 153, 151, 145, 149, 145, 145, 151, 151, 149, 145, 149, 143, 133,
-  133, 139, 141, 139, 129, 131, 177, 207, 218, 224, 216, 210, 210, 213, 222, 225,
-  224, 216, 207, 189, 143, 117, 105, 110, 110, 98, 98, 81, 86, 98, 101, 108,
-  101, 98, 84, 79, 71, 91, 101, 105, 105, 86, 91, 96, 81, 81, 94, 89,
-  9, 12, 18, 18, 29, 105, 158, 174, 187, 187, 187, 169, 125, 63, 18, 60,
-  86, 135, 153, 169, 174, 182, 177, 184, 184, 184, 185, 182, 181, 171, 158, 137,
-  158, 108, 38, 26, 29, 41, 32, 32, 32, 32, 38, 32, 32, 46, 38, 60,
-  41, 35, 49, 66, 68, 46, 38, 43, 55, 32, 38, 43, 66, 26, 20, 20,
-  18, 52, 23, 26, 94, 105, 18, 32, 86, 57, 84, 101, 133, 101, 143, 143,
-  105, 133, 133, 153, 23, 26, 135, 18, 18, 63, 15, 20, 55, 49, 46, 71,
-  79, 43, 108, 137, 57, 43, 41, 43, 23, 23, 66, 63, 76, 96, 112, 112,
-  123, 121, 125, 129, 96, 43, 66, 94, 94, 121, 127, 125, 129, 121, 133, 133,
-  131, 133, 127, 135, 139, 137, 141, 129, 123, 125, 127, 133, 135, 131, 135, 135,
-  135, 133, 145, 141, 147, 149, 147, 160, 160, 158, 158, 167, 165, 172, 176, 177,
-  179, 181, 189, 192, 198, 198, 198, 201, 204, 207, 210, 215, 212, 212, 215, 213,
-  216, 218, 218, 218, 219, 221, 212, 12, 29, 129, 149, 141, 147, 156, 156, 167,
-  151, 151, 151, 153, 149, 153, 145, 147, 145, 147, 151, 149, 145, 147, 143, 137,
-  141, 133, 135, 135, 131, 133, 172, 200, 215, 221, 213, 209, 207, 216, 224, 225,
-  221, 215, 204, 176, 129, 117, 119, 110, 110, 98, 101, 89, 74, 94, 98, 101,
-  91, 79, 81, 76, 86, 96, 105, 105, 98, 94, 101, 94, 89, 81, 96, 96,
-  20, 12, 20, 23, 32, 114, 153, 169, 182, 185, 182, 169, 131, 35, 29, 57,
-  91, 129, 153, 169, 177, 181, 184, 184, 182, 182, 185, 181, 181, 167, 155, 133,
-  171, 108, 32, 43, 38, 41, 23, 38, 26, 29, 46, 20, 35, 38, 71, 63,
-  35, 41, 38, 57, 57, 52, 43, 60, 26, 29, 26, 46, 74, 29, 23, 32,
-  26, 74, 20, 49, 98, 57, 96, 20, 94, 84, 79, 123, 117, 129, 137, 114,
-  101, 125, 131, 156, 110, 26, 119, 23, 32, 20, 23, 52, 46, 57, 29, 71,
-  26, 55, 52, 71, 60, 41, 32, 18, 23, 41, 60, 76, 86, 94, 112, 123,
-  117, 127, 127, 123, 74, 38, 74, 101, 98, 121, 125, 127, 127, 131, 131, 131,
-  131, 135, 137, 137, 141, 137, 129, 123, 127, 129, 127, 137, 129, 133, 135, 135,
-  137, 137, 143, 143, 139, 153, 151, 149, 160, 158, 158, 164, 167, 172, 171, 172,
-  181, 181, 184, 192, 192, 200, 197, 200, 206, 204, 206, 210, 212, 212, 213, 215,
-  213, 218, 218, 216, 218, 221, 219, 52, 41, 121, 153, 151, 156, 165, 160, 153,
-  156, 151, 151, 149, 160, 149, 155, 151, 151, 147, 151, 147, 143, 149, 145, 141,
-  133, 139, 143, 137, 137, 131, 156, 189, 209, 212, 210, 209, 206, 216, 225, 225,
-  221, 212, 200, 167, 117, 114, 114, 108, 105, 108, 101, 81, 89, 91, 101, 86,
-  89, 63, 79, 101, 98, 103, 96, 96, 91, 89, 101, 91, 86, 94, 91, 96,
-  12, 15, 12, 9, 38, 98, 151, 167, 182, 185, 177, 169, 133, 71, 29, 41,
-  79, 123, 151, 169, 172, 184, 182, 182, 181, 182, 185, 185, 182, 171, 151, 151,
-  162, 123, 41, 41, 23, 46, 35, 29, 18, 32, 52, 23, 52, 76, 66, 49,
-  32, 41, 29, 66, 49, 41, 63, 43, 38, 41, 38, 35, 57, 43, 18, 29,
-  26, 66, 26, 81, 84, 49, 105, 79, 32, 101, 110, 68, 86, 101, 158, 125,
-  103, 49, 110, 141, 162, 74, 94, 46, 38, 15, 26, 66, 55, 26, 15, 68,
-  63, 32, 41, 38, 43, 41, 29, 20, 29, 35, 68, 71, 98, 89, 110, 105,
-  125, 123, 121, 119, 63, 26, 71, 94, 108, 125, 127, 123, 131, 135, 133, 133,
-  131, 131, 139, 137, 137, 131, 133, 133, 131, 133, 125, 129, 139, 135, 129, 137,
-  137, 135, 145, 143, 147, 141, 147, 155, 158, 158, 160, 164, 164, 171, 171, 172,
-  174, 177, 190, 187, 193, 197, 201, 200, 206, 207, 207, 207, 209, 210, 212, 216,
-  216, 218, 218, 218, 218, 219, 221, 153, 68, 119, 151, 149, 149, 162, 160, 153,
-  151, 151, 151, 153, 147, 153, 155, 155, 151, 153, 149, 149, 149, 151, 151, 141,
-  139, 141, 143, 141, 137, 137, 139, 162, 193, 198, 200, 201, 209, 218, 225, 224,
-  218, 213, 198, 156, 123, 110, 103, 110, 101, 98, 81, 86, 79, 98, 96, 81,
-  55, 63, 86, 101, 101, 101, 103, 103, 89, 91, 91, 81, 98, 103, 94, 96,
-  29, 23, 23, 18, 32, 89, 143, 169, 184, 182, 184, 167, 137, 86, 35, 52,
-  81, 131, 151, 167, 176, 181, 181, 181, 177, 182, 181, 187, 174, 167, 156, 135,
-  165, 131, 41, 84, 43, 52, 23, 35, 29, 32, 32, 68, 103, 68, 35, 41,
-  26, 29, 49, 63, 55, 46, 43, 32, 52, 43, 49, 32, 49, 110, 26, 35,
-  41, 52, 43, 91, 52, 46, 74, 123, 23, 20, 149, 165, 143, 158, 96, 141,
-  114, 91, 60, 125, 117, 143, 112, 49, 143, 23, 26, 49, 41, 49, 32, 46,
-  60, 41, 32, 41, 41, 38, 15, 26, 43, 63, 79, 79, 103, 101, 110, 117,
-  119, 114, 119, 112, 55, 49, 84, 96, 114, 123, 125, 125, 133, 135, 141, 133,
-  133, 137, 133, 129, 131, 135, 129, 131, 131, 127, 133, 135, 127, 133, 133, 135,
-  137, 141, 143, 145, 147, 153, 153, 153, 155, 156, 156, 162, 160, 165, 167, 171,
-  177, 176, 181, 182, 193, 190, 200, 198, 201, 204, 203, 210, 209, 212, 210, 216,
-  215, 218, 218, 216, 218, 218, 219, 201, 81, 131, 149, 151, 131, 147, 153, 155,
-  149, 153, 153, 162, 156, 155, 155, 153, 156, 149, 151, 151, 153, 147, 145, 141,
-  145, 143, 141, 141, 143, 141, 145, 143, 158, 172, 181, 187, 209, 221, 230, 222,
-  218, 207, 189, 141, 117, 103, 101, 96, 103, 91, 76, 86, 96, 91, 89, 84,
-  68, 74, 94, 112, 105, 94, 98, 84, 81, 98, 94, 94, 84, 98, 108, 89,
-  26, 18, 15, 9, 18, 79, 139, 172, 179, 185, 181, 169, 149, 98, 46, 55,
-  81, 133, 151, 165, 174, 177, 179, 181, 182, 176, 184, 184, 174, 165, 153, 141,
-  167, 133, 49, 96, 46, 38, 23, 26, 26, 76, 91, 76, 63, 32, 38, 29,
-  23, 26, 60, 38, 68, 32, 32, 41, 63, 60, 74, 41, 29, 68, 38, 52,
-  29, 29, 101, 49, 35, 41, 43, 114, 94, 15, 32, 114, 89, 153, 123, 145,
-  86, 49, 55, 101, 137, 171, 131, 123, 187, 18, 43, 29, 35, 32, 32, 43,
-  26, 32, 35, 29, 23, 35, 29, 26, 38, 60, 81, 86, 101, 110, 114, 121,
-  114, 114, 117, 89, 35, 52, 89, 110, 114, 127, 129, 129, 131, 139, 137, 127,
-  139, 141, 141, 135, 133, 133, 133, 131, 133, 125, 133, 127, 125, 131, 125, 133,
-  141, 133, 139, 147, 143, 153, 143, 153, 155, 156, 156, 164, 160, 169, 165, 169,
-  172, 177, 181, 189, 190, 192, 197, 197, 201, 204, 206, 206, 209, 212, 212, 213,
-  216, 216, 215, 216, 216, 218, 219, 210, 101, 139, 149, 143, 119, 125, 137, 137,
-  141, 141, 147, 149, 158, 158, 156, 153, 153, 158, 155, 155, 156, 153, 145, 145,
-  153, 139, 145, 147, 153, 141, 141, 145, 133, 145, 151, 182, 210, 224, 227, 222,
-  216, 206, 177, 135, 112, 103, 101, 91, 84, 76, 81, 84, 86, 94, 76, 66,
-  71, 76, 101, 108, 103, 94, 91, 84, 84, 86, 91, 98, 94, 98, 91, 76,
-  20, 18, 9, 32, 23, 66, 127, 167, 179, 177, 182, 171, 143, 108, 32, 46,
-  74, 125, 147, 165, 177, 181, 177, 179, 181, 181, 182, 184, 174, 167, 153, 131,
-  149, 149, 43, 91, 35, 41, 26, 29, 41, 52, 49, 41, 52, 32, 26, 43,
-  29, 41, 60, 41, 68, 43, 38, 55, 55, 43, 43, 55, 35, 63, 60, 29,
-  20, 57, 123, 41, 23, 26, 41, 117, 98, 63, 26, 35, 32, 46, 105, 167,
-  119, 49, 32, 52, 71, 133, 193, 197, 119, 29, 32, 49, 29, 29, 52, 46,
-  38, 35, 43, 20, 26, 29, 18, 23, 49, 68, 74, 103, 101, 110, 117, 121,
-  114, 117, 114, 71, 26, 79, 76, 110, 123, 129, 125, 127, 135, 135, 135, 137,
-  133, 137, 149, 141, 127, 129, 135, 133, 139, 131, 129, 127, 129, 137, 131, 133,
-  139, 135, 139, 145, 145, 147, 147, 151, 155, 155, 158, 160, 160, 160, 162, 165,
-  167, 179, 179, 185, 189, 192, 195, 200, 200, 203, 206, 207, 207, 212, 215, 215,
-  213, 215, 216, 218, 218, 218, 219, 221, 153, 145, 143, 123, 98, 114, 108, 117,
-  123, 135, 135, 141, 145, 149, 153, 155, 156, 155, 155, 149, 156, 153, 147, 153,
-  145, 153, 153, 149, 149, 149, 145, 147, 137, 137, 149, 192, 213, 227, 227, 222,
-  215, 200, 167, 129, 105, 108, 103, 103, 81, 66, 81, 96, 98, 76, 79, 63,
-  76, 86, 101, 105, 98, 91, 94, 74, 94, 81, 94, 94, 89, 101, 94, 63,
-  23, 20, 20, 15, 18, 74, 143, 167, 177, 181, 172, 165, 149, 103, 57, 43,
-  71, 119, 145, 162, 171, 177, 179, 182, 179, 179, 181, 181, 179, 165, 155, 135,
-  135, 153, 43, 91, 29, 41, 26, 23, 29, 29, 26, 41, 35, 26, 29, 57,
-  26, 55, 41, 60, 49, 46, 49, 76, 63, 32, 41, 32, 57, 46, 29, 20,
-  23, 68, 81, 38, 38, 26, 66, 135, 131, 63, 98, 26, 55, 23, 15, 103,
-  165, 35, 46, 89, 63, 57, 143, 143, 18, 35, 29, 38, 18, 23, 55, 38,
-  38, 23, 32, 26, 32, 32, 26, 29, 60, 71, 96, 101, 101, 108, 110, 125,
-  117, 123, 98, 49, 32, 86, 101, 119, 125, 137, 133, 127, 133, 131, 131, 131,
-  137, 141, 135, 141, 137, 137, 135, 135, 135, 133, 131, 131, 129, 133, 135, 135,
-  141, 145, 137, 139, 145, 145, 141, 149, 151, 149, 151, 156, 158, 162, 165, 165,
-  174, 177, 176, 189, 184, 190, 195, 197, 201, 203, 206, 209, 209, 209, 212, 213,
-  215, 218, 216, 219, 218, 216, 219, 222, 195, 139, 114, 108, 68, 98, 86, 94,
-  103, 105, 112, 125, 133, 137, 139, 149, 145, 149, 151, 151, 149, 155, 153, 151,
-  145, 149, 158, 151, 153, 153, 149, 143, 139, 139, 153, 200, 215, 227, 227, 221,
-  210, 190, 153, 112, 103, 103, 89, 86, 76, 84, 89, 94, 91, 68, 74, 74,
-  81, 101, 103, 98, 96, 96, 84, 79, 86, 96, 103, 96, 98, 89, 74, 35,
-  18, 23, 15, 15, 23, 63, 125, 162, 177, 190, 184, 177, 153, 96, 46, 49,
-  81, 127, 149, 165, 179, 177, 181, 181, 177, 182, 182, 184, 181, 164, 158, 135,
-  119, 141, 63, 98, 46, 20, 26, 38, 38, 38, 41, 46, 35, 26, 29, 32,
-  41, 68, 38, 71, 43, 32, 52, 81, 71, 32, 26, 23, 35, 46, 29, 20,
-  18, 81, 29, 38, 57, 35, 49, 133, 131, 149, 41, 74, 29, 12, 32, 57,
-  103, 63, 20, 94, 137, 89, 86, 139, 12, 32, 49, 35, 46, 38, 23, 38,
-  35, 26, 23, 18, 18, 35, 49, 60, 55, 74, 98, 103, 112, 105, 114, 121,
-  117, 117, 74, 38, 43, 84, 103, 135, 125, 131, 127, 125, 135, 137, 135, 139,
-  141, 139, 141, 145, 141, 133, 135, 137, 131, 131, 135, 139, 137, 129, 133, 127,
-  135, 137, 147, 143, 149, 147, 145, 151, 156, 156, 156, 155, 162, 167, 162, 165,
-  171, 172, 177, 179, 187, 189, 195, 193, 197, 201, 203, 206, 207, 212, 212, 215,
-  213, 219, 218, 221, 218, 218, 218, 224, 216, 131, 81, 71, 60, 68, 68, 76,
-  81, 101, 98, 103, 108, 119, 123, 127, 129, 133, 141, 143, 145, 149, 149, 155,
-  156, 151, 164, 164, 151, 145, 141, 137, 137, 145, 172, 207, 219, 225, 225, 215,
-  207, 182, 139, 112, 98, 96, 74, 66, 63, 81, 98, 91, 74, 52, 63, 68,
-  94, 96, 94, 91, 96, 91, 94, 94, 96, 103, 101, 94, 81, 76, 52, 57,
-  20, 20, 15, 15, 20, 49, 114, 167, 187, 190, 187, 182, 160, 114, 55, 38,
-  68, 117, 139, 162, 172, 174, 181, 177, 181, 182, 182, 187, 177, 174, 162, 145,
-  121, 110, 71, 76, 79, 26, 20, 38, 46, 38, 26, 26, 32, 32, 32, 55,
-  63, 41, 52, 60, 35, 38, 49, 46, 86, 41, 35, 29, 23, 18, 41, 26,
-  23, 52, 46, 46, 63, 101, 98, 84, 145, 164, 84, 29, 60, 68, 23, 60,
-  52, 29, 46, 84, 79, 89, 105, 81, 18, 29, 29, 26, 20, 38, 41, 38,
-  26, 18, 35, 15, 32, 29, 66, 60, 68, 81, 103, 105, 114, 103, 110, 121,
-  117, 103, 20, 32, 74, 84, 121, 125, 125, 127, 129, 127, 133, 137, 135, 139,
-  141, 143, 133, 133, 131, 137, 141, 133, 139, 137, 129, 125, 133, 129, 129, 133,
-  137, 131, 137, 145, 141, 143, 151, 151, 153, 147, 153, 156, 160, 160, 162, 169,
-  171, 174, 174, 182, 177, 187, 195, 195, 200, 197, 200, 207, 209, 212, 213, 215,
-  215, 216, 215, 218, 216, 221, 219, 224, 222, 135, 63, 71, 63, 79, 52, 60,
-  68, 68, 89, 81, 84, 94, 96, 112, 108, 114, 125, 125, 137, 133, 143, 143,
-  153, 160, 169, 165, 158, 155, 129, 131, 137, 151, 190, 213, 222, 225, 221, 215,
-  195, 158, 127, 103, 89, 76, 68, 74, 74, 101, 96, 81, 60, 57, 74, 94,
-  101, 94, 94, 98, 89, 84, 86, 89, 101, 110, 98, 94, 94, 71, 41, 46,
-  12, 9, 9, 15, 41, 38, 105, 172, 181, 192, 190, 184, 158, 129, 41, 43,
-  71, 119, 141, 158, 174, 177, 179, 182, 184, 182, 181, 185, 177, 171, 160, 143,
-  121, 114, 91, 68, 96, 18, 26, 29, 60, 35, 32, 29, 29, 32, 26, 57,
-  43, 41, 63, 52, 29, 46, 52, 55, 68, 49, 38, 26, 35, 32, 41, 41,
-  38, 29, 32, 131, 12, 76, 129, 101, 133, 112, 176, 86, 38, 71, 63, 60,
-  63, 71, 63, 167, 55, 52, 86, 35, 20, 35, 35, 15, 38, 29, 26, 23,
-  35, 20, 18, 18, 43, 35, 60, 66, 74, 96, 105, 114, 114, 114, 112, 114,
-  123, 57, 15, 49, 79, 108, 121, 127, 121, 133, 123, 123, 131, 145, 137, 137,
-  135, 137, 137, 131, 137, 141, 137, 131, 131, 129, 127, 129, 135, 135, 131, 129,
-  137, 137, 137, 137, 133, 141, 139, 145, 145, 151, 155, 156, 156, 160, 162, 165,
-  171, 177, 172, 176, 179, 181, 195, 195, 197, 198, 201, 206, 207, 210, 212, 210,
-  212, 215, 216, 218, 216, 218, 221, 222, 224, 174, 60, 79, 60, 94, 63, 74,
-  71, 74, 79, 63, 76, 86, 79, 76, 89, 89, 94, 98, 103, 105, 117, 129,
-  143, 155, 167, 171, 160, 149, 155, 156, 145, 155, 197, 218, 224, 227, 219, 204,
-  176, 139, 117, 86, 74, 71, 66, 63, 81, 96, 91, 74, 57, 71, 94, 94,
-  108, 89, 91, 98, 91, 89, 94, 103, 108, 103, 89, 96, 68, 66, 41, 35,
-  20, 18, 15, 6, 15, 29, 121, 165, 184, 189, 190, 184, 164, 137, 57, 49,
-  76, 114, 145, 160, 171, 176, 177, 181, 179, 177, 184, 184, 179, 167, 164, 141,
-  105, 114, 91, 91, 96, 23, 18, 38, 26, 23, 29, 23, 29, 32, 60, 66,
-  41, 32, 52, 60, 41, 35, 57, 55, 66, 43, 41, 49, 26, 18, 29, 32,
-  38, 35, 38, 91, 12, 23, 110, 68, 105, 137, 160, 165, 123, 26, 46, 105,
-  114, 121, 55, 89, 29, 38, 35, 43, 29, 32, 26, 18, 32, 35, 29, 26,
-  23, 18, 43, 20, 26, 41, 60, 63, 81, 108, 117, 117, 108, 108, 110, 110,
-  94, 23, 15, 55, 105, 117, 123, 127, 127, 127, 125, 131, 123, 131, 143, 133,
-  135, 139, 133, 127, 133, 137, 135, 137, 133, 135, 131, 133, 137, 129, 123, 131,
-  127, 133, 139, 133, 143, 131, 141, 145, 149, 143, 151, 153, 153, 162, 160, 165,
-  169, 176, 174, 172, 172, 182, 187, 189, 193, 197, 200, 204, 209, 207, 212, 212,
-  213, 216, 216, 215, 218, 218, 221, 221, 224, 206, 68, 81, 74, 96, 86, 84,
-  84, 79, 84, 74, 63, 71, 66, 49, 60, 66, 63, 66, 79, 71, 86, 105,
-  125, 143, 147, 151, 156, 169, 172, 162, 156, 172, 206, 218, 227, 224, 215, 193,
-  156, 123, 89, 66, 52, 43, 55, 66, 81, 81, 81, 57, 63, 89, 96, 110,
-  79, 86, 96, 94, 91, 86, 86, 101, 108, 84, 101, 94, 79, 52, 43, 32,
-  20, 12, 12, 9, 12, 32, 110, 171, 184, 190, 195, 182, 174, 137, 63, 43,
-  68, 112, 137, 162, 172, 177, 179, 182, 182, 181, 187, 185, 177, 172, 162, 139,
-  57, 127, 98, 76, 89, 18, 38, 49, 23, 26, 23, 18, 32, 52, 55, 49,
-  23, 29, 81, 43, 41, 29, 57, 49, 66, 57, 63, 35, 41, 23, 43, 23,
-  41, 41, 32, 18, 18, 38, 23, 103, 91, 131, 121, 143, 158, 105, 119, 84,
-  84, 135, 94, 32, 20, 26, 32, 41, 49, 23, 20, 32, 29, 26, 18, 29,
-  26, 20, 20, 29, 38, 43, 84, 74, 96, 112, 105, 110, 110, 114, 114, 101,
-  26, 12, 32, 79, 108, 125, 129, 133, 133, 127, 125, 129, 133, 131, 133, 135,
-  133, 135, 129, 137, 141, 139, 143, 129, 135, 133, 133, 139, 133, 129, 131, 133,
-  127, 137, 139, 133, 141, 143, 141, 141, 143, 145, 151, 151, 151, 155, 165, 162,
-  167, 167, 172, 171, 174, 181, 187, 190, 193, 195, 200, 206, 204, 207, 215, 212,
-  213, 212, 216, 216, 216, 216, 219, 221, 222, 218, 76, 68, 86, 91, 98, 96,
-  91, 98, 81, 86, 81, 68, 68, 52, 55, 49, 46, 43, 35, 38, 49, 68,
-  91, 108, 117, 139, 184, 197, 193, 169, 160, 185, 209, 218, 224, 219, 212, 184,
-  141, 98, 71, 55, 41, 41, 79, 71, 84, 60, 57, 66, 89, 110, 114, 101,
-  91, 94, 89, 89, 84, 89, 91, 103, 112, 98, 94, 89, 57, 52, 43, 38,
-  35, 32, 29, 38, 41, 35, 114, 171, 182, 190, 193, 187, 179, 155, 71, 46,
-  76, 121, 145, 162, 169, 176, 182, 177, 179, 179, 189, 185, 179, 174, 164, 139,
-  60, 127, 86, 57, 60, 26, 43, 35, 20, 29, 29, 23, 43, 66, 46, 41,
-  43, 38, 60, 41, 29, 35, 81, 57, 49, 41, 49, 43, 52, 41, 41, 32,
-  23, 49, 55, 23, 38, 35, 15, 32, 105, 117, 151, 162, 108, 160, 112, 117,
-  89, 43, 119, 86, 26, 23, 35, 43, 32, 23, 35, 35, 29, 26, 29, 23,
-  9, 23, 23, 20, 41, 55, 74, 84, 98, 105, 110, 112, 108, 114, 103, 52,
-  23, 20, 71, 101, 117, 127, 125, 129, 143, 129, 131, 133, 133, 133, 133, 135,
-  129, 137, 139, 139, 135, 141, 137, 137, 135, 137, 137, 137, 133, 131, 131, 131,
-  131, 135, 135, 129, 135, 141, 139, 147, 149, 153, 153, 155, 156, 156, 162, 164,
-  167, 167, 165, 174, 177, 182, 179, 190, 193, 195, 195, 203, 203, 204, 207, 210,
-  212, 212, 215, 216, 218, 216, 219, 219, 221, 222, 143, 71, 94, 96, 103, 103,
-  108, 81, 86, 86, 84, 74, 68, 55, 49, 43, 35, 29, 29, 35, 29, 35,
-  49, 94, 114, 174, 203, 203, 200, 179, 169, 192, 212, 221, 222, 218, 201, 167,
-  121, 76, 60, 41, 35, 43, 68, 71, 66, 63, 66, 91, 103, 114, 117, 101,
-  89, 84, 86, 76, 89, 86, 101, 108, 98, 103, 86, 71, 52, 46, 32, 26,
-  26, 41, 57, 57, 55, 60, 108, 158, 181, 192, 197, 190, 189, 145, 86, 52,
-  81, 114, 145, 158, 169, 176, 182, 184, 179, 182, 184, 190, 184, 176, 165, 125,
-  86, 133, 103, 55, 32, 23, 35, 18, 20, 23, 32, 55, 26, 38, 38, 46,
-  26, 29, 35, 52, 26, 41, 63, 49, 57, 46, 41, 57, 38, 63, 32, 23,
-  15, 20, 60, 46, 23, 49, 32, 32, 18, 101, 110, 174, 160, 123, 156, 68,
-  98, 129, 131, 84, 20, 20, 35, 43, 20, 15, 20, 18, 26, 20, 15, 20,
-  20, 18, 32, 41, 66, 63, 81, 96, 103, 105, 110, 108, 125, 117, 71, 23,
-  26, 43, 86, 110, 123, 125, 129, 135, 131, 129, 131, 127, 129, 131, 129, 133,
-  127, 135, 137, 139, 137, 137, 141, 139, 137, 135, 131, 133, 129, 129, 131, 127,
-  131, 135, 133, 135, 133, 141, 137, 143, 149, 147, 147, 155, 149, 155, 156, 160,
-  160, 165, 169, 174, 176, 182, 182, 189, 190, 193, 198, 201, 200, 204, 210, 210,
-  212, 215, 212, 215, 219, 218, 219, 219, 221, 221, 192, 76, 89, 103, 110, 103,
-  98, 103, 103, 94, 89, 86, 71, 76, 68, 49, 41, 41, 29, 20, 12, 18,
-  29, 52, 145, 200, 210, 210, 198, 167, 165, 201, 215, 221, 221, 212, 193, 147,
-  89, 52, 38, 49, 49, 68, 76, 76, 57, 52, 76, 84, 98, 108, 103, 89,
-  81, 74, 74, 71, 96, 94, 108, 103, 105, 91, 89, 63, 43, 38, 46, 35,
-  63, 81, 71, 74, 74, 81, 108, 151, 181, 192, 198, 195, 185, 153, 105, 57,
-  76, 110, 141, 162, 169, 177, 182, 184, 179, 181, 184, 187, 181, 174, 158, 98,
-  94, 141, 117, 60, 43, 18, 41, 32, 43, 66, 68, 29, 23, 29, 32, 57,
-  46, 35, 43, 55, 38, 55, 55, 43, 71, 43, 46, 49, 38, 32, 23, 26,
-  41, 20, 29, 49, 32, 94, 41, 41, 32, 18, 79, 143, 131, 156, 149, 108,
-  98, 101, 94, 125, 29, 32, 38, 26, 43, 35, 32, 26, 26, 29, 15, 26,
-  32, 18, 23, 66, 68, 84, 96, 105, 105, 110, 108, 112, 110, 89, 29, 32,
-  23, 74, 105, 123, 125, 127, 127, 133, 127, 131, 133, 131, 133, 137, 133, 131,
-  135, 135, 135, 135, 133, 137, 139, 139, 135, 141, 137, 131, 131, 133, 131, 127,
-  131, 135, 129, 129, 131, 135, 137, 137, 149, 145, 145, 147, 156, 158, 160, 156,
-  158, 162, 165, 169, 172, 177, 176, 187, 184, 189, 197, 200, 203, 204, 206, 207,
-  212, 213, 215, 213, 216, 216, 219, 218, 219, 224, 212, 79, 86, 98, 96, 110,
-  105, 114, 117, 103, 96, 101, 81, 84, 76, 63, 49, 41, 18, 35, 35, 18,
-  15, 55, 160, 206, 213, 215, 192, 158, 182, 207, 216, 221, 216, 203, 164, 91,
-  60, 52, 26, 46, 60, 68, 66, 74, 55, 66, 84, 101, 114, 121, 86, 89,
-  81, 84, 79, 79, 84, 101, 110, 119, 103, 84, 86, 66, 60, 55, 38, 46,
-  96, 91, 86, 79, 91, 89, 123, 149, 181, 192, 195, 193, 182, 158, 114, 57,
-  79, 112, 141, 160, 172, 174, 182, 182, 182, 182, 185, 192, 181, 176, 165, 103,
-  91, 135, 91, 84, 18, 23, 35, 52, 57, 52, 35, 29, 41, 29, 41, 41,
-  38, 43, 49, 43, 46, 68, 29, 55, 74, 49, 52, 52, 35, 35, 35, 26,
-  46, 43, 18, 46, 63, 52, 46, 35, 26, 32, 63, 63, 141, 143, 189, 145,
-  96, 84, 123, 151, 43, 32, 23, 23, 29, 20, 32, 29, 32, 20, 9, 18,
-  20, 20, 46, 71, 60, 74, 96, 108, 103, 105, 110, 117, 96, 20, 23, 23,
-  71, 91, 114, 123, 127, 129, 127, 129, 127, 131, 139, 137, 129, 129, 129, 137,
-  131, 133, 125, 143, 133, 139, 139, 137, 135, 139, 135, 131, 135, 141, 131, 135,
-  129, 133, 135, 137, 141, 127, 133, 139, 147, 149, 141, 143, 155, 156, 158, 158,
-  153, 165, 158, 171, 177, 172, 179, 181, 187, 193, 197, 200, 201, 204, 204, 210,
-  212, 215, 213, 215, 212, 218, 216, 219, 221, 221, 222, 119, 79, 84, 108, 112,
-  101, 108, 110, 105, 98, 96, 76, 94, 84, 63, 66, 49, 52, 29, 20, 20,
-  29, 52, 158, 204, 212, 212, 184, 165, 192, 206, 213, 215, 204, 176, 114, 46,
-  46, 35, 49, 63, 63, 66, 55, 57, 66, 84, 101, 110, 101, 91, 84, 76,
-  66, 76, 68, 86, 86, 108, 119, 114, 108, 98, 76, 63, 63, 52, 43, 49,
-  79, 86, 86, 89, 103, 101, 135, 156, 181, 190, 195, 195, 187, 165, 127, 60,
-  94, 105, 141, 156, 172, 181, 182, 182, 184, 182, 189, 190, 185, 176, 164, 96,
-  91, 129, 91, 76, 26, 26, 43, 32, 23, 32, 43, 26, 32, 26, 46, 41,
-  57, 41, 41, 29, 32, 32, 35, 57, 76, 41, 43, 52, 52, 26, 35, 35,
-  32, 57, 43, 15, 55, 49, 57, 52, 43, 55, 49, 68, 57, 74, 141, 158,
-  137, 105, 98, 66, 32, 38, 23, 23, 23, 29, 29, 38, 15, 18, 15, 26,
-  23, 35, 57, 66, 68, 98, 96, 117, 108, 101, 110, 91, 20, 15, 23, 63,
-  91, 117, 117, 121, 125, 125, 131, 127, 127, 133, 131, 137, 129, 133, 129, 135,
-  131, 127, 135, 141, 139, 135, 141, 135, 145, 141, 133, 139, 137, 135, 133, 129,
-  133, 133, 135, 137, 135, 131, 133, 139, 143, 141, 143, 149, 155, 153, 149, 158,
-  160, 164, 165, 169, 169, 172, 174, 181, 185, 189, 195, 198, 200, 203, 206, 206,
-  209, 213, 213, 213, 213, 216, 219, 216, 216, 218, 221, 172, 66, 86, 96, 112,
-  112, 108, 112, 108, 105, 98, 103, 96, 81, 74, 76, 63, 63, 41, 26, 43,
-  46, 57, 149, 193, 207, 209, 197, 195, 195, 210, 207, 204, 172, 123, 46, 38,
-  32, 35, 41, 60, 68, 57, 49, 68, 76, 94, 103, 108, 91, 76, 63, 66,
-  71, 66, 79, 94, 96, 110, 117, 110, 96, 81, 81, 86, 74, 49, 43, 60,
-  86, 94, 81, 101, 103, 114, 143, 155, 182, 190, 193, 197, 190, 169, 131, 63,
-  86, 110, 137, 156, 176, 179, 179, 182, 184, 187, 190, 189, 184, 177, 171, 81,
-  110, 119, 91, 68, 29, 29, 35, 26, 29, 29, 49, 29, 32, 29, 43, 49,
-  46, 29, 41, 46, 32, 26, 35, 52, 63, 46, 32, 68, 79, 43, 38, 35,
-  20, 63, 86, 43, 32, 43, 86, 41, 32, 68, 94, 29, 86, 66, 131, 71,
-  131, 158, 119, 26, 29, 41, 23, 38, 35, 26, 23, 26, 23, 12, 20, 26,
-  35, 52, 66, 49, 84, 96, 101, 114, 105, 110, 76, 20, 15, 35, 66, 89,
-  108, 117, 119, 123, 127, 119, 131, 131, 131, 139, 127, 133, 135, 133, 135, 135,
-  131, 133, 133, 135, 137, 141, 139, 133, 143, 147, 133, 137, 137, 135, 133, 131,
-  127, 133, 129, 139, 135, 137, 133, 135, 145, 139, 143, 145, 151, 147, 149, 160,
-  156, 164, 165, 172, 165, 167, 174, 185, 184, 185, 190, 198, 197, 200, 204, 207,
-  209, 213, 212, 215, 215, 218, 215, 215, 218, 219, 221, 209, 68, 84, 86, 103,
-  110, 114, 112, 105, 103, 98, 98, 86, 84, 86, 76, 74, 68, 57, 52, 43,
-  41, 60, 129, 190, 207, 209, 209, 201, 200, 198, 184, 165, 121, 71, 52, 38,
-  46, 43, 60, 68, 46, 52, 57, 76, 96, 101, 101, 96, 96, 84, 60, 66,
-  74, 81, 79, 96, 105, 119, 112, 96, 94, 84, 79, 79, 63, 43, 68, 66,
-  66, 84, 101, 110, 114, 129, 143, 155, 182, 189, 195, 190, 185, 169, 135, 68,
-  94, 110, 137, 160, 171, 179, 179, 181, 185, 189, 189, 189, 184, 176, 164, 76,
-  127, 119, 91, 35, 23, 43, 41, 43, 29, 32, 20, 29, 46, 26, 49, 41,
-  43, 32, 41, 29, 35, 38, 57, 57, 86, 26, 38, 81, 89, 35, 35, 38,
-  23, 38, 91, 94, 38, 35, 84, 23, 49, 55, 121, 38, 60, 125, 153, 46,
-  81, 103, 112, 49, 32, 29, 32, 35, 23, 38, 23, 23, 18, 38, 32, 32,
-  52, 66, 71, 89, 91, 84, 98, 110, 94, 35, 18, 9, 32, 79, 96, 96,
-  117, 114, 125, 114, 121, 123, 129, 131, 129, 139, 131, 135, 139, 133, 135, 129,
-  133, 135, 133, 137, 141, 139, 141, 141, 137, 141, 139, 137, 137, 135, 143, 137,
-  131, 137, 135, 143, 137, 133, 131, 131, 141, 143, 143, 149, 147, 147, 153, 153,
-  155, 160, 164, 165, 165, 172, 177, 172, 179, 177, 190, 192, 197, 200, 203, 206,
-  206, 209, 212, 215, 213, 218, 219, 215, 215, 216, 221, 219, 103, 84, 94, 98,
-  101, 108, 110, 108, 101, 96, 91, 103, 89, 91, 81, 76, 81, 63, 68, 74,
-  66, 81, 131, 192, 210, 216, 219, 207, 195, 167, 151, 114, 66, 60, 35, 35,
-  63, 57, 60, 63, 49, 57, 74, 84, 108, 112, 105, 96, 81, 81, 63, 66,
-  68, 74, 101, 108, 119, 114, 105, 94, 96, 91, 76, 74, 55, 57, 66, 43,
-  55, 81, 91, 119, 125, 123, 139, 155, 181, 185, 190, 190, 187, 167, 129, 74,
-  94, 110, 135, 160, 171, 182, 179, 179, 182, 185, 187, 189, 179, 172, 162, 98,
-  108, 125, 105, 23, 35, 38, 23, 63, 26, 57, 29, 49, 38, 26, 35, 43,
-  52, 38, 35, 29, 35, 46, 91, 55, 105, 38, 55, 66, 89, 84, 26, 29,
-  26, 26, 94, 68, 68, 52, 41, 103, 35, 66, 41, 79, 66, 96, 171, 110,
-  86, 18, 79, 60, 43, 26, 32, 29, 41, 20, 20, 29, 12, 15, 15, 32,
-  63, 63, 74, 91, 105, 91, 68, 35, 12, 9, 23, 60, 81, 94, 103, 110,
-  117, 112, 125, 127, 127, 125, 125, 129, 127, 133, 133, 133, 133, 133, 145, 133,
-  131, 135, 137, 135, 137, 137, 139, 145, 135, 141, 139, 137, 135, 139, 137, 141,
-  129, 139, 133, 139, 135, 131, 131, 133, 137, 141, 141, 149, 145, 147, 149, 151,
-  156, 164, 160, 165, 162, 171, 176, 172, 176, 181, 184, 192, 193, 197, 201, 203,
-  207, 206, 209, 210, 215, 215, 216, 218, 216, 221, 218, 221, 149, 81, 89, 94,
-  105, 98, 108, 103, 110, 101, 105, 101, 91, 98, 86, 79, 81, 86, 89, 86,
-  74, 86, 143, 190, 213, 219, 216, 201, 169, 133, 86, 68, 52, 46, 41, 35,
-  60, 66, 66, 55, 52, 81, 81, 98, 105, 108, 96, 81, 68, 63, 68, 76,
-  71, 94, 91, 117, 121, 110, 108, 94, 94, 89, 84, 43, 57, 66, 74, 57,
-  41, 74, 94, 121, 123, 114, 121, 147, 176, 187, 190, 189, 184, 164, 129, 84,
-  91, 105, 143, 158, 171, 179, 182, 184, 184, 184, 189, 187, 185, 177, 171, 108,
-  81, 112, 98, 29, 20, 32, 32, 38, 32, 57, 29, 49, 46, 26, 29, 26,
-  74, 66, 38, 29, 32, 43, 79, 55, 101, 35, 43, 79, 105, 81, 52, 26,
-  32, 29, 98, 66, 29, 32, 32, 137, 55, 52, 57, 94, 84, 66, 156, 141,
-  79, 20, 71, 84, 23, 18, 20, 32, 32, 15, 15, 29, 23, 20, 23, 63,
-  71, 76, 89, 66, 38, 74, 20, 18, 32, 49, 84, 89, 96, 105, 112, 108,
-  119, 117, 114, 125, 125, 125, 129, 129, 131, 127, 127, 125, 127, 141, 133, 137,
-  133, 129, 143, 137, 135, 139, 137, 143, 149, 143, 149, 143, 143, 137, 139, 137,
-  139, 133, 135, 137, 129, 135, 137, 133, 137, 141, 143, 145, 147, 145, 149, 153,
-  156, 156, 160, 164, 160, 171, 176, 177, 174, 181, 185, 192, 193, 197, 203, 201,
-  206, 206, 212, 212, 215, 216, 218, 218, 215, 219, 218, 219, 189, 68, 81, 101,
-  96, 108, 103, 98, 101, 105, 98, 108, 98, 108, 103, 86, 86, 84, 91, 94,
-  86, 81, 139, 184, 209, 212, 203, 177, 121, 89, 66, 71, 52, 41, 55, 63,
-  81, 66, 63, 66, 86, 96, 110, 112, 108, 105, 86, 66, 66, 57, 52, 71,
-  84, 94, 110, 119, 108, 114, 105, 98, 96, 71, 55, 46, 68, 60, 68, 46,
-  23, 49, 79, 98, 105, 98, 110, 139, 171, 184, 193, 193, 190, 169, 145, 89,
-  91, 110, 133, 149, 171, 179, 179, 182, 182, 185, 187, 192, 181, 172, 165, 119,
-  76, 94, 89, 23, 32, 23, 41, 41, 32, 46, 23, 68, 55, 29, 43, 35,
-  76, 43, 35, 35, 32, 35, 84, 55, 103, 23, 49, 84, 117, 79, 94, 32,
-  32, 26, 41, 108, 20, 32, 55, 71, 149, 35, 32, 46, 68, 108, 121, 181,
-  135, 20, 63, 43, 32, 15, 29, 29, 23, 38, 18, 26, 20, 32, 38, 41,
-  32, 35, 26, 20, 18, 23, 32, 74, 76, 81, 91, 98, 105, 110, 125, 117,
-  114, 114, 125, 123, 125, 121, 125, 131, 131, 135, 135, 143, 127, 133, 135, 135,
-  131, 133, 143, 139, 137, 141, 141, 143, 145, 139, 141, 151, 139, 141, 139, 139,
-  141, 141, 131, 131, 137, 139, 137, 135, 139, 139, 149, 141, 143, 149, 149, 151,
-  149, 156, 162, 165, 162, 169, 174, 171, 181, 181, 185, 185, 190, 195, 197, 201,
-  207, 206, 207, 210, 213, 213, 216, 215, 216, 219, 218, 218, 213, 84, 84, 89,
-  94, 103, 105, 103, 112, 114, 103, 112, 110, 103, 98, 94, 108, 105, 112, 101,
-  96, 86, 123, 167, 187, 190, 177, 129, 79, 79, 81, 71, 55, 66, 74, 68,
-  63, 66, 57, 60, 94, 105, 121, 108, 96, 89, 76, 84, 66, 55, 49, 71,
-  98, 108, 114, 117, 119, 110, 108, 103, 89, 57, 46, 63, 71, 55, 55, 49,
-  26, 43, 55, 76, 96, 108, 112, 137, 165, 189, 192, 192, 187, 174, 139, 101,
-  91, 103, 131, 153, 167, 176, 181, 181, 187, 185, 185, 190, 185, 181, 169, 137,
-  57, 89, 43, 41, 41, 20, 32, 35, 35, 43, 49, 66, 66, 32, 35, 41,
-  81, 41, 20, 41, 32, 43, 60, 74, 76, 23, 38, 101, 114, 129, 125, 66,
-  55, 52, 29, 114, 60, 79, 29, 46, 133, 71, 89, 38, 81, 131, 117, 145,
-  160, 103, 49, 29, 41, 15, 32, 32, 23, 41, 41, 26, 23, 23, 12, 29,
-  20, 26, 43, 41, 55, 81, 68, 84, 84, 105, 110, 117, 125, 121, 125, 119,
-  127, 121, 125, 123, 125, 129, 131, 131, 125, 141, 127, 127, 137, 137, 135, 135,
-  129, 131, 133, 135, 131, 135, 145, 145, 139, 143, 141, 143, 141, 139, 147, 135,
-  137, 139, 143, 127, 133, 135, 141, 139, 135, 137, 141, 147, 143, 143, 149, 149,
-  158, 158, 160, 160, 164, 167, 167, 172, 181, 184, 184, 189, 190, 193, 198, 198,
-  203, 206, 206, 210, 210, 215, 216, 216, 216, 218, 219, 219, 216, 112, 79, 89,
-  91, 91, 96, 101, 105, 108, 103, 112, 110, 105, 105, 101, 108, 108, 114, 112,
-  98, 101, 105, 141, 155, 147, 121, 84, 81, 63, 63, 74, 66, 79, 79, 63,
-  66, 63, 74, 74, 89, 110, 117, 103, 91, 57, 57, 57, 55, 55, 63, 96,
-  105, 110, 119, 129, 119, 108, 103, 91, 66, 63, 57, 49, 52, 52, 43, 32,
-  41, 35, 55, 63, 91, 91, 91, 125, 160, 181, 189, 190, 187, 172, 143, 127,
-  98, 112, 131, 153, 169, 181, 181, 187, 185, 184, 189, 190, 187, 167, 165, 153,
-  46, 76, 29, 32, 23, 18, 38, 38, 29, 35, 49, 52, 52, 55, 32, 41,
-  89, 52, 32, 43, 38, 68, 68, 105, 60, 15, 29, 94, 112, 127, 105, 76,
-  29, 15, 94, 84, 137, 12, 9, 52, 35, 123, 49, 74, 41, 141, 114, 105,
-  110, 117, 110, 23, 23, 35, 35, 29, 29, 20, 15, 23, 20, 15, 29, 29,
-  52, 41, 71, 68, 79, 74, 86, 98, 114, 110, 117, 110, 112, 112, 117, 121,
-  125, 121, 121, 125, 125, 119, 129, 127, 119, 129, 127, 133, 135, 131, 129, 135,
-  129, 135, 137, 141, 139, 133, 143, 141, 143, 145, 143, 147, 143, 139, 137, 137,
-  145, 135, 145, 141, 131, 137, 135, 141, 139, 137, 141, 139, 141, 149, 149, 151,
-  153, 155, 160, 162, 156, 167, 169, 169, 177, 181, 182, 190, 192, 198, 197, 200,
-  203, 204, 206, 207, 210, 212, 215, 218, 216, 218, 216, 219, 221, 169, 63, 79,
-  86, 96, 103, 101, 103, 110, 108, 110, 119, 110, 108, 101, 117, 121, 114, 114,
-  108, 114, 108, 108, 119, 112, 98, 86, 81, 76, 79, 76, 89, 76, 79, 68,
-  49, 55, 76, 91, 98, 112, 86, 81, 66, 63, 55, 46, 49, 55, 74, 110,
-  105, 112, 117, 129, 125, 114, 110, 86, 63, 63, 52, 55, 52, 49, 41, 38,
-  35, 49, 41, 57, 74, 89, 84, 129, 149, 179, 189, 193, 189, 176, 147, 131,
-  98, 112, 129, 149, 165, 176, 177, 184, 185, 185, 182, 189, 182, 174, 167, 149,
-  43, 79, 35, 49, 29, 32, 46, 43, 23, 32, 46, 63, 74, 60, 46, 49,
-  60, 94, 20, 32, 32, 46, 86, 101, 46, 29, 23, 71, 121, 71, 135, 110,
-  18, 15, 38, 94, 127, 76, 12, 57, 89, 49, 129, 38, 71, 110, 103, 135,
-  49, 121, 103, 43, 32, 29, 32, 23, 20, 9, 18, 26, 41, 41, 55, 63,
-  74, 79, 89, 94, 89, 98, 110, 114, 110, 110, 114, 117, 119, 121, 119, 125,
-  127, 127, 119, 125, 119, 121, 117, 133, 131, 133, 127, 129, 127, 125, 131, 141,
-  137, 129, 133, 135, 137, 137, 133, 137, 135, 143, 139, 139, 141, 133, 145, 137,
-  141, 137, 149, 139, 133, 137, 133, 139, 135, 139, 135, 137, 141, 149, 143, 151,
-  145, 153, 156, 156, 162, 164, 169, 172, 171, 182, 181, 184, 185, 193, 197, 195,
-  198, 201, 207, 206, 209, 210, 215, 215, 216, 216, 219, 221, 218, 198, 74, 68,
-  86, 81, 96, 103, 103, 112, 114, 123, 117, 112, 114, 119, 123, 119, 112, 108,
-  114, 117, 103, 110, 98, 101, 94, 89, 86, 96, 91, 101, 91, 76, 84, 71,
-  76, 71, 86, 105, 103, 101, 81, 94, 76, 66, 66, 57, 49, 74, 91, 108,
-  112, 125, 129, 121, 112, 108, 105, 81, 71, 57, 41, 49, 57, 43, 49, 46,
-  38, 63, 55, 57, 63, 76, 76, 121, 155, 181, 192, 203, 200, 185, 151, 133,
-  94, 105, 131, 153, 169, 177, 185, 181, 184, 182, 190, 189, 185, 176, 165, 117,
-  60, 66, 55, 74, 35, 20, 43, 35, 35, 43, 41, 60, 46, 49, 55, 55,
-  38, 108, 41, 32, 32, 32, 66, 101, 35, 32, 20, 66, 119, 52, 129, 137,
-  41, 23, 15, 103, 108, 117, 32, 15, 26, 98, 127, 68, 41, 66, 121, 127,
-  127, 84, 66, 66, 23, 18, 18, 32, 23, 32, 52, 20, 35, 41, 49, 63,
-  71, 89, 101, 103, 103, 103, 101, 110, 112, 117, 121, 125, 117, 123, 117, 125,
-  117, 121, 125, 117, 121, 121, 133, 127, 131, 135, 129, 135, 133, 129, 131, 133,
-  137, 135, 137, 133, 133, 135, 139, 141, 135, 147, 141, 143, 141, 139, 143, 147,
-  143, 137, 141, 145, 137, 137, 145, 147, 137, 143, 145, 145, 141, 147, 147, 153,
-  147, 153, 156, 160, 160, 164, 165, 165, 172, 172, 176, 184, 181, 184, 192, 195,
-  195, 203, 203, 204, 209, 207, 213, 216, 215, 215, 216, 218, 221, 213, 79, 66,
-  81, 94, 94, 103, 108, 110, 117, 112, 114, 117, 117, 121, 121, 125, 119, 112,
-  114, 110, 103, 103, 105, 96, 98, 91, 89, 105, 103, 98, 94, 79, 74, 74,
-  79, 76, 96, 101, 79, 86, 79, 55, 68, 68, 81, 68, 55, 81, 98, 117,
-  119, 129, 127, 112, 119, 98, 81, 63, 46, 43, 41, 49, 35, 32, 38, 26,
-  41, 46, 49, 41, 60, 49, 63, 110, 155, 192, 207, 209, 207, 206, 177, 137,
-  105, 119, 133, 156, 167, 181, 181, 185, 185, 185, 187, 192, 185, 177, 131, 57,
-  32, 46, 43, 49, 38, 49, 52, 32, 29, 46, 43, 60, 46, 46, 43, 63,
-  32, 84, 84, 20, 35, 18, 91, 119, 66, 43, 32, 46, 114, 52, 84, 143,
-  105, 49, 23, 89, 108, 127, 74, 15, 15, 60, 76, 145, 26, 26, 89, 98,
-  129, 57, 29, 55, 23, 43, 20, 20, 41, 29, 29, 26, 38, 68, 68, 81,
-  89, 103, 101, 108, 110, 105, 108, 112, 114, 119, 117, 119, 112, 117, 123, 123,
-  127, 121, 125, 125, 117, 123, 131, 121, 131, 133, 127, 133, 131, 133, 131, 131,
-  133, 131, 127, 139, 133, 137, 141, 137, 137, 141, 135, 137, 141, 139, 145, 143,
-  139, 141, 145, 145, 141, 143, 139, 141, 141, 143, 141, 145, 145, 145, 147, 149,
-  153, 149, 156, 162, 158, 169, 167, 169, 171, 176, 182, 182, 187, 190, 193, 192,
-  192, 200, 206, 206, 207, 207, 212, 215, 215, 215, 213, 219, 216, 216, 123, 55,
-  86, 89, 96, 108, 110, 110, 117, 117, 114, 121, 123, 125, 121, 123, 108, 117,
-  110, 110, 110, 103, 101, 98, 89, 91, 108, 108, 110, 101, 84, 81, 76, 68,
-  89, 98, 96, 94, 84, 68, 60, 49, 63, 57, 84, 63, 68, 103, 117, 125,
-  127, 121, 123, 108, 98, 94, 84, 63, 57, 41, 49, 60, 38, 43, 35, 32,
-  35, 49, 55, 38, 55, 52, 71, 114, 156, 203, 209, 212, 209, 209, 197, 153,
-  103, 114, 129, 155, 167, 176, 184, 184, 187, 182, 189, 189, 185, 174, 143, 105,
-  52, 46, 46, 38, 55, 26, 35, 38, 32, 43, 43, 52, 49, 38, 46, 60,
-  38, 52, 117, 18, 26, 35, 125, 103, 35, 38, 41, 52, 110, 68, 55, 156,
-  147, 55, 23, 20, 79, 129, 32, 60, 12, 32, 71, 123, 105, 18, 43, 60,
-  112, 123, 76, 46, 38, 29, 23, 15, 32, 35, 29, 35, 63, 76, 86, 91,
-  91, 105, 105, 110, 114, 110, 105, 110, 112, 119, 119, 121, 119, 123, 121, 117,
-  123, 125, 125, 123, 129, 123, 123, 123, 123, 127, 127, 129, 133, 133, 127, 127,
-  131, 133, 137, 129, 129, 129, 131, 133, 139, 145, 133, 141, 147, 147, 143, 145,
-  143, 147, 153, 141, 147, 147, 141, 149, 145, 139, 145, 143, 151, 147, 147, 147,
-  153, 149, 155, 158, 156, 162, 167, 167, 172, 174, 176, 185, 189, 185, 189, 195,
-  192, 197, 203, 206, 206, 207, 210, 212, 213, 215, 213, 216, 218, 218, 171, 71,
-  76, 84, 84, 94, 84, 108, 117, 105, 110, 127, 129, 125, 127, 117, 121, 119,
-  112, 114, 114, 112, 101, 101, 98, 108, 114, 114, 110, 103, 91, 89, 79, 89,
-  91, 98, 103, 89, 81, 57, 68, 57, 55, 66, 60, 74, 86, 108, 121, 129,
-  129, 127, 112, 110, 91, 71, 63, 46, 38, 46, 46, 41, 38, 41, 41, 60,
-  35, 41, 43, 41, 52, 46, 49, 112, 165, 204, 209, 212, 213, 209, 200, 179,
-  98, 112, 127, 153, 167, 176, 181, 184, 185, 182, 189, 187, 181, 174, 149, 137,
-  79, 46, 29, 32, 60, 35, 57, 35, 57, 91, 49, 38, 41, 38, 52, 55,
-  55, 35, 94, 52, 35, 23, 155, 79, 35, 32, 32, 84, 123, 43, 81, 114,
-  162, 81, 23, 23, 35, 110, 71, 55, 49, 20, 76, 60, 121, 43, 35, 63,
-  91, 110, 103, 121, 26, 20, 6, 15, 20, 26, 41, 60, 66, 71, 91, 103,
-  101, 105, 98, 103, 112, 119, 110, 103, 117, 121, 125, 121, 119, 123, 117, 121,
-  119, 121, 125, 121, 125, 123, 119, 129, 125, 127, 127, 123, 133, 133, 127, 131,
-  131, 135, 131, 131, 137, 135, 137, 129, 141, 135, 137, 141, 137, 139, 151, 141,
-  141, 143, 139, 147, 147, 143, 137, 147, 143, 141, 145, 151, 143, 149, 149, 153,
-  155, 147, 149, 160, 158, 164, 169, 167, 172, 171, 182, 184, 181, 184, 190, 193,
-  198, 197, 198, 203, 212, 210, 210, 212, 212, 215, 216, 216, 218, 219, 200, 55,
-  68, 76, 96, 114, 105, 114, 96, 117, 110, 129, 123, 127, 117, 121, 121, 112,
-  112, 110, 103, 108, 105, 108, 110, 112, 121, 123, 112, 98, 89, 84, 94, 105,
-  101, 101, 91, 81, 79, 84, 71, 79, 68, 57, 81, 86, 108, 125, 131, 131,
-  133, 123, 112, 96, 84, 71, 46, 38, 41, 35, 46, 52, 43, 49, 63, 63,
-  38, 49, 41, 35, 55, 43, 55, 112, 171, 206, 209, 210, 210, 207, 201, 182,
-  108, 117, 131, 151, 165, 179, 182, 182, 184, 182, 184, 182, 181, 182, 129, 131,
-  91, 35, 32, 26, 46, 20, 49, 26, 43, 41, 46, 46, 41, 46, 84, 84,
-  79, 52, 49, 74, 43, 46, 151, 71, 38, 32, 43, 79, 112, 15, 94, 76,
-  149, 139, 35, 15, 46, 133, 139, 38, 71, 43, 49, 91, 60, 91, 18, 71,
-  79, 133, 84, 129, 127, 38, 18, 15, 18, 32, 41, 57, 76, 79, 84, 91,
-  98, 103, 108, 108, 114, 112, 112, 108, 112, 117, 123, 121, 119, 117, 121, 125,
-  121, 125, 123, 125, 129, 123, 119, 114, 137, 127, 131, 129, 125, 129, 127, 129,
-  135, 137, 129, 131, 131, 133, 135, 139, 137, 141, 143, 149, 145, 145, 133, 139,
-  145, 139, 141, 139, 147, 147, 147, 147, 155, 147, 141, 145, 145, 155, 149, 155,
-  156, 156, 155, 155, 164, 164, 167, 165, 162, 172, 172, 182, 177, 185, 192, 192,
-  190, 197, 200, 204, 206, 207, 207, 210, 212, 213, 216, 216, 216, 218, 213, 89,
-  76, 79, 86, 86, 94, 110, 103, 108, 121, 117, 123, 123, 121, 123, 129, 112,
-  112, 114, 108, 117, 114, 105, 117, 121, 121, 119, 108, 101, 86, 89, 91, 96,
-  81, 84, 74, 89, 79, 84, 89, 66, 68, 71, 89, 108, 121, 135, 133, 133,
-  125, 114, 98, 89, 68, 55, 60, 26, 32, 43, 43, 63, 43, 63, 96, 76,
-  32, 38, 41, 35, 46, 46, 46, 89, 169, 206, 206, 209, 209, 204, 197, 184,
-  98, 108, 133, 155, 164, 176, 181, 182, 182, 185, 185, 185, 184, 177, 112, 98,
-  74, 41, 57, 20, 18, 29, 55, 35, 52, 49, 79, 43, 41, 55, 71, 96,
-  71, 35, 43, 55, 60, 79, 149, 35, 52, 38, 52, 79, 129, 23, 71, 68,
-  76, 135, 105, 23, 46, 145, 137, 49, 15, 26, 49, 91, 68, 41, 29, 26,
-  41, 103, 71, 86, 143, 139, 35, 43, 32, 57, 66, 68, 76, 79, 96, 101,
-  103, 105, 110, 103, 108, 121, 114, 114, 123, 114, 123, 119, 121, 119, 127, 117,
-  121, 125, 119, 119, 127, 123, 119, 127, 131, 127, 127, 127, 131, 133, 125, 125,
-  131, 131, 137, 133, 131, 139, 135, 137, 143, 139, 141, 137, 141, 147, 137, 147,
-  143, 145, 147, 141, 147, 149, 147, 143, 153, 147, 153, 139, 145, 153, 147, 149,
-  153, 155, 156, 158, 160, 162, 171, 165, 169, 169, 172, 174, 179, 184, 185, 192,
-  193, 197, 200, 200, 203, 207, 206, 210, 212, 212, 213, 210, 216, 221, 221, 127,
-  71, 81, 94, 96, 89, 98, 94, 117, 110, 121, 119, 121, 129, 129, 123, 123,
-  121, 114, 114, 119, 125, 129, 135, 129, 121, 110, 110, 86, 94, 91, 76, 84,
-  79, 81, 68, 91, 86, 84, 84, 81, 71, 81, 91, 114, 133, 139, 137, 131,
-  131, 105, 89, 76, 49, 43, 41, 38, 41, 41, 43, 52, 68, 84, 94, 91,
-  32, 46, 43, 38, 52, 29, 38, 79, 156, 206, 206, 206, 209, 204, 197, 174,
-  108, 121, 133, 155, 167, 169, 176, 185, 184, 182, 185, 185, 179, 182, 129, 94,
-  66, 38, 32, 18, 18, 43, 68, 15, 46, 23, 71, 55, 41, 55, 63, 63,
-  63, 55, 38, 68, 96, 149, 96, 38, 71, 18, 46, 66, 123, 35, 35, 76,
-  60, 55, 151, 91, 35, 137, 98, 29, 38, 35, 32, 57, 79, 63, 66, 23,
-  38, 74, 98, 18, 103, 71, 129, 35, 60, 66, 68, 84, 79, 81, 89, 96,
-  103, 101, 101, 108, 110, 114, 112, 117, 114, 119, 127, 127, 119, 123, 119, 123,
-  119, 121, 123, 129, 125, 127, 123, 123, 123, 121, 129, 131, 133, 129, 125, 125,
-  127, 125, 131, 133, 133, 137, 133, 131, 137, 139, 141, 139, 137, 141, 137, 137,
-  141, 139, 141, 141, 145, 145, 147, 149, 147, 147, 147, 147, 153, 151, 149, 149,
-  162, 167, 158, 155, 160, 165, 164, 171, 165, 167, 174, 172, 177, 181, 184, 192,
-  192, 198, 198, 203, 200, 203, 206, 207, 210, 212, 213, 212, 216, 215, 218, 160,
-  108, 101, 98, 96, 94, 94, 96, 101, 108, 108, 125, 133, 133, 135, 129, 123,
-  117, 121, 123, 121, 131, 137, 139, 133, 119, 117, 91, 76, 84, 76, 74, 71,
-  68, 60, 84, 89, 91, 91, 81, 76, 79, 96, 101, 125, 133, 139, 137, 131,
-  121, 101, 71, 49, 49, 38, 26, 20, 26, 35, 60, 74, 94, 94, 91, 96 };
-
 /* Define image 'milla' of size 211x242x1x3 and type 'const unsigned char' */
 const unsigned char data_milla[] = {
   93, 92, 92, 91, 91, 90, 90, 90, 92, 90, 92, 91, 91, 92, 92, 92,
@@ -21186,7 +17087,7 @@ const unsigned char data_milla[] = {
   104, 134, 165, 146, 141, 117, 138, 134, 131, 136, 145, 146, 138, 136, 140, 143,
   143, 143 };
 
-/* Define image 'test' of size 555x103x1x3 and type 'unsigned char' */
+/* Define image 'logo' of size 555x103x1x3 and type 'unsigned char' */
 const unsigned char data_logo[] = {
   76, 77, 75, 75, 75, 99, 102, 72, 63, 0, 84, 115, 114, 110, 115, 80,
   81, 108, 112, 69, 38, 87, 115, 118, 96, 116, 84, 88, 85, 107, 83, 72,
diff --git a/examples/odykill.cpp b/examples/odykill.cpp
index 839cf02..9c17e38 100644
--- a/examples/odykill.cpp
+++ b/examples/odykill.cpp
@@ -155,17 +155,17 @@ int main(int argc,char **argv) {
         int n = 5 + ((int)(200*cimg::rand())%16);
         enemy = graphics[n];
         m_enemy = masks[n];
-        enemy_x=cimg::crand()*1e8; enemy_y=cimg::crand()*1e8; enemy_z=cimg::crand()*1e8;
+        enemy_x=cimg::rand(-1,1)*1e8; enemy_y=cimg::rand(-1,1)*1e8; enemy_z=cimg::rand(-1,1)*1e8;
         va = angle = 0;
       }
     }
 
-    if (enemy_x<0) { enemy_x=0; vx = speed*cimg::crand(); }
-    if (enemy_x>canvas.width()) { enemy_x=canvas.width(); vx = speed*cimg::crand(); }
-    if (enemy_y<0) { enemy_y=0; vy = speed*cimg::crand(); }
-    if (!shooted && enemy_y>canvas.height()) { enemy_y=canvas.height(); vy = speed*cimg::crand(); }
-    if (enemy_z<0.1) { enemy_z = 0.1; vz = speed*0.01*cimg::crand(); }
-    if (enemy_z>0.7) { enemy_z = 0.7; vz = speed*0.01*cimg::crand(); }
+    if (enemy_x<0) { enemy_x=0; vx = speed*cimg::rand(-1,1); }
+    if (enemy_x>canvas.width()) { enemy_x=canvas.width(); vx = speed*cimg::rand(-1,1); }
+    if (enemy_y<0) { enemy_y=0; vy = speed*cimg::rand(-1,1); }
+    if (!shooted && enemy_y>canvas.height()) { enemy_y=canvas.height(); vy = speed*cimg::rand(-1,1); }
+    if (enemy_z<0.1) { enemy_z = 0.1; vz = speed*0.01*cimg::rand(-1,1); }
+    if (enemy_z>0.7) { enemy_z = 0.7; vz = speed*0.01*cimg::rand(-1,1); }
     angle+=va;
 
     // Handle mouse interaction
diff --git a/examples/wavelet_atrous.cpp b/examples/wavelet_atrous.cpp
index 28f4ba4..cfaeb14 100644
--- a/examples/wavelet_atrous.cpp
+++ b/examples/wavelet_atrous.cpp
@@ -61,40 +61,39 @@ using namespace cimg_library;
 
 // Define convolution mask.
 CImg<float> mask(const unsigned char dirIdx, const unsigned char scale) {
-  int d1 = 1 << (scale-1);
-  int d2 = 1 << scale;
-  int c = d2;
-  int vecLen = (1 << (scale + 1)) + 1;
+  const int
+    d1 = 1 << (scale-1),
+    d2 = 1 << scale,
+    c = d2,
+    vecLen = (1 << (scale + 1)) + 1;
 
-  float valC  = 0.375f;  // 6/16
-  float valD1 = 0.25f;   // 4/16
-  float valD2 = 0.0625f; // 1/16
+  const float
+    valC  = 0.375f,  // 6/16
+    valD1 = 0.25f,   // 4/16
+    valD2 = 0.0625f; // 1/16
 
-  switch(dirIdx){
-  case 0: //x
-    {
-      CImg<float> m(vecLen,1,1);m.fill(0);
-      m(c) = valC;
-      m(c - d1) =  m(c + d1) = valD1;
-      m(c - d2) =  m(c + d2) = valD2;
-      return m;
-    }
-  case 1: //y
-    {
-      CImg<float> m(1,vecLen,1);m.fill(0);
-      m(0,c) = valC;
-      m(0,c - d1) =  m(0,c + d1) = valD1;
-      m(0,c - d2) =  m(0,c + d2) = valD2;
-      return m;
-    }
-  case 2: //t
-    {
-      CImg<float> m(1,1,vecLen);m.fill(0);
-      m(0,0,c) = valC;
-      m(0,0,c - d1) =  m(0,0,c + d1) = valD1;
-      m(0,0,c - d2) =  m(0,0,c + d2) = valD2;
-      return m;
-    }
+  switch(dirIdx) {
+  case 0 : { // x
+    CImg<float> m(vecLen,1,1,1,0);
+    m(c) = valC;
+    m(c - d1) = m(c + d1) = valD1;
+    m(c - d2) = m(c + d2) = valD2;
+    return m;
+  }
+  case 1: { // y
+    CImg<float> m(1,vecLen,1,1,0);
+    m(0,c) = valC;
+    m(0,c - d1) = m(0,c + d1) = valD1;
+    m(0,c - d2) = m(0,c + d2) = valD2;
+    return m;
+  }
+  case 2: { // t
+    CImg<float> m(1,1,vecLen,1,0);
+    m(0,0,c) = valC;
+    m(0,0,c - d1) = m(0,0,c + d1) = valD1;
+    m(0,0,c - d2) = m(0,0,c + d2) = valD2;
+    return m;
+  }
   default: throw CImgException("Error, unknow decompostion axe, dirIdx = '%c'.",dirIdx);
   }
 }
@@ -103,7 +102,6 @@ CImg<float> mask(const unsigned char dirIdx, const unsigned char scale) {
   Main procedure
   ----------------*/
 int main(int argc,char **argv) {
-
   cimg_usage("Perform an 'a trous' wavelet transform (using a cubic spline) on an image or on a video sequence.\n"
              "This wavelet transform is undecimated and produces 2 images/videos at each scale. For an example of\n"
              "decomposition on a video, try -i img/trees.inr (sequence from the MIT).\n"
@@ -119,7 +117,7 @@ int main(int argc,char **argv) {
     s = cimg_option("-s",3,"Scale of decomposition");
 
   const bool help = cimg_option("-h",false,"Display Help");
-  if(help) exit(0);
+  if (help) std::exit(0);
 
   // Initialize Image Data
   std::fprintf(stderr," - Load image sequence '%s'...\n",cimg::basename(name_i));
@@ -127,57 +125,55 @@ int main(int argc,char **argv) {
   CImg<float> mask_conv;
   CImgList<float> res(s,texture_in.width(),texture_in.height(),texture_in.depth());
   CImgList<float> wav(s,texture_in.width(),texture_in.height(),texture_in.depth());
-  cimglist_for(res,l) { res(l).fill(0.0); wav(l).fill(0.0);}
+  cimglist_for(res,l) { res(l).fill(0.0); wav(l).fill(0.0); }
   unsigned int i;
 
-  int firstDirIdx = 0;
-  int lastDirIdx = 2;
-  if (axe_dec){// The multiscale decomposition will be performed in just one direction
+  int firstDirIdx = 0,lastDirIdx = 2;
+  if (axe_dec) { // The multiscale decomposition will be performed in just one direction
     char c = cimg::uncase(axe_dec[0]);
     switch(c) {
-    case 'x': {firstDirIdx = 0; break;}
-    case 'y': {firstDirIdx = 1; break;}
-    case 't': {firstDirIdx = 2; break;}
+    case 'x': firstDirIdx = 0; break;
+    case 'y': firstDirIdx = 1; break;
+    case 't': firstDirIdx = 2; break;
     default: throw CImgException("Error, unknow decompostion axe '%c', try 'x', 'y' or 't'",c);
     }
-    lastDirIdx = firstDirIdx;//only one direction
+    lastDirIdx = firstDirIdx; // Only one direction
   }
 
-  for(i=0;i<s;i++){
+  for (i = 0; i<s; i++) {
     std::fprintf(stderr," - Performing scale %u ...\n",i + 1);
-    if(i==0){ res(i) =  texture_in;} else {  res(i) = res(i - 1);}
-    for(int di=firstDirIdx;di<=lastDirIdx;di++){
-      mask_conv = mask((unsigned char)di, (unsigned char)(i + 1));
+    if (i==0) { res(i) = texture_in;} else { res(i) = res(i - 1); }
+    for (int di = firstDirIdx; di<=lastDirIdx; di++) {
+      mask_conv = mask((unsigned char)di,(unsigned char)(i + 1));
       res(i) = res(i).get_convolve(mask_conv);
     }
-    if(i==0){wav(i) = texture_in - res(i);}  // res(0) and wav(0) are the 1st scale of decompostion
-    else {wav(i) = res(i - 1) - res(i);}
+    if (i==0) { wav(i) = texture_in - res(i); } // res(0) and wav(0) are the 1st scale of decompostion
+    else { wav(i) = res(i - 1) - res(i); }
   }
 
-  if (*name_o){
-    // Save the Multi-Scale Analysis
+  if (*name_o) {
+    // Save the Multi-Scale Analysis.
     std::fprintf(stderr," - Saving of all output sequences : %s in the msa/ directory... \n",cimg::basename(name_o));
     int count = 1; // res0 = original image
     char filename[256] = "", filename_wav[256] = "";
     char STmp[3] = "";
     const int err = std::system("mkdir msa");
-    if (!err) for(i=0;i<s;i++) {
-      std::strcpy( filename, "msa/res" );
-      std::strcpy( filename_wav, "msa/wav" );
-      if( count < 10 )
-        { std::strcat( filename, "0" );std::strcat( filename_wav, "0" );}
-      std::sprintf( STmp, "%d_", count );
-      std::strcat( filename, STmp ); std::strcat( filename_wav, STmp );
-      std::strcat( filename,name_o);std::strcat( filename_wav,name_o);
-      res(i).save(filename);
-      wav(i).save(filename_wav);
-      count++;
-    }
+    if (!err) for (i = 0; i<s; i++) {
+        std::strcpy( filename, "msa/res" );
+        std::strcpy( filename_wav, "msa/wav" );
+        if (count<10) { std::strcat( filename, "0" ); std::strcat( filename_wav, "0" ); }
+        std::sprintf(STmp,"%d_",count);
+        std::strcat(filename,STmp); std::strcat(filename_wav,STmp);
+        std::strcat(filename,name_o); std::strcat(filename_wav,name_o);
+        res(i).save(filename);
+        wav(i).save(filename_wav);
+        count++;
+      }
   }
 
-  // Result visualization
+  // Result visualization.
   const float col[] = { 255, 255, 255 };
-  for(i=0;i<s;i++) {
+  for (i = 0; i<s; i++) {
     res[i].normalize(0,255).draw_text(2,2,"Scale %d",col,0,1,13,i);
     wav[i].normalize(0,255).draw_text(2,2,"Scale %d",col,0,1,13,i);
   }
diff --git a/html/CImg_documentation.h b/html/CImg_documentation.h
index 5004725..7019852 100644
--- a/html/CImg_documentation.h
+++ b/html/CImg_documentation.h
@@ -56,7 +56,7 @@
   The %CImg Library consists in a single header file <tt>CImg.h</tt> providing a set of C++ template classes that
   can be used in your own sources, to load/save, process and display images or list of images.
   Very portable (Unix/X11,Windows, MacOS X, FreeBSD,..), efficient, simple to use, it's a pleasant toolkit
-  for coding image processing stuffs in C++.
+  for coding image processing stuff in C++.
 
   The header file <tt>CImg.h</tt> contains all the classes and functions that compose the library itself.
   This is one originality of the %CImg Library. This particularly means that :
@@ -64,7 +64,7 @@
   the compilation of your own C++ code.
   - No complex dependencies have to be handled : Just include the <tt>CImg.h</tt> file, and you get a working C++ image processing toolkit.
   - The compilation is done on the fly : only CImg functionalities really used by your program are compiled and appear in the
-  compiled executable program. This leads to very compact code, without any unused stuffs.
+  compiled executable program. This leads to very compact code, without any unused stuff.
   - Class members and functions are inlined, leading to better performance during the program execution.
 
   The %CImg Library is structured as follows :
@@ -94,7 +94,7 @@
   as environment variables are automatically set by the CImg library (see also \ref cimg_environment).
 
   - The class \ref cimg_library::CImgException (and its subclasses) are used by the library to throw exceptions
-  when errors occur. Those exceptions can be catched with a bloc <tt>try { ..} catch (CImgException) { .. }</tt>.
+  when errors occur. Those exceptions can be caught with a <tt>try { ..} catch (CImgException) { .. }</tt> block.
   Subclasses define precisely the type of encountered errors.
 
   Knowing these four classes is \b enough to get benefit of the %CImg Library functionalities.
@@ -102,7 +102,7 @@
 
   \section s2 CImg version of "Hello world".
 
-  Below is a very simple code that creates a "Hello World" image. This shows you basically how a CImg program looks like.
+  Below is some very simple code that creates a "Hello World" image. This shows you basically how a CImg program looks like.
 
   \code
   #include "CImg.h"
@@ -132,15 +132,15 @@
   \endcode
 
   Generally, you can write very small code that performs complex image processing tasks. The %CImg Library is very simple
-  to use and provide a lot of interesting algorithms for image manipulation.
+  to use and provides a lot of interesting algorithms for image manipulation.
 
   \section s3 How to compile ?
 
   The CImg library is a very light and user-friendly library : only standard system libraries are used.
-  It avoid to handle complex dependancies and problems with library compatibility.
+  It avoids handling complex dependencies and problems with library compatibility.
   The only thing you need is a (quite modern) C++ compiler :
 
-  - <b>Microsoft Visual C++ 6.0, Visual Studio.NET and Visual Express Edition</b> : Use project files and solution files provided in the
+  - <b>Microsoft Visual C++ 6.0, Visual Studio.NET and Visual Express Edition</b> : Use the project files and solution files provided in the
   %CImg Library package (directory 'compilation/') to see how it works.
   - <b>Intel ICL compiler</b> : Use the following command to compile a CImg-based program with ICL :
   \code
@@ -164,9 +164,9 @@
   \endcode
   - <b>Dev-Cpp</b> : Use the project file provided in the CImg library package to see how it works.
 
-  If you are using another compilers and encounter problems, please
+  If you are using other compilers and encounter problems, please
   <a href="http://www.greyc.ensicaen.fr/~dtschump">write me</a> since maintaining compatibility is one
-  of the priority of the %CImg Library. Nevertheless, old compilers that does not respect the C++ norm will not
+  of the priorities of the %CImg Library. Nevertheless, old compilers that do not respect the C++ standard will not
   support the %CImg Library.
 
   \section s4 What's next ?
@@ -216,7 +216,7 @@
   <a href="https://raw.githubusercontent.com/dtschump/CImg/master/CImg.h">CImg.h</a>
   providing a set of C++ classes and functions that can be used in your own sources,
   to load/save, manage/process and display generic images.
-  It's actually a very simple and pleasant toolkit for coding image processing stuffs in C++ :
+  It's actually a very simple and pleasant toolkit for coding image processing stuff in C++ :
   Just include the header file <tt>CImg.h</tt>, and you are ready to handle images in your C++ programs.
 
   \subsection ssf12 1.2. What platforms are supported ?
@@ -518,7 +518,7 @@
   \code CImg<unsigned char> image("lena.jpg"), visu(500,400,1,3,0); \endcode
   Creation of two instances of images of \c unsigned \c char pixels.
   The first image \c image is initialized by reading an image file from the disk.
-  Here, <tt>lena.jpg</tt> must be in the same directory than the current program.
+  Here, <tt>lena.jpg</tt> must be in the same directory as the current program.
   Note that you must also have installed the \e ImageMagick package in order to be able to read JPG images.
   The second image \c visu is initialized as a black color image with dimension <tt>dx=500</tt>, <tt>dy=400</tt>,
   <tt>dz=1</tt> (here, it is a 2D image, not a 3D one), and <tt>dv=3</tt> (each pixel has 3 'vector' channels R,G,B).
@@ -803,7 +803,7 @@
   - and so on...
 
   The value of a neighborhood pixel outside the image range (image border problem) is automatically set to the same
-  values than the nearest valid pixel in the image (this is also called the \e Neumann \e border \e condition).
+  values as the nearest valid pixel in the image (this is also called the \e Neumann \e border \e condition).
 
   \subsection lo11 Example codes
   More than a long discussion, the above example will demonstrate how to compute the gradient norm of a 3D volume
@@ -826,7 +826,7 @@
   pixel values on a 5x5 neighborhood.
 
   \code
-  CImg<unsigned char> src("image_color.jpg"), dest(src,false), neighbor(5,5);  // Image definitions.
+  CImg<unsigned char> src("image_color.jpg"), dest(src,false);  // Image definitions.
   typedef unsigned char uchar;		   // Avoid space in the second parameter of the macro CImg_5x5x1 below.
   CImg<> N(5,5);	                   // Define a 5x5 neighborhood as a 5x5 image.
   cimg_forC(src,k)			   // Standard loop on color channels
@@ -994,7 +994,7 @@
    \param usage   : A brief explanation of the option. If \c usage==0, the option won't appear on the option list
 		    when invoking the executable with options \c -h or \c --help (hidden option).
 
-   \return \c cimg_option() returns an object that has the \e same \e type than the default value \c default.
+   \return \c cimg_option() returns an object that has the \e same \e type as the default value \c default.
    The return value is equal to the one specified on the command line. If no such option have been specified,
    the return value is equal to the default value \c default.
    Warning, this can be confusing in some situations (look at the end of the next section).
diff --git a/html/footer.html b/html/footer.html
index 4e0452f..332f792 100644
--- a/html/footer.html
+++ b/html/footer.html
@@ -7,10 +7,6 @@
       </font>
       <br/>
 
-      <center>
-        <a href="https://sourceforge.net/p/cimg/donate/"><img src="http://images.sourceforge.net/images/project-support.jpg" width="88" height="32" border="0" alt="Support This Project" /></a>
-      </center>
-
   </div></div><div id="footer"><img alt="" src="images/footer.jpg" />
 </div></div>
 
diff --git a/html/footer_reference.html b/html/footer_reference.html
index 5b2e29b..49a4d6c 100644
--- a/html/footer_reference.html
+++ b/html/footer_reference.html
@@ -10,9 +10,6 @@
       </font>
       <br/>
 
-      <center>
-        <a href="https://sourceforge.net/p/cimg/donate/"><img src="http://images.sourceforge.net/images/project-support.jpg" width="88" height="32" border="0" alt="Support This Project" /></a>
-      </center>
   </td></tr></table>
 
 <!-- Start of StatCounter Code -->
diff --git a/html/header.html b/html/header.html
index 0362191..2024925 100644
--- a/html/header.html
+++ b/html/header.html
@@ -46,11 +46,12 @@
             <a href="http://cimg.eu"><img src="http://cimg.eu/img/CImgLogo2.jpg" alt="" border="0" /></a><br/>
           </center>
           <center><font size="-1" color="#777777">
-              Latest stable version: <b><a href="http://cimg.eu/files">1.6.4</a></b>
-                 -   
-              Development snapshot: <b><a href="http://cimg.eu/files">1.6.5_pre</a></b>
+              Latest stable version: <b><a href="http://cimg.eu/files">1.7.1</a></b>
+              <!--    -    -->
+              <!-- Development snapshot: <b><a href="http://cimg.eu/files">1.7.2_pre</a></b> -->
           </font></center>
       </td></tr>
+      <tr bgcolor="#FFFFFF"><td><hr noshade size="1" style="border-top: 1px solid #ccc;"/></td></tr>
       <tr><td>
           <table width="95%" align="center"><tr>
               <td>
@@ -76,4 +77,5 @@
               </td>
           </tr></table>
       </td></tr>
+      <tr bgcolor="#FFFFFF"><td><hr noshade size="1" style="border-top: 1px solid #ccc;"/></td></tr>
     </table>
diff --git a/html/header_reference.html b/html/header_reference.html
index f70aaa2..5178ec2 100644
--- a/html/header_reference.html
+++ b/html/header_reference.html
@@ -44,8 +44,13 @@
             <br/><br/>
             <a href="http://cimg.eu"><img src="http://cimg.eu/img/CImgLogo2.jpg" alt="" border="0" /></a><br/>
           </center>
-          <center><font size="-1">Current stable version: <b><a href="http://cimg.eu/files">1.6.3</a></b></font><br/><br/></center>
+          <center><font size="-1" color="#777777">
+              Latest stable version: <b><a href="http://cimg.eu/files">1.7.1</a></b>
+              <!--    -    -->
+              <!-- Development snapshot: <b><a href="http://cimg.eu/files">1.7.2_pre</a></b> -->
+          </font></center>
       </td></tr>
+      <tr bgcolor="#FFFFFF"><td><hr noshade size="1" style="border-top: 1px solid #ccc;"/></td></tr>
       <tr><td>
           <table width="95%" align="center"><tr>
               <td>
@@ -72,6 +77,7 @@
             </td>
           </tr></table>
       </td></tr>
+      <tr bgcolor="#FFFFFF"><td><hr noshade size="1" style="border-top: 1px solid #ccc;"/></td></tr>
     </table>
 
     <table align="center" cellpadding="12" cellspacing="0" width="1000" style="border-style:solid; border-width:0px; border-color:black" bgcolor="#FFFFFF">
diff --git a/html/img/postcard54.jpg b/html/img/postcard54.jpg
new file mode 100644
index 0000000..52a8c74
Binary files /dev/null and b/html/img/postcard54.jpg differ
diff --git a/html/img/postcard55.jpg b/html/img/postcard55.jpg
new file mode 100644
index 0000000..e065206
Binary files /dev/null and b/html/img/postcard55.jpg differ
diff --git a/html/img/postcard56.jpg b/html/img/postcard56.jpg
new file mode 100644
index 0000000..dbf1c4c
Binary files /dev/null and b/html/img/postcard56.jpg differ
diff --git a/html/img/postcard57.jpg b/html/img/postcard57.jpg
new file mode 100644
index 0000000..22d68d3
Binary files /dev/null and b/html/img/postcard57.jpg differ
diff --git a/html/img/postcard58.jpg b/html/img/postcard58.jpg
new file mode 100644
index 0000000..9ef22bd
Binary files /dev/null and b/html/img/postcard58.jpg differ
diff --git a/html/img/postcard59.jpg b/html/img/postcard59.jpg
new file mode 100644
index 0000000..67c21eb
Binary files /dev/null and b/html/img/postcard59.jpg differ
diff --git a/html/img/postcard60.jpg b/html/img/postcard60.jpg
new file mode 100644
index 0000000..7574bc6
Binary files /dev/null and b/html/img/postcard60.jpg differ
diff --git a/html/img/postcard61.jpg b/html/img/postcard61.jpg
new file mode 100644
index 0000000..22d515e
Binary files /dev/null and b/html/img/postcard61.jpg differ
diff --git a/html/img/postcard62.jpg b/html/img/postcard62.jpg
new file mode 100644
index 0000000..c94e461
Binary files /dev/null and b/html/img/postcard62.jpg differ
diff --git a/html/index.shtml b/html/index.shtml
index 786b0d5..50f4588 100644
--- a/html/index.shtml
+++ b/html/index.shtml
@@ -87,12 +87,17 @@
 <div id="center"><div id="text_centre_intro">
 
 <blockquote>
-  <a href="http://tschumperle.users.greyc.fr/">David Tschumperlé</a> (project leader)<br/><br/>
+  <ul>
+    <li><a href="http://tschumperle.users.greyc.fr/">David Tschumperlé</a> (project leader)</li>
+  </ul>
+     (Check out his <a href="http://opensource.graphics">blog</a>)
+  <br/><br/>
   with the help of many contributors around the world :<br/><br/>
   <i>
     Maksim Aizenshtein,
     Alberto Albiol,
     Antonio Albiol,
+    Neil Brown,
     Haz-Edine Assemlal,
     Vincent Barra,
     Wolf Blecher,
@@ -241,7 +246,7 @@
       or parts of the <a href="reference/index.html">documentation</a>.</li>
     <li>If you just want to say you've been happy with the library, you can send me a postcard from your place, to the following address : <br/>
       <i>David Tschumperlé, GREYC (UMR CNRS 6072), Equipe IMAGE, 6 Bd du Maréchal Juin, 14050 Caen Cedex, FRANCE.</i><br/><br/>
-      53 postcards received yet (I still have empty space on my wall ! :) ), from :<br/><br/>
+      58 postcards received yet (I still have empty space on my wall ! :) ), from :<br/><br/>
       <ul>
         <li><a href="img/postcard1.jpg" onclick="NewWindow(this.href,'name','420','320','yes');return false;">
             Comissao Nacional de Energia Nuclear, Rio de Janeiro, Brazil.</a></li>
@@ -344,11 +349,24 @@
         <li><a href="img/postcard51.jpg" onclick="NewWindow(this.href,'name','420','320','yes');return false;">
             EDF/France, from ZondeR.</a></li>
         <li><a href="img/postcard52.jpg" onclick="NewWindow(this.href,'name','300','460','yes');return false;">
-            Belgium, from Marc Lis.</a><br/><br/></li>
+            Belgium, from Marc Lis.</a></li>
         <li><a href="img/postcard53.jpg" onclick="NewWindow(this.href,'name','420','320','yes');return false;">
-            Roma/Italy, from Patrick Wauters.</a><br/><br/></li>
-        <li>If you have too much money, you can also <a href="https://sourceforge.net/p/cimg/donate/">
-            <img src="img/project-support.jpg" alt=""></img></a></li>
+            Roma/Italy, from Patrick Wauters.</a></li>
+        <li><a href="img/postcard54.jpg" onclick="NewWindow(this.href,'name','420','320','yes');return false;">
+            Germany, from Werner Meier.</a></li>
+        <li><a href="img/postcard55.jpg" onclick="NewWindow(this.href,'name','320','420','yes');return false;">
+            Germany, from Justin Pletzfeld.</a></li>
+        <li><a href="img/postcard56.jpg" onclick="NewWindow(this.href,'name','420','320','yes');return false;">
+            New York/USA, from Garry R. Osgood.</a></li>
+        <li><a href="img/postcard57.jpg" onclick="NewWindow(this.href,'name','320','420','yes');return false;">
+            Italy, from Andrea (coder of PhotoFlow).</a></li>
+        <li><a href="img/postcard58.jpg" onclick="NewWindow(this.href,'name','420','320','yes');return false;">
+            Sydney/Australia, from Peter Neave.</a></li>
+        <li><a href="img/postcard59.jpg" onclick="NewWindow(this.href,'name','320','420','yes');return false;">
+            Fort Worth/Texas/USA, from Steve Gillow.</a></li>
+        <li><a href="img/postcard60.jpg" onclick="NewWindow(this.href,'name','420','320','yes');return false;">
+            Pondicherry/India, from Bruno Steinbach.</a></li>
+        <br/><br/></li>
     </ul></li>
   </ul>
 </blockquote>
diff --git a/html/style.css b/html/style.css
index 0adcd12..1a2cb65 100644
--- a/html/style.css
+++ b/html/style.css
@@ -1,148 +1,148 @@
 body {
-font-family: 'Open Sans', sans-serif;
-font-size:15px;
-line-height:20px;
+    font-family: 'Open Sans', sans-serif;
+    font-size:16px;
+    line-height:21px;
 }
 a {
-font-weight:bold;
-color:#636363;
+    font-weight:bold;
+    color:#636363;
 }
 tt {
-/* font-family:Arial, Helvetica, sans-serif; */
-font-family: 'Open Sans', sans-serif;
-color:#404040;
+    /* font-family:Arial, Helvetica, sans-serif; */
+    font-family: 'Open Sans', sans-serif;
+    color:#404040;
 }
 pre {
-/* font-family:Arial, Helvetica, sans-serif; */
-font-family: 'Open Sans', sans-serif;
-color:#404040;
+    /* font-family:Arial, Helvetica, sans-serif; */
+    font-family: 'Open Sans', sans-serif;
+    color:#404040;
 }
 #bloc_option {
-margin:0 auto;
-width:1000px;
+    margin:0 auto;
+    width:1000px;
 }
 #bloc_option_bis {
-margin:0 auto;
-width:1000px;
+    margin:0 auto;
+    width:1000px;
 }
 #top_bleu {
-width:1000px;
-height:47px;
-position:relative;
-float:left;
-background-image:url(images/header.jpg);
-background-repeat:no-repeat;
-font-size:20px;
-color:#fff;
+    width:1000px;
+    height:47px;
+    position:relative;
+    float:left;
+    background-image:url(images/header.jpg);
+    background-repeat:no-repeat;
+    font-size:20px;
+    color:#fff;
 }
 #top_gris {
-width:1000px;
-height:47px;
-position:relative;
-float:left;
-background-image:url(images/header.jpg);
-background-repeat:no-repeat;
-font-size:20px;
-color:#fff;
+    width:1000px;
+    height:47px;
+    position:relative;
+    float:left;
+    background-image:url(images/header.jpg);
+    background-repeat:no-repeat;
+    font-size:20px;
+    color:#fff;
 }
 #top_rouge {
-width:1000px;
-height:47px;
-position:relative;
-float:left;
-background-image:url(images/header.jpg);
-background-repeat:no-repeat;
-font-size:20px;
-color:#fff;
+    width:1000px;
+    height:47px;
+    position:relative;
+    float:left;
+    background-image:url(images/header.jpg);
+    background-repeat:no-repeat;
+    font-size:20px;
+    color:#fff;
 }
 #top_vert {
-width:1000px;
-height:47px;
-position:relative;
-float:left;
-background-image:url(images/header.jpg);
-background-repeat:no-repeat;
-font-size:18px;
-color:#fff;
+    width:1000px;
+    height:47px;
+    position:relative;
+    float:left;
+    background-image:url(images/header.jpg);
+    background-repeat:no-repeat;
+    font-size:18px;
+    color:#fff;
 }
 #top_bis {
-width:1000px;
-height:21px;
-position:relative;
-float:left;
-background-image:url(images/header_bis.jpg);
-background-repeat:no-repeat;
-font-size:20px;
-color:#fff;
+    width:1000px;
+    height:21px;
+    position:relative;
+    float:left;
+    background-image:url(images/header_bis.jpg);
+    background-repeat:no-repeat;
+    font-size:20px;
+    color:#fff;
 }
 #center{
-position:relative;
-float:left;
-width:1000px;
-text-align:justify;
-background-image:url(images/centre.jpg);
+    position:relative;
+    float:left;
+    width:1000px;
+    text-align:justify;
+    background-image:url(images/centre.jpg);
 }
 #text_centre_intro {
-padding-left:50px;
-padding-top:15px;
-width:900px;
-position:relative;
-float:left;
-text-align:justify;
-color:#404040;
+    padding-left:50px;
+    padding-top:15px;
+    width:900px;
+    position:relative;
+    float:left;
+    text-align:justify;
+    color:#404040;
 }
 #text_centre {
-padding-left:15px;
-padding-top:15px;
-width:940px;
-position:relative;
-float:left;
-text-align:justify;
-color:#636363;
+    padding-left:15px;
+    padding-top:15px;
+    width:940px;
+    position:relative;
+    float:left;
+    text-align:justify;
+    color:#636363;
 }
 #text_centre_intro_bis {
-width:1000px;
-position:relative;
-float:left;
-text-align:center;
-color:#636363;
+    width:1000px;
+    position:relative;
+    float:left;
+    text-align:center;
+    color:#636363;
 }
 #text_top {
-padding-top:15px;
-padding-left:15px;
-color:#708090;
-width:170px;
-text-align:center;
+    padding-top:15px;
+    padding-left:15px;
+    color:#708090;
+    width:170px;
+    text-align:center;
 }
 #footer {
-position:relative;
-float:left;
-height:20px;
+    position:relative;
+    float:left;
+    height:20px;
 }
 
 .highslide-caption {
-	display: none;
-	border-top: none;
-	font-size: 10pt;
-	padding: 5px;
-  color: #000000;
-	background: #ffffff;
-  border: 0px solid #ffffff;
+    display: none;
+    border-top: none;
+    font-size: 10pt;
+    padding: 5px;
+    color: #000000;
+    background: #ffffff;
+    border: 0px solid #ffffff;
 }
 
 code,
 pre {
-  padding: 0 3px 2px;
-  color: #333333;
-  -webkit-border-radius: 3px;
-     -moz-border-radius: 3px;
-          border-radius: 3px;
+    padding: 0 3px 2px;
+    color: #333333;
+    -webkit-border-radius: 3px;
+    -moz-border-radius: 3px;
+    border-radius: 3px;
 }
 
 code {
-  padding: 2px 4px;
-  color: #d14;
-  white-space: nowrap;
-  background-color: #f7f7f9;
-  border: 1px solid #e1e1e8;
+    padding: 2px 4px;
+    color: #d14;
+    white-space: nowrap;
+    background-color: #f7f7f9;
+    border: 1px solid #e1e1e8;
 }
diff --git a/plugins/chlpca.h b/plugins/chlpca.h
index f8531f0..b85db5c 100644
--- a/plugins/chlpca.h
+++ b/plugins/chlpca.h
@@ -164,8 +164,8 @@ return (*this);
 //! CHLPCA denoising from the PhD thesis of Hu Haijuan
 /**
    \param px the patch half width
-   \param px the patch half height
-   \param px the patch half depth
+   \param py the patch half height
+   \param pz the patch half depth
    \param wx the training region half width
    \param wy the training region half height
    \param wz the training region half depth
diff --git a/plugins/tiff_stream.h b/plugins/tiff_stream.h
index b4d934b..d7ab07c 100644
--- a/plugins/tiff_stream.h
+++ b/plugins/tiff_stream.h
@@ -102,7 +102,7 @@ const CImg<T>& save_tiff(std::ostream *tiffOutStream, const unsigned int compres
   TIFF *tif = TIFFStreamOpen("MemTiff", tiffOutStream);
   if (tif)
     {
-      cimg_forZ(*this,z) get_slice(z)._save_tiff(tif,z,compression_type,0,0);
+      cimg_forZ(*this,z) get_slice(z)._save_tiff(tif,z,z,compression_type,0,0);
       tiffOutStream->flush();
       TIFFClose(tif);
     }
diff --git a/resources/cimg_buildpackage b/resources/cimg_buildpackage
index fe0c0b4..0331d9b 100755
--- a/resources/cimg_buildpackage
+++ b/resources/cimg_buildpackage
@@ -130,8 +130,14 @@ rm -rf ../latex
 # Commit changes on GIT repository
 echo " - Commit on GIT repository."
 cd $SRC_DIR
-git commit -m "Auto-commit for release "${RELEASE}${SUFFIX} >>$LOG_FILE 2>&1
-git push
+if [ "$1" == "final" ]; then
+    git tag -d v.$RELEASE1$RELEASE2$RELEASE3
+    git tag v.$RELEASE1$RELEASE2$RELEASE3
+    git commit -m "Final release "${RELEASE} >>$LOG_FILE 2>&1
+else
+    git commit -m "Auto-commit for release "${RELEASE}${SUFFIX} >>$LOG_FILE 2>&1
+fi
+git push --tags
 
 # Create ZIP archive
 echo " - Build ZIP archive file '$ZIP_FILE'."
diff --git a/resources/compile_win_visualcpp.bat b/resources/compile_win_visualcpp.bat
index 722c754..8e7b46a 100644
--- a/resources/compile_win_visualcpp.bat
+++ b/resources/compile_win_visualcpp.bat
@@ -10,6 +10,6 @@ REM ----------------------------------------------------------------
 CD ..\examples\
 SET CPPFILE=CImg_demo captcha curve_editor2d dtmri_view3d edge_explorer2d fade_images gaussian_fit1d generate_loop_macros hough_transform2d image2ascii image_registration2d image_surface3d jawbreaker mcf_levelsets2d mcf_levelsets3d odykill pde_heatflow2d pde_TschumperleDeriche2d plotter1d radon_transform2d scene3d spherical_function3d tetris tron tutorial wavelet_atrous use_chlpca use_draw_gradient use_nlmeans use_patchmatch use_RGBclass use_skeleton
 FOR %%F IN (%CPPFILE%) DO (
-  cl /W4 /Ox /Ob2 /Oi /Ot /c /EHsc /I"%SDKPATH%\Include" /I"..\\" %%F.cpp
+  cl /W4 /wd"4127" /wd"4311" /wd"4312" /wd"4512" /wd"4571" /wd"4640" /wd"4706" /wd"4710" /wd"4800" /wd"4804" /wd"4820" /wd"4996" /Ox /Ob2 /Oi /Ot /c /EHsc /D "_CRT_SECURE_NO_WARNINGS" /I"%SDKPATH%\Include" /I"..\\" %%F.cpp
   link /LIBPATH:"%SDKPATH%\Lib" %%F.obj user32.lib gdi32.lib shell32.lib
 )

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/cimg.git



More information about the debian-science-commits mailing list