#ifndef IMDI_UTL_H #define IMDI_UTL_H /* Integer Multi-Dimensional Interpolation */ /* * Copyright 2000 - 2007 Graeme W. Gill * All rights reserved. * * This material is licenced under the GNU AFFERO GENERAL PUBLIC LICENSE Version 3 :- * see the License.txt file for licencing details. */ #include /* Common utility definitions used at both generation and runtime. */ #define IXDI 10 /* maximum input channels/dimensions allowed */ #define IXDO 10 /* maximum output channels/dimensions allowed */ #if IXDI > IXDO /* Maximum of either DI or DO */ # define IXDIDO IXDI #else # define IXDIDO IXDO #endif #define ALLOW64 /* Allow declarations but not use of 64 bit types */ #ifndef FORCE64 # undef FORCE64 /* Use 64 bit, even on architectures where it's */ /* not a native size. ALLOW64 must be defined */ #endif /* ------------------------------------------------------ */ #if defined(ALLOW64) && (ULONG_MAX == 0xffffffffffffffffUL || defined(FORCE64)) #ifndef USE64 #pragma message("Using 64 bit integer color kernel") #endif /* USE64 */ #define USE64 /* Use 64 bits if it's natural or forced */ #endif /* ------------------------------------------------------- */ /* Macros combination counter */ /* Declare the counter name nn, combinations out of total */ /* Maximum combinations is DI+2 */ #define COMBO(nn, comb, total) \ int nn[IXDI+2]; /* counter value */ \ int nn##_cmb = (comb); /* number of combinations*/ \ int nn##_tot = (total); /* out of total possible */ \ int nn##_e /* dimension index */ /* Set total to new setting */ #define CB_SETT(nn, total) \ nn##_tot = (total) /* total possible */ /* Set combinations to new setting */ #define CB_SETC(nn, comb) \ nn##_cmb = (comb) /* number of combinations*/ /* Set the counter to its initial value */ #define CB_INIT(nn) \ { \ for (nn##_e = 0; nn##_e < nn##_cmb; nn##_e++) \ nn[nn##_e] = nn##_cmb-nn##_e-1; \ nn##_e = 0; \ } /* Increment the counter value */ #define CB_INC(nn) \ { \ for (nn##_e = 0; nn##_e < nn##_cmb; nn##_e++) { \ nn[nn##_e]++; \ if (nn[nn##_e] < (nn##_tot-nn##_e)) { \ int nn##_ee; /* No carry */ \ for (nn##_ee = nn##_e-1; nn##_ee >= 0; nn##_ee--) \ nn[nn##_ee] = nn[nn##_ee+1] + 1; \ break; \ } \ } \ } /* After increment, expression is TRUE if counter is done */ #define CB_DONE(nn) \ (nn##_e >= nn##_cmb) /* ------------------------------------------------------- */ /* Macros simplex combination counter. */ /* Based on COMBO, but skips invalid simplex combinations */ #define XCOMBO(nn, comb, total) \ COMBO(nn, comb, total) /* Set total to new setting */ #define XCB_SETT(nn, total) \ CB_SETT(nn, total) /* Set combinations to new setting */ #define XCB_SETC(nn, comb) \ CB_SETC(nn, comb) /* Set the counter to its initial value */ #define XCB_INIT(nn) \ { \ int nn##_ii; \ \ for (nn##_e = 0; nn##_e < nn##_cmb; nn##_e++) \ nn[nn##_e] = nn##_cmb-nn##_e-1; \ for (nn##_ii = 1; nn##_ii < nn##_cmb; nn##_ii++) { \ if ((nn[nn##_ii-1] ^ nn[nn##_ii]) & nn[nn##_ii])\ break; /* Went from 0 to 1 */ \ } \ if (nn##_ii < nn##_cmb) { /* Fix invalid combination */ \ XCB_INC(nn); \ } \ nn##_e = 0; \ } /* Increment the counter value */ #define XCB_INC(nn) \ { \ int nn##_ii = 0; \ \ while (nn##_ii < nn##_cmb) { \ for (nn##_e = 0; nn##_e < nn##_cmb; nn##_e++) { \ nn[nn##_e]++; \ if (nn[nn##_e] < (nn##_tot-nn##_e)) { \ int nn##_ee; /* No carry */ \ for (nn##_ee = nn##_e-1; nn##_ee >= 0; nn##_ee--) \ nn[nn##_ee] = nn[nn##_ee+1] + 1; \ break; \ } \ } \ if (nn##_e >= nn##_cmb) \ break; /* Done */ \ \ /* Reject invalid combinations */ \ for (nn##_ii = 1; nn##_ii < nn##_cmb; nn##_ii++) { \ if ((nn[nn##_ii-1] ^ nn[nn##_ii]) & nn[nn##_ii]) \ break; /* Went from 0 to 1 */ \ } \ } \ } /* After increment, expression is TRUE if counter is done */ #define XCB_DONE(nn) \ CB_DONE(nn) /* ------------------------------------------------------- */ /* Macro pseudo-hilbert counter */ /* This multi-dimensional count sequence is a distributed */ /* Gray code sequence, with direction reversal on every */ /* alternate power of 2 scale. */ /* It is intended to aid cache coherence in multi-dimensional */ /* regular sampling. It approximates the Hilbert curve sequence. */ #define PHILBERT(nn) \ int nn[IXDIDO];/* counter value */ \ int nn##di; /* Dimensionality */ \ unsigned nn##res; /* Resolution per coordinate */ \ unsigned nn##bits; /* Bits per coordinate */ \ unsigned nn##ix; /* Current binary index */ \ unsigned nn##tmask; /* Total 2^n count mask */ \ unsigned nn##count; /* Usable count */ /* Init counter for dimenion di, resolution res */ #define PH_INIT(nn, pdi, pres) \ { \ int nn##e; \ \ nn##di = pdi; \ nn##res = (unsigned)pres; \ \ /* Compute bits */ \ for (nn##bits = 0; (1u << nn##bits) < nn##res; nn##bits++) \ ; \ \ /* Compute the total count mask */ \ nn##tmask = ((1u << (nn##bits * nn##di))-1); \ \ /* Compute usable count */ \ nn##count = 1; \ for (nn##e = 0; nn##e < nn##di; nn##e++) \ nn##count *= nn##res; \ \ nn##ix = 0; \ for (nn##e = 0; nn##e < nn##di; nn##e++) \ nn[nn##e] = 0; \ } /* Increment the counter value */ #define PH_INC(nn) \ { \ int nn##e; \ do { \ unsigned int nn##b; \ int nn##gix; /* Gray code index */ \ \ nn##ix = (nn##ix + 1) & nn##tmask; \ \ /* Convert to gray code index */ \ nn##gix = nn##ix ^ (nn##ix >> 1); \ \ for (nn##e = 0; nn##e < nn##di; nn##e++) \ nn[nn##e] = 0; \ \ /* Distribute bits */ \ for (nn##b = 0; nn##b < nn##bits; nn##b++) { \ if (nn##b & 1) { /* In reverse order */ \ for (nn##e = nn##di-1; nn##e >= 0; nn##e--) { \ nn[nn##e] |= (nn##gix & 1) << nn##b; \ nn##gix >>= 1; \ } \ } else { /* In normal order */ \ for (nn##e = 0; nn##e < nn##di; nn##e++) { \ nn[nn##e] |= (nn##gix & 1) << nn##b; \ nn##gix >>= 1; \ } \ } \ } \ \ /* Convert from Gray to binary coordinates */ \ for (nn##e = 0; nn##e < nn##di; nn##e++) { \ unsigned nn##sh, nn##tv; \ \ for(nn##sh = 1, nn##tv = nn[nn##e];; nn##sh <<= 1) { \ unsigned nn##ptv = nn##tv; \ nn##tv ^= (nn##tv >> nn##sh); \ if (nn##ptv <= 1 || nn##sh == 16) \ break; \ } \ /* Filter - increment again if outside cube range */ \ if (nn##tv >= nn##res) \ break; \ nn[nn##e] = nn##tv; \ } \ \ } while (nn##e < nn##di); \ \ } /* After increment, expression is TRUE if counter has looped back to start. */ #define PH_LOOPED(nn) \ (nn##ix == 0) \ /* ------------------------------------------------------- */ #endif /* IMDI_UTL_H */