263 lines
7.5 KiB
C
263 lines
7.5 KiB
C
#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 <limits.h>
|
|
|
|
/* 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 */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|