[poppler] Branch 'xpdf303merge' - poppler/Function.cc poppler/Function.h
Carlos Garcia Campos
carlosgc at kemper.freedesktop.org
Mon Sep 5 11:50:28 PDT 2011
poppler/Function.cc | 87 +++++++++++++++++++++++++++++++++++++++++++---------
poppler/Function.h | 4 +-
2 files changed, 75 insertions(+), 16 deletions(-)
New commits:
commit e5661e1a08c38d4c8d69976a8c1c02c1102bc88c
Author: Carlos Garcia Campos <carlosgc at gnome.org>
Date: Mon Sep 5 20:49:13 2011 +0200
Optimize SampledFunction
Pull index computation code out of the transform function; cache the
last transform.
diff --git a/poppler/Function.cc b/poppler/Function.cc
index d43105b..7d068d3 100644
--- a/poppler/Function.cc
+++ b/poppler/Function.cc
@@ -218,8 +218,10 @@ SampledFunction::SampledFunction(Object *funcObj, Dict *dict) {
Guint buf, bitMask;
int bits;
Guint s;
- int i;
+ double in[funcMaxInputs];
+ int i, j, t, bit, idx;
+ idxOffset = NULL;
samples = NULL;
sBuf = NULL;
ok = gFalse;
@@ -261,12 +263,30 @@ SampledFunction::SampledFunction(Object *funcObj, Dict *dict) {
goto err3;
}
sampleSize[i] = obj2.getInt();
+ if (sampleSize[i] <= 0) {
+ error(errSyntaxError, -1, "Illegal non-positive value in function size array");
+ goto err3;
+ }
obj2.free();
}
obj1.free();
- idxMul[0] = n;
- for (i = 1; i < m; ++i) {
- idxMul[i] = idxMul[i-1] * sampleSize[i-1];
+ idxOffset = (int *)gmallocn(1 << m, sizeof(int));
+ for (i = 0; i < (1<<m); ++i) {
+ idx = 0;
+ for (j = m - 1, t = i; j >= 1; --j, t <<= 1) {
+ if (sampleSize[j] == 1) {
+ bit = 0;
+ } else {
+ bit = (t >> (m - 1)) & 1;
+ }
+ idx = (idx + bit) * sampleSize[j-1];
+ }
+ if (sampleSize[0] == 1) {
+ bit = 0;
+ } else {
+ bit = (t >> (m - 1)) & 1;
+ }
+ idxOffset[i] = (idx + bit) * n;
}
//----- BitsPerSample
@@ -368,6 +388,13 @@ SampledFunction::SampledFunction(Object *funcObj, Dict *dict) {
}
str->close();
+ // set up the cache
+ for (i = 0; i < m; ++i) {
+ in[i] = domain[i][0];
+ cacheIn[i] = in[i] - 1;
+ }
+ transform(in, cacheOut);
+
ok = gTrue;
return;
@@ -380,6 +407,9 @@ SampledFunction::SampledFunction(Object *funcObj, Dict *dict) {
}
SampledFunction::~SampledFunction() {
+ if (idxOffset) {
+ gfree(idxOffset);
+ }
if (samples) {
gfree(samples);
}
@@ -390,6 +420,8 @@ SampledFunction::~SampledFunction() {
SampledFunction::SampledFunction(SampledFunction *func) {
memcpy(this, func, sizeof(SampledFunction));
+ idxOffset = (int *)gmallocn(1 << m, sizeof(int));
+ memcpy(idxOffset, func->idxOffset, (1 << m) * (int)sizeof(int));
samples = (double *)gmallocn(nSamples, sizeof(double));
memcpy(samples, func->samples, nSamples * sizeof(double));
sBuf = (double *)gmallocn(1 << m, sizeof(double));
@@ -397,37 +429,54 @@ SampledFunction::SampledFunction(SampledFunction *func) {
void SampledFunction::transform(double *in, double *out) {
double x;
- int e[funcMaxInputs][2];
+ int e[funcMaxInputs];
double efrac0[funcMaxInputs];
double efrac1[funcMaxInputs];
- int i, j, k, idx, t;
+ int i, j, k, idx0, t;
+
+ // check the cache
+ for (i = 0; i < m; ++i) {
+ if (in[i] != cacheIn[i]) {
+ break;
+ }
+ }
+ if (i == m) {
+ for (i = 0; i < n; ++i) {
+ out[i] = cacheOut[i];
+ }
+ return;
+ }
// map input values into sample array
for (i = 0; i < m; ++i) {
x = (in[i] - domain[i][0]) * inputMul[i] + encode[i][0];
- if (x < 0) {
+ if (x < 0 || x != x) { // x!=x is a more portable version of isnan(x)
x = 0;
} else if (x > sampleSize[i] - 1) {
x = sampleSize[i] - 1;
}
- e[i][0] = (int)x;
- if ((e[i][1] = e[i][0] + 1) >= sampleSize[i]) {
+ e[i] = (int)x;
+ if (e[i] == sampleSize[i] - 1 && sampleSize[i] > 1) {
// this happens if in[i] = domain[i][1]
- e[i][1] = e[i][0];
+ e[i] = sampleSize[i] - 2;
}
- efrac1[i] = x - e[i][0];
+ efrac1[i] = x - e[i];
efrac0[i] = 1 - efrac1[i];
}
+ // compute index for the first sample to be used
+ idx0 = 0;
+ for (k = m - 1; k >= 1; --k) {
+ idx0 = (idx0 + e[k]) * sampleSize[k-1];
+ }
+ idx0 = (idx0 + e[0]) * n;
+
// for each output, do m-linear interpolation
for (i = 0; i < n; ++i) {
// pull 2^m values out of the sample array
for (j = 0; j < (1<<m); ++j) {
- idx = i;
- for (k = 0, t = j; k < m; ++k, t >>= 1) {
- idx += idxMul[k] * (e[k][t & 1]);
- }
+ int idx = idx0 + idxOffset[j] + i;
if (likely(idx >= 0 && idx < nSamples)) {
sBuf[j] = samples[idx];
} else {
@@ -450,6 +499,14 @@ void SampledFunction::transform(double *in, double *out) {
out[i] = range[i][1];
}
}
+
+ // save current result in the cache
+ for (i = 0; i < m; ++i) {
+ cacheIn[i] = in[i];
+ }
+ for (i = 0; i < n; ++i) {
+ cacheOut[i] = out[i];
+ }
}
//------------------------------------------------------------------------
diff --git a/poppler/Function.h b/poppler/Function.h
index d6ac893..5043822 100644
--- a/poppler/Function.h
+++ b/poppler/Function.h
@@ -146,10 +146,12 @@ private:
decode[funcMaxOutputs][2];
double // input multipliers
inputMul[funcMaxInputs];
- int idxMul[funcMaxInputs]; // sample array index multipliers
+ int *idxOffset;
double *samples; // the samples
int nSamples; // size of the samples array
double *sBuf; // buffer for the transform function
+ double cacheIn[funcMaxInputs];
+ double cacheOut[funcMaxOutputs];
GBool ok;
};
More information about the poppler
mailing list