w32tex
About: TeX Live provides a comprehensive TeX system including all the major TeX-related programs, macro packages, and fonts that are free software. Windows sources.
  Fossies Dox: w32tex-src.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

Function.cc
Go to the documentation of this file.
1 //========================================================================
2 //
3 // Function.cc
4 //
5 // Copyright 2001-2003 Glyph & Cog, LLC
6 //
7 //========================================================================
8 
9 #include <aconf.h>
10 
11 #ifdef USE_GCC_PRAGMAS
12 #pragma implementation
13 #endif
14 
15 #include <stdlib.h>
16 #include <string.h>
17 #include <ctype.h>
18 #include <math.h>
19 #include "gmem.h"
20 #include "gmempp.h"
21 #include "GList.h"
22 #include "Object.h"
23 #include "Dict.h"
24 #include "Stream.h"
25 #include "Error.h"
26 #include "Function.h"
27 
28 //------------------------------------------------------------------------
29 
30 // Max depth of nested functions. This is used to catch infinite
31 // loops in the function object structure.
32 #define recursionLimit 8
33 
34 //------------------------------------------------------------------------
35 // Function
36 //------------------------------------------------------------------------
37 
39 }
40 
42 }
43 
44 Function *Function::parse(Object *funcObj, int expectedInputs,
45  int expectedOutputs, int recursion) {
46  Function *func;
47  Dict *dict;
48  int funcType;
49  Object obj1;
50 
51  if (recursion > recursionLimit) {
52  error(errSyntaxError, -1, "Loop detected in function objects");
53  return NULL;
54  }
55 
56  if (funcObj->isStream()) {
57  dict = funcObj->streamGetDict();
58  } else if (funcObj->isDict()) {
59  dict = funcObj->getDict();
60  } else if (funcObj->isName("Identity")) {
61  if (expectedInputs != expectedOutputs) {
62  error(errSyntaxError, -1, "Invalid use of identity function");
63  return NULL;
64  }
65  return new IdentityFunction(expectedInputs);
66  } else {
67  error(errSyntaxError, -1, "Expected function dictionary or stream");
68  return NULL;
69  }
70 
71  if (!dict->lookup("FunctionType", &obj1)->isInt()) {
72  error(errSyntaxError, -1, "Function type is missing or wrong type");
73  obj1.free();
74  return NULL;
75  }
76  funcType = obj1.getInt();
77  obj1.free();
78 
79  if (funcType == 0) {
80  func = new SampledFunction(funcObj, dict);
81  } else if (funcType == 2) {
82  func = new ExponentialFunction(funcObj, dict);
83  } else if (funcType == 3) {
84  func = new StitchingFunction(funcObj, dict, expectedInputs,
85  expectedOutputs, recursion);
86  } else if (funcType == 4) {
87  func = new PostScriptFunction(funcObj, dict);
88  } else {
89  error(errSyntaxError, -1, "Unimplemented function type ({0:d})", funcType);
90  return NULL;
91  }
92  if (!func->isOk()) {
93  delete func;
94  return NULL;
95  }
96 
97  if (func->getInputSize() != expectedInputs ||
98  (expectedOutputs >= 0 && func->getOutputSize() != expectedOutputs)) {
100  "Incorrect number of function inputs or outputs");
101  delete func;
102  return NULL;
103  }
104 
105  return func;
106 }
107 
109  Object obj1, obj2;
110  int i;
111 
112  //----- Domain
113  if (!dict->lookup("Domain", &obj1)->isArray()) {
114  error(errSyntaxError, -1, "Function is missing domain");
115  goto err2;
116  }
117  m = obj1.arrayGetLength() / 2;
118  if (m > funcMaxInputs) {
119  error(errSyntaxError, -1,
120  "Functions with more than {0:d} inputs are unsupported",
121  funcMaxInputs);
122  goto err2;
123  }
124  for (i = 0; i < m; ++i) {
125  obj1.arrayGet(2*i, &obj2);
126  if (!obj2.isNum()) {
127  error(errSyntaxError, -1, "Illegal value in function domain array");
128  goto err1;
129  }
130  domain[i][0] = obj2.getNum();
131  obj2.free();
132  obj1.arrayGet(2*i+1, &obj2);
133  if (!obj2.isNum()) {
134  error(errSyntaxError, -1, "Illegal value in function domain array");
135  goto err1;
136  }
137  domain[i][1] = obj2.getNum();
138  obj2.free();
139  }
140  obj1.free();
141 
142  //----- Range
143  hasRange = gFalse;
144  n = 0;
145  if (dict->lookup("Range", &obj1)->isArray()) {
146  hasRange = gTrue;
147  n = obj1.arrayGetLength() / 2;
148  if (n > funcMaxOutputs) {
149  error(errSyntaxError, -1,
150  "Functions with more than {0:d} outputs are unsupported",
152  goto err2;
153  }
154  for (i = 0; i < n; ++i) {
155  obj1.arrayGet(2*i, &obj2);
156  if (!obj2.isNum()) {
157  error(errSyntaxError, -1, "Illegal value in function range array");
158  goto err1;
159  }
160  range[i][0] = obj2.getNum();
161  obj2.free();
162  obj1.arrayGet(2*i+1, &obj2);
163  if (!obj2.isNum()) {
164  error(errSyntaxError, -1, "Illegal value in function range array");
165  goto err1;
166  }
167  range[i][1] = obj2.getNum();
168  obj2.free();
169  }
170  }
171  obj1.free();
172 
173  return gTrue;
174 
175  err1:
176  obj2.free();
177  err2:
178  obj1.free();
179  return gFalse;
180 }
181 
182 //------------------------------------------------------------------------
183 // IdentityFunction
184 //------------------------------------------------------------------------
185 
187  int i;
188 
189  m = n = nInputs;
190  // domain info shouldn't be used anywhere
191  for (i = 0; i < nInputs; ++i) {
192  domain[i][0] = 0;
193  domain[i][1] = 1;
194  }
195  hasRange = gFalse;
196 }
197 
199 }
200 
201 void IdentityFunction::transform(double *in, double *out) {
202  int i;
203 
204  for (i = 0; i < m; ++i) {
205  out[i] = in[i];
206  }
207 }
208 
209 //------------------------------------------------------------------------
210 // SampledFunction
211 //------------------------------------------------------------------------
212 
214  Stream *str;
215  int sampleBits;
216  double sampleMul;
217  Object obj1, obj2;
218  Guint buf, bitMask;
219  int bits;
220  Guint s;
221  double in[funcMaxInputs];
222  int i, j, t, bit, idx;
223 
224  idxOffset = NULL;
225  samples = NULL;
226  sBuf = NULL;
227  ok = gFalse;
228 
229  //----- initialize the generic stuff
230  if (!init(dict)) {
231  goto err1;
232  }
233  if (!hasRange) {
234  error(errSyntaxError, -1, "Type 0 function is missing range");
235  goto err1;
236  }
237  if (m > sampledFuncMaxInputs) {
238  error(errSyntaxError, -1,
239  "Sampled functions with more than {0:d} inputs are unsupported",
241  goto err1;
242  }
243 
244  //----- buffer
245  sBuf = (double *)gmallocn(1 << m, sizeof(double));
246 
247  //----- get the stream
248  if (!funcObj->isStream()) {
249  error(errSyntaxError, -1, "Type 0 function isn't a stream");
250  goto err1;
251  }
252  str = funcObj->getStream();
253 
254  //----- Size
255  if (!dict->lookup("Size", &obj1)->isArray() ||
256  obj1.arrayGetLength() != m) {
257  error(errSyntaxError, -1, "Function has missing or invalid size array");
258  goto err2;
259  }
260  for (i = 0; i < m; ++i) {
261  obj1.arrayGet(i, &obj2);
262  if (!obj2.isInt()) {
263  error(errSyntaxError, -1, "Illegal value in function size array");
264  goto err3;
265  }
266  sampleSize[i] = obj2.getInt();
267  if (sampleSize[i] <= 0) {
268  error(errSyntaxError, -1, "Illegal non-positive value in function size array");
269  goto err3;
270  }
271  obj2.free();
272  }
273  obj1.free();
274  idxOffset = (int *)gmallocn(1 << m, sizeof(int));
275  for (i = 0; i < (1<<m); ++i) {
276  idx = 0;
277  for (j = m - 1, t = i; j >= 1; --j, t <<= 1) {
278  if (sampleSize[j] == 1) {
279  bit = 0;
280  } else {
281  bit = (t >> (m - 1)) & 1;
282  }
283  idx = (idx + bit) * sampleSize[j-1];
284  }
285  if (sampleSize[0] == 1) {
286  bit = 0;
287  } else {
288  bit = (t >> (m - 1)) & 1;
289  }
290  idxOffset[i] = (idx + bit) * n;
291  }
292 
293  //----- BitsPerSample
294  if (!dict->lookup("BitsPerSample", &obj1)->isInt()) {
295  error(errSyntaxError, -1, "Function has missing or invalid BitsPerSample");
296  goto err2;
297  }
298  sampleBits = obj1.getInt();
299  sampleMul = 1.0 / (pow(2.0, (double)sampleBits) - 1);
300  obj1.free();
301 
302  //----- Encode
303  if (dict->lookup("Encode", &obj1)->isArray() &&
304  obj1.arrayGetLength() == 2*m) {
305  for (i = 0; i < m; ++i) {
306  obj1.arrayGet(2*i, &obj2);
307  if (!obj2.isNum()) {
308  error(errSyntaxError, -1, "Illegal value in function encode array");
309  goto err3;
310  }
311  encode[i][0] = obj2.getNum();
312  obj2.free();
313  obj1.arrayGet(2*i+1, &obj2);
314  if (!obj2.isNum()) {
315  error(errSyntaxError, -1, "Illegal value in function encode array");
316  goto err3;
317  }
318  encode[i][1] = obj2.getNum();
319  obj2.free();
320  }
321  } else {
322  for (i = 0; i < m; ++i) {
323  encode[i][0] = 0;
324  encode[i][1] = sampleSize[i] - 1;
325  }
326  }
327  obj1.free();
328  for (i = 0; i < m; ++i) {
329  inputMul[i] = (encode[i][1] - encode[i][0]) /
330  (domain[i][1] - domain[i][0]);
331  }
332 
333  //----- Decode
334  if (dict->lookup("Decode", &obj1)->isArray() &&
335  obj1.arrayGetLength() == 2*n) {
336  for (i = 0; i < n; ++i) {
337  obj1.arrayGet(2*i, &obj2);
338  if (!obj2.isNum()) {
339  error(errSyntaxError, -1, "Illegal value in function decode array");
340  goto err3;
341  }
342  decode[i][0] = obj2.getNum();
343  obj2.free();
344  obj1.arrayGet(2*i+1, &obj2);
345  if (!obj2.isNum()) {
346  error(errSyntaxError, -1, "Illegal value in function decode array");
347  goto err3;
348  }
349  decode[i][1] = obj2.getNum();
350  obj2.free();
351  }
352  } else {
353  for (i = 0; i < n; ++i) {
354  decode[i][0] = range[i][0];
355  decode[i][1] = range[i][1];
356  }
357  }
358  obj1.free();
359 
360  //----- samples
361  nSamples = n;
362  for (i = 0; i < m; ++i) {
363  if (nSamples > INT_MAX / sampleSize[i]) {
364  error(errSyntaxError, -1, "Integer overflow in sampled function setup");
365  goto err1;
366  }
367  nSamples *= sampleSize[i];
368  }
369  samples = (double *)gmallocn(nSamples, sizeof(double));
370  buf = 0;
371  bits = 0;
372  bitMask = (sampleBits < 32) ? ((1 << sampleBits) - 1) : 0xffffffffU;
373  str->reset();
374  for (i = 0; i < nSamples; ++i) {
375  if (sampleBits == 8) {
376  s = str->getChar();
377  } else if (sampleBits == 16) {
378  s = str->getChar();
379  s = (s << 8) + str->getChar();
380  } else if (sampleBits == 32) {
381  s = str->getChar();
382  s = (s << 8) + str->getChar();
383  s = (s << 8) + str->getChar();
384  s = (s << 8) + str->getChar();
385  } else {
386  while (bits < sampleBits) {
387  buf = (buf << 8) | (str->getChar() & 0xff);
388  bits += 8;
389  }
390  s = (buf >> (bits - sampleBits)) & bitMask;
391  bits -= sampleBits;
392  }
393  samples[i] = (double)s * sampleMul;
394  }
395  str->close();
396 
397  // set up the cache
398  for (i = 0; i < m; ++i) {
399  in[i] = domain[i][0];
400  cacheIn[i] = in[i] - 1;
401  }
403 
404  ok = gTrue;
405  return;
406 
407  err3:
408  obj2.free();
409  err2:
410  obj1.free();
411  err1:
412  return;
413 }
414 
416  if (idxOffset) {
417  gfree(idxOffset);
418  }
419  if (samples) {
420  gfree(samples);
421  }
422  if (sBuf) {
423  gfree(sBuf);
424  }
425 }
426 
428  memcpy((void *)this, (void *)func, sizeof(SampledFunction));
429  idxOffset = (int *)gmallocn(1 << m, sizeof(int));
430  memcpy(idxOffset, func->idxOffset, (1 << m) * (int)sizeof(int));
431  samples = (double *)gmallocn(nSamples, sizeof(double));
432  memcpy(samples, func->samples, nSamples * sizeof(double));
433  sBuf = (double *)gmallocn(1 << m, sizeof(double));
434 }
435 
436 void SampledFunction::transform(double *in, double *out) {
437  double x;
438  int e[funcMaxInputs];
439  double efrac0[funcMaxInputs];
440  double efrac1[funcMaxInputs];
441  int i, j, k, idx0, t;
442 
443  // check the cache
444  for (i = 0; i < m; ++i) {
445  if (in[i] != cacheIn[i]) {
446  break;
447  }
448  }
449  if (i == m) {
450  for (i = 0; i < n; ++i) {
451  out[i] = cacheOut[i];
452  }
453  return;
454  }
455 
456  // map input values into sample array
457  for (i = 0; i < m; ++i) {
458  x = (in[i] - domain[i][0]) * inputMul[i] + encode[i][0];
459  if (x < 0 || x != x) { // x!=x is a more portable version of isnan(x)
460  x = 0;
461  } else if (x > sampleSize[i] - 1) {
462  x = sampleSize[i] - 1;
463  }
464  e[i] = (int)x;
465  if (e[i] == sampleSize[i] - 1 && sampleSize[i] > 1) {
466  // this happens if in[i] = domain[i][1]
467  e[i] = sampleSize[i] - 2;
468  }
469  efrac1[i] = x - e[i];
470  efrac0[i] = 1 - efrac1[i];
471  }
472 
473  // compute index for the first sample to be used
474  idx0 = 0;
475  for (k = m - 1; k >= 1; --k) {
476  idx0 = (idx0 + e[k]) * sampleSize[k-1];
477  }
478  idx0 = (idx0 + e[0]) * n;
479 
480  // for each output, do m-linear interpolation
481  for (i = 0; i < n; ++i) {
482 
483  // pull 2^m values out of the sample array
484  for (j = 0; j < (1<<m); ++j) {
485  sBuf[j] = samples[idx0 + idxOffset[j] + i];
486  }
487 
488  // do m sets of interpolations
489  for (j = 0, t = (1<<m); j < m; ++j, t >>= 1) {
490  for (k = 0; k < t; k += 2) {
491  sBuf[k >> 1] = efrac0[j] * sBuf[k] + efrac1[j] * sBuf[k+1];
492  }
493  }
494 
495  // map output value to range
496  out[i] = sBuf[0] * (decode[i][1] - decode[i][0]) + decode[i][0];
497  if (out[i] < range[i][0]) {
498  out[i] = range[i][0];
499  } else if (out[i] > range[i][1]) {
500  out[i] = range[i][1];
501  }
502  }
503 
504  // save current result in the cache
505  for (i = 0; i < m; ++i) {
506  cacheIn[i] = in[i];
507  }
508  for (i = 0; i < n; ++i) {
509  cacheOut[i] = out[i];
510  }
511 }
512 
513 //------------------------------------------------------------------------
514 // ExponentialFunction
515 //------------------------------------------------------------------------
516 
518  Object obj1, obj2;
519  int i;
520 
521  ok = gFalse;
522 
523  //----- initialize the generic stuff
524  if (!init(dict)) {
525  goto err1;
526  }
527  if (m != 1) {
528  error(errSyntaxError, -1, "Exponential function with more than one input");
529  goto err1;
530  }
531 
532  //----- C0
533  if (dict->lookup("C0", &obj1)->isArray()) {
534  if (hasRange && obj1.arrayGetLength() != n) {
535  error(errSyntaxError, -1, "Function's C0 array is wrong length");
536  goto err2;
537  }
538  n = obj1.arrayGetLength();
539  if (n > funcMaxOutputs) {
540  error(errSyntaxError, -1,
541  "Functions with more than {0:d} outputs are unsupported",
543  goto err2;
544  }
545  for (i = 0; i < n; ++i) {
546  obj1.arrayGet(i, &obj2);
547  if (!obj2.isNum()) {
548  error(errSyntaxError, -1, "Illegal value in function C0 array");
549  goto err3;
550  }
551  c0[i] = obj2.getNum();
552  obj2.free();
553  }
554  } else {
555  if (hasRange && n != 1) {
556  error(errSyntaxError, -1, "Function's C0 array is wrong length");
557  goto err2;
558  }
559  n = 1;
560  c0[0] = 0;
561  }
562  obj1.free();
563 
564  //----- C1
565  if (dict->lookup("C1", &obj1)->isArray()) {
566  if (obj1.arrayGetLength() != n) {
567  error(errSyntaxError, -1, "Function's C1 array is wrong length");
568  goto err2;
569  }
570  for (i = 0; i < n; ++i) {
571  obj1.arrayGet(i, &obj2);
572  if (!obj2.isNum()) {
573  error(errSyntaxError, -1, "Illegal value in function C1 array");
574  goto err3;
575  }
576  c1[i] = obj2.getNum();
577  obj2.free();
578  }
579  } else {
580  if (n != 1) {
581  error(errSyntaxError, -1, "Function's C1 array is wrong length");
582  goto err2;
583  }
584  c1[0] = 1;
585  }
586  obj1.free();
587 
588  //----- N (exponent)
589  if (!dict->lookup("N", &obj1)->isNum()) {
590  error(errSyntaxError, -1, "Function has missing or invalid N");
591  goto err2;
592  }
593  e = obj1.getNum();
594  obj1.free();
595 
596  ok = gTrue;
597  return;
598 
599  err3:
600  obj2.free();
601  err2:
602  obj1.free();
603  err1:
604  return;
605 }
606 
608 }
609 
611  memcpy((void *)this, (void *)func, sizeof(ExponentialFunction));
612 }
613 
614 void ExponentialFunction::transform(double *in, double *out) {
615  double x;
616  int i;
617 
618  if (in[0] < domain[0][0]) {
619  x = domain[0][0];
620  } else if (in[0] > domain[0][1]) {
621  x = domain[0][1];
622  } else {
623  x = in[0];
624  }
625  for (i = 0; i < n; ++i) {
626  out[i] = c0[i] + pow(x, e) * (c1[i] - c0[i]);
627  if (hasRange) {
628  if (out[i] < range[i][0]) {
629  out[i] = range[i][0];
630  } else if (out[i] > range[i][1]) {
631  out[i] = range[i][1];
632  }
633  }
634  }
635  return;
636 }
637 
638 //------------------------------------------------------------------------
639 // StitchingFunction
640 //------------------------------------------------------------------------
641 
643  int expectedInputs, int expectedOutputs,
644  int recursion) {
645  Object obj1, obj2;
646  int i;
647 
648  ok = gFalse;
649  funcs = NULL;
650  bounds = NULL;
651  encode = NULL;
652  scale = NULL;
653 
654  //----- initialize the generic stuff
655  if (!init(dict)) {
656  goto err1;
657  }
658  if (m != 1) {
659  error(errSyntaxError, -1, "Stitching function with more than one input");
660  goto err1;
661  }
662 
663  //----- Functions
664  if (!dict->lookup("Functions", &obj1)->isArray() ||
665  obj1.arrayGetLength() < 1) {
666  error(errSyntaxError, -1,
667  "Missing 'Functions' entry in stitching function");
668  goto err1;
669  }
670  k = obj1.arrayGetLength();
671  funcs = (Function **)gmallocn(k, sizeof(Function *));
672  bounds = (double *)gmallocn(k + 1, sizeof(double));
673  encode = (double *)gmallocn(2 * k, sizeof(double));
674  scale = (double *)gmallocn(k, sizeof(double));
675  for (i = 0; i < k; ++i) {
676  funcs[i] = NULL;
677  }
678  for (i = 0; i < k; ++i) {
679  if (!(funcs[i] = Function::parse(obj1.arrayGet(i, &obj2),
680  expectedInputs, expectedOutputs,
681  recursion + 1))) {
682  goto err2;
683  }
684  if (i == 0) {
685  n = funcs[0]->getOutputSize();
686  }
687  if (funcs[i]->getInputSize() != 1 || funcs[i]->getOutputSize() != n) {
688  error(errSyntaxError, -1,
689  "Incompatible subfunctions in stitching function");
690  goto err2;
691  }
692  obj2.free();
693  }
694  obj1.free();
695 
696  //----- Bounds
697  if (!dict->lookup("Bounds", &obj1)->isArray() ||
698  obj1.arrayGetLength() != k - 1) {
699  error(errSyntaxError, -1,
700  "Missing or invalid 'Bounds' entry in stitching function");
701  goto err1;
702  }
703  bounds[0] = domain[0][0];
704  for (i = 1; i < k; ++i) {
705  if (!obj1.arrayGet(i - 1, &obj2)->isNum()) {
706  error(errSyntaxError, -1,
707  "Invalid type in 'Bounds' array in stitching function");
708  goto err2;
709  }
710  bounds[i] = obj2.getNum();
711  obj2.free();
712  }
713  bounds[k] = domain[0][1];
714  obj1.free();
715 
716  //----- Encode
717  if (!dict->lookup("Encode", &obj1)->isArray() ||
718  obj1.arrayGetLength() != 2 * k) {
719  error(errSyntaxError, -1,
720  "Missing or invalid 'Encode' entry in stitching function");
721  goto err1;
722  }
723  for (i = 0; i < 2 * k; ++i) {
724  if (!obj1.arrayGet(i, &obj2)->isNum()) {
725  error(errSyntaxError, -1,
726  "Invalid type in 'Encode' array in stitching function");
727  goto err2;
728  }
729  encode[i] = obj2.getNum();
730  obj2.free();
731  }
732  obj1.free();
733 
734  //----- pre-compute the scale factors
735  for (i = 0; i < k; ++i) {
736  if (bounds[i] == bounds[i+1]) {
737  // avoid a divide-by-zero -- in this situation, function i will
738  // never be used anyway
739  scale[i] = 0;
740  } else {
741  scale[i] = (encode[2*i+1] - encode[2*i]) / (bounds[i+1] - bounds[i]);
742  }
743  }
744 
745  ok = gTrue;
746  return;
747 
748  err2:
749  obj2.free();
750  err1:
751  obj1.free();
752 }
753 
755  int i;
756 
757  memcpy((void *)this, (void *)func, sizeof(StitchingFunction));
758  funcs = (Function **)gmallocn(k, sizeof(Function *));
759  for (i = 0; i < k; ++i) {
760  funcs[i] = func->funcs[i]->copy();
761  }
762  bounds = (double *)gmallocn(k + 1, sizeof(double));
763  memcpy(bounds, func->bounds, (k + 1) * sizeof(double));
764  encode = (double *)gmallocn(2 * k, sizeof(double));
765  memcpy(encode, func->encode, 2 * k * sizeof(double));
766  scale = (double *)gmallocn(k, sizeof(double));
767  memcpy(scale, func->scale, k * sizeof(double));
768  ok = gTrue;
769 }
770 
772  int i;
773 
774  if (funcs) {
775  for (i = 0; i < k; ++i) {
776  if (funcs[i]) {
777  delete funcs[i];
778  }
779  }
780  }
781  gfree(funcs);
782  gfree(bounds);
783  gfree(encode);
784  gfree(scale);
785 }
786 
787 void StitchingFunction::transform(double *in, double *out) {
788  double x;
789  int i;
790 
791  if (in[0] < domain[0][0]) {
792  x = domain[0][0];
793  } else if (in[0] > domain[0][1]) {
794  x = domain[0][1];
795  } else {
796  x = in[0];
797  }
798  for (i = 0; i < k - 1; ++i) {
799  if (x < bounds[i+1]) {
800  break;
801  }
802  }
803  x = encode[2*i] + (x - bounds[i]) * scale[i];
804  funcs[i]->transform(&x, out);
805 }
806 
807 //------------------------------------------------------------------------
808 // PostScriptFunction
809 //------------------------------------------------------------------------
810 
811 // This is not an enum, because we can't foreward-declare the enum
812 // type in Function.h
813 //
814 // NB: This must be kept in sync with psOpNames[] below.
815 #define psOpAbs 0
816 #define psOpAdd 1
817 #define psOpAnd 2
818 #define psOpAtan 3
819 #define psOpBitshift 4
820 #define psOpCeiling 5
821 #define psOpCopy 6
822 #define psOpCos 7
823 #define psOpCvi 8
824 #define psOpCvr 9
825 #define psOpDiv 10
826 #define psOpDup 11
827 #define psOpEq 12
828 #define psOpExch 13
829 #define psOpExp 14
830 #define psOpFalse 15
831 #define psOpFloor 16
832 #define psOpGe 17
833 #define psOpGt 18
834 #define psOpIdiv 19
835 #define psOpIndex 20
836 #define psOpLe 21
837 #define psOpLn 22
838 #define psOpLog 23
839 #define psOpLt 24
840 #define psOpMod 25
841 #define psOpMul 26
842 #define psOpNe 27
843 #define psOpNeg 28
844 #define psOpNot 29
845 #define psOpOr 30
846 #define psOpPop 31
847 #define psOpRoll 32
848 #define psOpRound 33
849 #define psOpSin 34
850 #define psOpSqrt 35
851 #define psOpSub 36
852 #define psOpTrue 37
853 #define psOpTruncate 38
854 #define psOpXor 39
855 // the push/j/jz ops are used internally (and are not listed in psOpNames[])
856 #define psOpPush 40
857 #define psOpJ 41
858 #define psOpJz 42
859 
860 #define nPSOps (sizeof(psOpNames) / sizeof(const char *))
861 
862 // Note: 'if' and 'ifelse' are parsed separately.
863 // The rest are listed here in alphabetical order.
864 //
865 // NB: This must be kept in sync with the psOpXXX defines above.
866 static const char *psOpNames[] = {
867  "abs",
868  "add",
869  "and",
870  "atan",
871  "bitshift",
872  "ceiling",
873  "copy",
874  "cos",
875  "cvi",
876  "cvr",
877  "div",
878  "dup",
879  "eq",
880  "exch",
881  "exp",
882  "false",
883  "floor",
884  "ge",
885  "gt",
886  "idiv",
887  "index",
888  "le",
889  "ln",
890  "log",
891  "lt",
892  "mod",
893  "mul",
894  "ne",
895  "neg",
896  "not",
897  "or",
898  "pop",
899  "roll",
900  "round",
901  "sin",
902  "sqrt",
903  "sub",
904  "true",
905  "truncate",
906  "xor"
907 };
908 
909 struct PSCode {
910  int op;
911  union {
912  double d;
913  int i;
914  } val;
915 };
916 
917 #define psStackSize 100
918 
920  Stream *str;
921  GList *tokens;
922  GString *tok;
923  double in[funcMaxInputs];
924  int tokPtr, codePtr, i;
925 
926  codeString = NULL;
927  code = NULL;
928  codeSize = 0;
929  ok = gFalse;
930 
931  //----- initialize the generic stuff
932  if (!init(dict)) {
933  goto err1;
934  }
935  if (!hasRange) {
936  error(errSyntaxError, -1, "Type 4 function is missing range");
937  goto err1;
938  }
939 
940  //----- get the stream
941  if (!funcObj->isStream()) {
942  error(errSyntaxError, -1, "Type 4 function isn't a stream");
943  goto err1;
944  }
945  str = funcObj->getStream();
946 
947  //----- tokenize the function
948  codeString = new GString();
949  tokens = new GList();
950  str->reset();
951  while ((tok = getToken(str))) {
952  tokens->append(tok);
953  }
954  str->close();
955 
956  //----- parse the function
957  if (tokens->getLength() < 1 ||
958  ((GString *)tokens->get(0))->cmp("{")) {
959  error(errSyntaxError, -1, "Expected '{{' at start of PostScript function");
960  goto err2;
961  }
962  tokPtr = 1;
963  codePtr = 0;
964  if (!parseCode(tokens, &tokPtr, &codePtr)) {
965  goto err2;
966  }
967  codeLen = codePtr;
968 
969  //----- set up the cache
970  for (i = 0; i < m; ++i) {
971  in[i] = domain[i][0];
972  cacheIn[i] = in[i] - 1;
973  }
975 
976  ok = gTrue;
977 
978  err2:
979  deleteGList(tokens, GString);
980  err1:
981  return;
982 }
983 
985  memcpy((void *)this, (void *)func, sizeof(PostScriptFunction));
986  codeString = func->codeString->copy();
987  code = (PSCode *)gmallocn(codeSize, sizeof(PSCode));
988  memcpy(code, func->code, codeSize * sizeof(PSCode));
989 }
990 
992  gfree(code);
993  if (codeString) {
994  delete codeString;
995  }
996 }
997 
998 void PostScriptFunction::transform(double *in, double *out) {
999  double stack[psStackSize];
1000  double x;
1001  int sp, i;
1002 
1003  // check the cache
1004  for (i = 0; i < m; ++i) {
1005  if (in[i] != cacheIn[i]) {
1006  break;
1007  }
1008  }
1009  if (i == m) {
1010  for (i = 0; i < n; ++i) {
1011  out[i] = cacheOut[i];
1012  }
1013  return;
1014  }
1015 
1016  for (i = 0; i < m; ++i) {
1017  stack[psStackSize - 1 - i] = in[i];
1018  }
1019  sp = exec(stack, psStackSize - m);
1020  // if (sp < psStackSize - n) {
1021  // error(errSyntaxWarning, -1,
1022  // "Extra values on stack at end of PostScript function");
1023  // }
1024  if (sp > psStackSize - n) {
1025  error(errSyntaxError, -1, "Stack underflow in PostScript function");
1026  sp = psStackSize - n;
1027  }
1028  for (i = 0; i < n; ++i) {
1029  x = stack[sp + n - 1 - i];
1030  if (x < range[i][0]) {
1031  out[i] = range[i][0];
1032  } else if (x > range[i][1]) {
1033  out[i] = range[i][1];
1034  } else {
1035  out[i] = x;
1036  }
1037  }
1038 
1039  // save current result in the cache
1040  for (i = 0; i < m; ++i) {
1041  cacheIn[i] = in[i];
1042  }
1043  for (i = 0; i < n; ++i) {
1044  cacheOut[i] = out[i];
1045  }
1046 }
1047 
1048 GBool PostScriptFunction::parseCode(GList *tokens, int *tokPtr, int *codePtr) {
1049  GString *tok;
1050  char *p;
1051  int a, b, mid, cmp;
1052  int codePtr0, codePtr1;
1053 
1054  while (1) {
1055  if (*tokPtr >= tokens->getLength()) {
1056  error(errSyntaxError, -1,
1057  "Unexpected end of PostScript function stream");
1058  return gFalse;
1059  }
1060  tok = (GString *)tokens->get((*tokPtr)++);
1061  p = tok->getCString();
1062  if (isdigit(*p) || *p == '.' || *p == '-') {
1063  addCodeD(codePtr, psOpPush, atof(tok->getCString()));
1064  } else if (!tok->cmp("{")) {
1065  codePtr0 = *codePtr;
1066  addCodeI(codePtr, psOpJz, 0);
1067  if (!parseCode(tokens, tokPtr, codePtr)) {
1068  return gFalse;
1069  }
1070  if (*tokPtr >= tokens->getLength()) {
1071  error(errSyntaxError, -1,
1072  "Unexpected end of PostScript function stream");
1073  return gFalse;
1074  }
1075  tok = (GString *)tokens->get((*tokPtr)++);
1076  if (!tok->cmp("if")) {
1077  code[codePtr0].val.i = *codePtr;
1078  } else if (!tok->cmp("{")) {
1079  codePtr1 = *codePtr;
1080  addCodeI(codePtr, psOpJ, 0);
1081  code[codePtr0].val.i = *codePtr;
1082  if (!parseCode(tokens, tokPtr, codePtr)) {
1083  return gFalse;
1084  }
1085  if (*tokPtr >= tokens->getLength()) {
1086  error(errSyntaxError, -1,
1087  "Unexpected end of PostScript function stream");
1088  return gFalse;
1089  }
1090  tok = (GString *)tokens->get((*tokPtr)++);
1091  if (!tok->cmp("ifelse")) {
1092  code[codePtr1].val.i = *codePtr;
1093  } else {
1094  error(errSyntaxError, -1,
1095  "Expected 'ifelse' in PostScript function stream");
1096  return gFalse;
1097  }
1098  } else {
1099  error(errSyntaxError, -1,
1100  "Expected 'if' in PostScript function stream");
1101  return gFalse;
1102  }
1103  } else if (!tok->cmp("}")) {
1104  break;
1105  } else if (!tok->cmp("if")) {
1106  error(errSyntaxError, -1,
1107  "Unexpected 'if' in PostScript function stream");
1108  return gFalse;
1109  } else if (!tok->cmp("ifelse")) {
1110  error(errSyntaxError, -1,
1111  "Unexpected 'ifelse' in PostScript function stream");
1112  return gFalse;
1113  } else {
1114  a = -1;
1115  b = nPSOps;
1116  cmp = 0; // make gcc happy
1117  // invariant: psOpNames[a] < tok < psOpNames[b]
1118  while (b - a > 1) {
1119  mid = (a + b) / 2;
1120  cmp = tok->cmp(psOpNames[mid]);
1121  if (cmp > 0) {
1122  a = mid;
1123  } else if (cmp < 0) {
1124  b = mid;
1125  } else {
1126  a = b = mid;
1127  }
1128  }
1129  if (cmp != 0) {
1130  error(errSyntaxError, -1,
1131  "Unknown operator '{0:t}' in PostScript function",
1132  tok);
1133  return gFalse;
1134  }
1135  addCode(codePtr, a);
1136  }
1137  }
1138  return gTrue;
1139 }
1140 
1141 void PostScriptFunction::addCode(int *codePtr, int op) {
1142  if (*codePtr >= codeSize) {
1143  if (codeSize) {
1144  codeSize *= 2;
1145  } else {
1146  codeSize = 16;
1147  }
1148  code = (PSCode *)greallocn(code, codeSize, sizeof(PSCode));
1149  }
1150  code[*codePtr].op = op;
1151  ++(*codePtr);
1152 }
1153 
1154 void PostScriptFunction::addCodeI(int *codePtr, int op, int x) {
1155  if (*codePtr >= codeSize) {
1156  if (codeSize) {
1157  codeSize *= 2;
1158  } else {
1159  codeSize = 16;
1160  }
1161  code = (PSCode *)greallocn(code, codeSize, sizeof(PSCode));
1162  }
1163  code[*codePtr].op = op;
1164  code[*codePtr].val.i = x;
1165  ++(*codePtr);
1166 }
1167 
1168 void PostScriptFunction::addCodeD(int *codePtr, int op, double x) {
1169  if (*codePtr >= codeSize) {
1170  if (codeSize) {
1171  codeSize *= 2;
1172  } else {
1173  codeSize = 16;
1174  }
1175  code = (PSCode *)greallocn(code, codeSize, sizeof(PSCode));
1176  }
1177  code[*codePtr].op = op;
1178  code[*codePtr].val.d = x;
1179  ++(*codePtr);
1180 }
1181 
1183  GString *s;
1184  int c;
1185  GBool comment;
1186 
1187  s = new GString();
1188  comment = gFalse;
1189  while (1) {
1190  if ((c = str->getChar()) == EOF) {
1191  delete s;
1192  return NULL;
1193  }
1194  codeString->append((char)c);
1195  if (comment) {
1196  if (c == '\x0a' || c == '\x0d') {
1197  comment = gFalse;
1198  }
1199  } else if (c == '%') {
1200  comment = gTrue;
1201  } else if (!isspace(c)) {
1202  break;
1203  }
1204  }
1205  if (c == '{' || c == '}') {
1206  s->append((char)c);
1207  } else if (isdigit(c) || c == '.' || c == '-') {
1208  while (1) {
1209  s->append((char)c);
1210  c = str->lookChar();
1211  if (c == EOF || !(isdigit(c) || c == '.' || c == '-')) {
1212  break;
1213  }
1214  str->getChar();
1215  codeString->append((char)c);
1216  }
1217  } else {
1218  while (1) {
1219  s->append((char)c);
1220  c = str->lookChar();
1221  if (c == EOF || !isalnum(c)) {
1222  break;
1223  }
1224  str->getChar();
1225  codeString->append((char)c);
1226  }
1227  }
1228  return s;
1229 }
1230 
1231 int PostScriptFunction::exec(double *stack, int sp0) {
1232  PSCode *c;
1233  double tmp[psStackSize];
1234  double t;
1235  int sp, ip, nn, k, i;
1236 
1237  sp = sp0;
1238  ip = 0;
1239  while (ip < codeLen) {
1240  c = &code[ip++];
1241  switch(c->op) {
1242  case psOpAbs:
1243  if (sp >= psStackSize) {
1244  goto underflow;
1245  }
1246  stack[sp] = fabs(stack[sp]);
1247  break;
1248  case psOpAdd:
1249  if (sp + 1 >= psStackSize) {
1250  goto underflow;
1251  }
1252  stack[sp + 1] = stack[sp + 1] + stack[sp];
1253  ++sp;
1254  break;
1255  case psOpAnd:
1256  if (sp + 1 >= psStackSize) {
1257  goto underflow;
1258  }
1259  stack[sp + 1] = (int)stack[sp + 1] & (int)stack[sp];
1260  ++sp;
1261  break;
1262  case psOpAtan:
1263  if (sp + 1 >= psStackSize) {
1264  goto underflow;
1265  }
1266  stack[sp + 1] = atan2(stack[sp + 1], stack[sp]);
1267  ++sp;
1268  break;
1269  case psOpBitshift:
1270  if (sp + 1 >= psStackSize) {
1271  goto underflow;
1272  }
1273  k = (int)stack[sp + 1];
1274  nn = (int)stack[sp];
1275  if (nn > 0) {
1276  stack[sp + 1] = k << nn;
1277  } else if (nn < 0) {
1278  stack[sp + 1] = k >> -nn;
1279  } else {
1280  stack[sp + 1] = k;
1281  }
1282  ++sp;
1283  break;
1284  case psOpCeiling:
1285  if (sp >= psStackSize) {
1286  goto underflow;
1287  }
1288  stack[sp] = ceil(stack[sp]);
1289  break;
1290  case psOpCopy:
1291  if (sp >= psStackSize) {
1292  goto underflow;
1293  }
1294  nn = (int)stack[sp++];
1295  if (nn < 0) {
1296  goto invalidArg;
1297  }
1298  if (sp + nn > psStackSize) {
1299  goto underflow;
1300  }
1301  if (sp - nn < 0) {
1302  goto overflow;
1303  }
1304  for (i = 0; i < nn; ++i) {
1305  stack[sp - nn + i] = stack[sp + i];
1306  }
1307  sp -= nn;
1308  break;
1309  case psOpCos:
1310  if (sp >= psStackSize) {
1311  goto underflow;
1312  }
1313  stack[sp] = cos(stack[sp]);
1314  break;
1315  case psOpCvi:
1316  if (sp >= psStackSize) {
1317  goto underflow;
1318  }
1319  stack[sp] = (int)stack[sp];
1320  break;
1321  case psOpCvr:
1322  if (sp >= psStackSize) {
1323  goto underflow;
1324  }
1325  break;
1326  case psOpDiv:
1327  if (sp + 1 >= psStackSize) {
1328  goto underflow;
1329  }
1330  if (stack[sp] == 0) {
1331  goto invalidArg;
1332  }
1333  stack[sp + 1] = stack[sp + 1] / stack[sp];
1334  ++sp;
1335  break;
1336  case psOpDup:
1337  if (sp >= psStackSize) {
1338  goto underflow;
1339  }
1340  if (sp < 1) {
1341  goto overflow;
1342  }
1343  stack[sp - 1] = stack[sp];
1344  --sp;
1345  break;
1346  case psOpEq:
1347  if (sp + 1 >= psStackSize) {
1348  goto underflow;
1349  }
1350  stack[sp + 1] = stack[sp + 1] == stack[sp] ? 1 : 0;
1351  ++sp;
1352  break;
1353  case psOpExch:
1354  if (sp + 1 >= psStackSize) {
1355  goto underflow;
1356  }
1357  t = stack[sp];
1358  stack[sp] = stack[sp + 1];
1359  stack[sp + 1] = t;
1360  break;
1361  case psOpExp:
1362  if (sp + 1 >= psStackSize) {
1363  goto underflow;
1364  }
1365  stack[sp + 1] = pow(stack[sp + 1], stack[sp]);
1366  ++sp;
1367  break;
1368  case psOpFalse:
1369  if (sp < 1) {
1370  goto overflow;
1371  }
1372  stack[sp - 1] = 0;
1373  --sp;
1374  break;
1375  case psOpFloor:
1376  if (sp >= psStackSize) {
1377  goto underflow;
1378  }
1379  stack[sp] = floor(stack[sp]);
1380  break;
1381  case psOpGe:
1382  if (sp + 1 >= psStackSize) {
1383  goto underflow;
1384  }
1385  stack[sp + 1] = stack[sp + 1] >= stack[sp] ? 1 : 0;
1386  ++sp;
1387  break;
1388  case psOpGt:
1389  if (sp + 1 >= psStackSize) {
1390  goto underflow;
1391  }
1392  stack[sp + 1] = stack[sp + 1] > stack[sp] ? 1 : 0;
1393  ++sp;
1394  break;
1395  case psOpIdiv:
1396  if (sp + 1 >= psStackSize) {
1397  goto underflow;
1398  }
1399  k = (int)stack[sp];
1400  if (k == 0) {
1401  goto invalidArg;
1402  }
1403  stack[sp + 1] = (int)stack[sp + 1] / k;
1404  ++sp;
1405  break;
1406  case psOpIndex:
1407  if (sp >= psStackSize) {
1408  goto underflow;
1409  }
1410  k = (int)stack[sp];
1411  if (k < 0) {
1412  goto invalidArg;
1413  }
1414  if (sp + 1 + k >= psStackSize) {
1415  goto underflow;
1416  }
1417  stack[sp] = stack[sp + 1 + k];
1418  break;
1419  case psOpLe:
1420  if (sp + 1 >= psStackSize) {
1421  goto underflow;
1422  }
1423  stack[sp + 1] = stack[sp + 1] <= stack[sp] ? 1 : 0;
1424  ++sp;
1425  break;
1426  case psOpLn:
1427  if (sp >= psStackSize) {
1428  goto underflow;
1429  }
1430  stack[sp] = log(stack[sp]);
1431  break;
1432  case psOpLog:
1433  if (sp >= psStackSize) {
1434  goto underflow;
1435  }
1436  stack[sp] = log10(stack[sp]);
1437  break;
1438  case psOpLt:
1439  if (sp + 1 >= psStackSize) {
1440  goto underflow;
1441  }
1442  stack[sp + 1] = stack[sp + 1] < stack[sp] ? 1 : 0;
1443  ++sp;
1444  break;
1445  case psOpMod:
1446  if (sp + 1 >= psStackSize) {
1447  goto underflow;
1448  }
1449  k = (int)stack[sp];
1450  if (k == 0) {
1451  goto invalidArg;
1452  }
1453  stack[sp + 1] = (int)stack[sp + 1] % k;
1454  ++sp;
1455  break;
1456  case psOpMul:
1457  if (sp + 1 >= psStackSize) {
1458  goto underflow;
1459  }
1460  stack[sp + 1] = stack[sp + 1] * stack[sp];
1461  ++sp;
1462  break;
1463  case psOpNe:
1464  if (sp + 1 >= psStackSize) {
1465  goto underflow;
1466  }
1467  stack[sp + 1] = stack[sp + 1] != stack[sp] ? 1 : 0;
1468  ++sp;
1469  break;
1470  case psOpNeg:
1471  if (sp >= psStackSize) {
1472  goto underflow;
1473  }
1474  stack[sp] = -stack[sp];
1475  break;
1476  case psOpNot:
1477  if (sp >= psStackSize) {
1478  goto underflow;
1479  }
1480  stack[sp] = stack[sp] == 0 ? 1 : 0;
1481  break;
1482  case psOpOr:
1483  if (sp + 1 >= psStackSize) {
1484  goto underflow;
1485  }
1486  stack[sp + 1] = (int)stack[sp + 1] | (int)stack[sp];
1487  ++sp;
1488  break;
1489  case psOpPop:
1490  if (sp >= psStackSize) {
1491  goto underflow;
1492  }
1493  ++sp;
1494  break;
1495  case psOpRoll:
1496  if (sp + 1 >= psStackSize) {
1497  goto underflow;
1498  }
1499  k = (int)stack[sp++];
1500  nn = (int)stack[sp++];
1501  if (nn < 0) {
1502  goto invalidArg;
1503  }
1504  if (nn > 0) {
1505  if (sp + nn > psStackSize) {
1506  goto underflow;
1507  }
1508  if (k >= 0) {
1509  k %= nn;
1510  } else {
1511  k = -k % nn;
1512  if (k) {
1513  k = nn - k;
1514  }
1515  }
1516  for (i = 0; i < nn; ++i) {
1517  tmp[i] = stack[sp + i];
1518  }
1519  for (i = 0; i < nn; ++i) {
1520  stack[sp + i] = tmp[(i + k) % nn];
1521  }
1522  }
1523  break;
1524  case psOpRound:
1525  if (sp >= psStackSize) {
1526  goto underflow;
1527  }
1528  t = stack[sp];
1529  stack[sp] = (t >= 0) ? floor(t + 0.5) : ceil(t - 0.5);
1530  break;
1531  case psOpSin:
1532  if (sp >= psStackSize) {
1533  goto underflow;
1534  }
1535  stack[sp] = sin(stack[sp]);
1536  break;
1537  case psOpSqrt:
1538  if (sp >= psStackSize) {
1539  goto underflow;
1540  }
1541  stack[sp] = sqrt(stack[sp]);
1542  break;
1543  case psOpSub:
1544  if (sp + 1 >= psStackSize) {
1545  goto underflow;
1546  }
1547  stack[sp + 1] = stack[sp + 1] - stack[sp];
1548  ++sp;
1549  break;
1550  case psOpTrue:
1551  if (sp < 1) {
1552  goto overflow;
1553  }
1554  stack[sp - 1] = 1;
1555  --sp;
1556  break;
1557  case psOpTruncate:
1558  if (sp >= psStackSize) {
1559  goto underflow;
1560  }
1561  t = stack[sp];
1562  stack[sp] = (t >= 0) ? floor(t) : ceil(t);
1563  break;
1564  case psOpXor:
1565  if (sp + 1 >= psStackSize) {
1566  goto underflow;
1567  }
1568  stack[sp + 1] = (int)stack[sp + 1] ^ (int)stack[sp];
1569  ++sp;
1570  break;
1571  case psOpPush:
1572  if (sp < 1) {
1573  goto overflow;
1574  }
1575  stack[--sp] = c->val.d;
1576  break;
1577  case psOpJ:
1578  ip = c->val.i;
1579  break;
1580  case psOpJz:
1581  if (sp >= psStackSize) {
1582  goto underflow;
1583  }
1584  k = (int)stack[sp++];
1585  if (k == 0) {
1586  ip = c->val.i;
1587  }
1588  break;
1589  }
1590  }
1591  return sp;
1592 
1593  underflow:
1594  error(errSyntaxError, -1, "Stack underflow in PostScript function");
1595  return sp;
1596  overflow:
1597  error(errSyntaxError, -1, "Stack overflow in PostScript function");
1598  return sp;
1599  invalidArg:
1600  error(errSyntaxError, -1, "Invalid arg in PostScript function");
1601  return sp;
1602 }
double __cdecl atan2(double _Y, double _X)
double __cdecl log10(double _X)
double __cdecl pow(double _X, double _Y)
double __cdecl log(double _X)
#define deleteGList(list, T)
Definition: GList.h:94
int cmp(const void *p, const void *q)
Definition: bkmk2uni.c:1611
Definition: Dict.h:29
Object * lookup(const char *key, Object *obj, int recursion=0)
Definition: Dict.cc:122
double c0[32]
Definition: Function.h:166
double c1[32]
Definition: Function.h:167
ExponentialFunction(Object *funcObj, Dict *dict)
Definition: Function.cc:517
virtual ~ExponentialFunction()
Definition: Function.cc:607
virtual void transform(double *in, double *out)
Definition: Function.cc:614
static Function * parse(Object *funcObj, int expectedInputs, int expectedOutputs, int recursion=0)
Definition: Function.cc:44
int n
Definition: Function.h:77
virtual ~Function()
Definition: Function.cc:41
int getOutputSize()
Definition: Function.h:62
GBool hasRange
Definition: Function.h:82
double range[32][2]
Definition: Function.h:81
GBool init(Dict *dict)
Definition: Function.cc:108
virtual void transform(double *in, double *out)=0
int m
Definition: Function.h:77
int getInputSize()
Definition: Function.h:61
Function()
Definition: Function.cc:38
double domain[32][2]
Definition: Function.h:79
Definition: GList.h:24
int getLength()
Definition: GList.h:39
void append(void *p)
Definition: GList.cc:53
void * get(int i)
Definition: GList.h:48
GString * append(char c)
Definition: GString.cc:218
virtual void transform(double *in, double *out)
Definition: Function.cc:201
virtual ~IdentityFunction()
Definition: Function.cc:198
Definition: Object.h:84
GBool isDict()
Definition: Object.h:137
Stream * getStream()
Definition: Object.h:162
GBool isNum()
Definition: Object.h:132
double getNum()
Definition: Object.h:157
GBool isName()
Definition: Object.h:134
void free()
Definition: Object.cc:119
GBool isStream()
Definition: Object.h:138
int getInt()
Definition: Object.h:155
GBool isInt()
Definition: Object.h:130
Dict * streamGetDict()
Definition: Object.h:317
int arrayGetLength()
Definition: Object.h:236
GBool isArray()
Definition: Object.h:136
Dict * getDict()
Definition: Object.h:161
Object * arrayGet(int i, Object *obj, int recursion=0)
Definition: Object.h:242
double cacheOut[32]
Definition: Function.h:236
void addCodeI(int *codePtr, int op, int x)
Definition: Function.cc:1154
GString * codeString
Definition: Function.h:231
GString * getToken(Stream *str)
Definition: Function.cc:1182
double cacheIn[32]
Definition: Function.h:235
virtual void transform(double *in, double *out)
Definition: Function.cc:998
void addCodeD(int *codePtr, int op, double x)
Definition: Function.cc:1168
int exec(double *stack, int sp0)
Definition: Function.cc:1231
PostScriptFunction(Object *funcObj, Dict *dict)
Definition: Function.cc:919
GBool parseCode(GList *tokens, int *tokPtr, int *codePtr)
Definition: Function.cc:1048
void addCode(int *codePtr, int op)
Definition: Function.cc:1141
virtual ~PostScriptFunction()
Definition: Function.cc:991
SampledFunction(Object *funcObj, Dict *dict)
Definition: Function.cc:213
double cacheOut[32]
Definition: Function.h:140
int * idxOffset
Definition: Function.h:135
virtual void transform(double *in, double *out)
Definition: Function.cc:436
int sampleSize[32]
Definition: Function.h:128
double inputMul[32]
Definition: Function.h:134
double encode[32][2]
Definition: Function.h:130
double * samples
Definition: Function.h:136
double cacheIn[32]
Definition: Function.h:139
double decode[32][2]
Definition: Function.h:132
virtual ~SampledFunction()
Definition: Function.cc:415
double * sBuf
Definition: Function.h:138
Function ** funcs
Definition: Function.h:198
double * bounds
Definition: Function.h:199
virtual ~StitchingFunction()
Definition: Function.cc:771
double * scale
Definition: Function.h:201
StitchingFunction(Object *funcObj, Dict *dict, int expectedInputs, int expectedOutputs, int recursion)
Definition: Function.cc:642
virtual void transform(double *in, double *out)
Definition: Function.cc:787
double * encode
Definition: Function.h:200
Definition: Stream.h:67
#define b
Definition: jpegint.h:372
#define gfree(p)
Definition: dt2dv.c:326
double cos()
double sin()
double sqrt()
#define error(a)
Definition: dviinfo.c:48
#define s
Definition: afcover.h:80
#define t
Definition: afcover.h:96
void * greallocn(void *p, int nObjs, int objSize)
Definition: gmem.cc:291
void * gmallocn(int nObjs, int objSize)
Definition: gmem.cc:204
__gmp_expr< mpf_t, __gmp_unary_expr< __gmp_expr< mpf_t, U >, __gmp_ceil_function > > ceil(const __gmp_expr< mpf_t, U > &expr)
Definition: gmpxx.h:3340
#define c(n)
Definition: gpos-common.c:150
#define a(n)
Definition: gpos-common.c:148
#define memcpy(d, s, n)
Definition: gsftopk.c:64
#define gFalse
Definition: gtypes.h:18
int GBool
Definition: gtypes.h:16
#define gTrue
Definition: gtypes.h:17
unsigned int Guint
Definition: gtypes.h:26
FILE * out
Definition: hbf2gf.c:286
char comment[255+1]
Definition: hbf2gf.c:350
#define NULL
Definition: ftobjs.h:61
small capitals from c petite p
Definition: afcover.h:72
small capitals from c petite p scientific i
Definition: afcover.h:80
FT_UInt idx
Definition: cffcmap.c:135
#define bits
Definition: infblock.c:15
#define EOF
Definition: afmparse.c:59
@ errSyntaxError
Definition: Error.h:25
#define psOpAtan
Definition: Function.cc:818
#define psOpFalse
Definition: Function.cc:830
#define psOpExp
Definition: Function.cc:829
#define psOpIdiv
Definition: Function.cc:834
#define psOpIndex
Definition: Function.cc:835
#define psOpDup
Definition: Function.cc:826
#define psOpLog
Definition: Function.cc:838
#define psStackSize
Definition: Function.cc:917
#define psOpMul
Definition: Function.cc:841
#define psOpCopy
Definition: Function.cc:821
#define psOpEq
Definition: Function.cc:827
#define psOpCvi
Definition: Function.cc:823
#define nPSOps
Definition: Function.cc:860
#define psOpNot
Definition: Function.cc:844
#define psOpNe
Definition: Function.cc:842
#define psOpLt
Definition: Function.cc:839
#define psOpFloor
Definition: Function.cc:831
#define psOpJ
Definition: Function.cc:857
#define psOpRoll
Definition: Function.cc:847
#define psOpMod
Definition: Function.cc:840
#define recursionLimit
Definition: Function.cc:32
#define psOpXor
Definition: Function.cc:854
#define psOpBitshift
Definition: Function.cc:819
#define psOpTrue
Definition: Function.cc:852
#define psOpPop
Definition: Function.cc:846
#define psOpNeg
Definition: Function.cc:843
#define psOpJz
Definition: Function.cc:858
#define psOpExch
Definition: Function.cc:828
#define psOpCeiling
Definition: Function.cc:820
#define psOpGt
Definition: Function.cc:833
#define psOpAbs
Definition: Function.cc:815
#define psOpPush
Definition: Function.cc:856
static const char * psOpNames[]
Definition: Function.cc:866
#define psOpLn
Definition: Function.cc:837
#define psOpGe
Definition: Function.cc:832
#define psOpAdd
Definition: Function.cc:816
#define psOpCvr
Definition: Function.cc:824
#define psOpLe
Definition: Function.cc:836
#define psOpSub
Definition: Function.cc:851
#define psOpSin
Definition: Function.cc:849
#define psOpAnd
Definition: Function.cc:817
#define psOpDiv
Definition: Function.cc:825
#define psOpRound
Definition: Function.cc:848
#define psOpCos
Definition: Function.cc:822
#define psOpSqrt
Definition: Function.cc:850
#define psOpTruncate
Definition: Function.cc:853
#define psOpOr
Definition: Function.cc:845
#define funcMaxOutputs
Definition: Function.h:31
#define sampledFuncMaxInputs
Definition: Function.h:32
#define funcMaxInputs
Definition: Function.h:30
double atof(const char *)
#define buf
#define INT_MAX
Definition: c-minmax.h:53
#define fabs(x)
Definition: cpascal.h:211
#define floor(x)
Definition: cpascal.h:52
void overflow(const char *)
Definition: cwebboot.c:1385
#define isdigit(c)
Definition: snprintf.c:177
static luaL_Reg func[]
Definition: except.c:32
float x
Definition: cordic.py:15
int k
Definition: otp-parser.c:70
unsigned char bit
Definition: pbm.h:9
integer nn[24]
Definition: pmxab.c:90
#define isspace(ch)
Definition: utype.h:87
#define isalnum(ch)
Definition: utype.h:84
#define str(s)
Definition: sh6.c:399
ShellFileEnvironment e
Definition: sh6.c:388
static FILE * in
Definition: squeeze.c:36
int i
Definition: Function.cc:913
double d
Definition: Function.cc:912
int op
Definition: Function.cc:910
union PSCode::@72 val
Definition: namelist.c:170
Definition: inftrees.h:24
unsigned char op
Definition: inftrees.h:25
unsigned short val
Definition: inftrees.h:27
Definition: sh.h:1226
Definition: spc_misc.c:56
Definition: dvips.h:235
int j
Definition: t4ht.c:1589
op
Definition: tex4ht.c:3129
return() int(((double) *(font_tbl[cur_fnt].wtbl+(int)(*(font_tbl[cur_fnt].char_wi+(int)(ch - font_tbl[cur_fnt].char_f)% 256)))/(double)(1L<< 20)) *(double) font_tbl[cur_fnt].scale)
#define sp
Definition: stack.c:11
#define ip
Definition: stack.c:14
static const char * tok(parser_state *p)
Definition: y.tab.c:10456