1
/* Copyright (C) 2001-2006 Artifex Software, Inc.
4
This software is provided AS-IS with no warranty, either express or
7
This software is distributed under license and may not be copied, modified
8
or distributed except as expressly authorized under the terms of that
9
license. Refer to licensing information at http://www.artifex.com/
10
or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
11
San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
14
/* $Id: gsfunc3.c 8250 2007-09-25 13:31:24Z giles $ */
15
/* Implementation of LL3 Functions */
26
/* ---------------- Utilities ---------------- */
28
#define MASK1 ((uint)(~0) / 3)
31
* Free an array of subsidiary Functions. Note that this may be called
32
* before the Functions array has been fully initialized. Note also that
33
* its argument conforms to the Functions array in the parameter structure,
34
* but it (necessarily) deconstifies it.
37
fn_free_functions(const gs_function_t *const * Functions, int count,
42
for (i = count; --i >= 0;)
44
gs_function_free((gs_function_t *)Functions[i], true, mem);
45
gs_free_const_object(mem, Functions, "Functions");
49
* Scale an array of subsidiary functions. Note that the scale may either
50
* be propagated unchanged (step_ranges = false) or divided among the
51
* (1-output) subfunctions (step_ranges = true).
54
fn_scale_functions(gs_function_t ***ppsfns, const gs_function_t *const *pfns,
55
int count, const gs_range_t *pranges, bool step_ranges,
58
gs_function_t **psfns;
59
int code = alloc_function_array(count, &psfns, mem);
60
const gs_range_t *ranges = pranges;
65
for (i = 0; i < count; ++i) {
66
int code = gs_function_make_scaled(pfns[i], &psfns[i], ranges, mem);
69
fn_free_functions((const gs_function_t *const *)psfns, count, mem);
79
/* ---------------- Exponential Interpolation functions ---------------- */
81
typedef struct gs_function_ElIn_s {
82
gs_function_head_t head;
83
gs_function_ElIn_params_t params;
86
private_st_function_ElIn();
88
/* Evaluate an Exponential Interpolation function. */
90
fn_ElIn_evaluate(const gs_function_t * pfn_common, const float *in, float *out)
92
const gs_function_ElIn_t *const pfn =
93
(const gs_function_ElIn_t *)pfn_common;
94
double arg = in[0], raised;
97
if (arg < pfn->params.Domain[0])
98
arg = pfn->params.Domain[0];
99
else if (arg > pfn->params.Domain[1])
100
arg = pfn->params.Domain[1];
101
raised = pow(arg, pfn->params.N);
102
for (i = 0; i < pfn->params.n; ++i) {
103
float v0 = (pfn->params.C0 == 0 ? 0.0 : pfn->params.C0[i]);
104
float v1 = (pfn->params.C1 == 0 ? 1.0 : pfn->params.C1[i]);
105
double value = v0 + raised * (v1 - v0);
107
if (pfn->params.Range) {
108
float r0 = pfn->params.Range[2 * i],
109
r1 = pfn->params.Range[2 * i + 1];
117
if_debug3('~', "[~]ElIn %g => [%d]%g\n", arg, i, out[i]);
122
/* Test whether an Exponential function is monotonic. (They always are.) */
124
fn_ElIn_is_monotonic(const gs_function_t * pfn_common,
125
const float *lower, const float *upper, uint *mask)
127
const gs_function_ElIn_t *const pfn =
128
(const gs_function_ElIn_t *)pfn_common;
130
if (lower[0] > pfn->params.Domain[1] ||
131
upper[0] < pfn->params.Domain[0]
133
return_error(gs_error_rangecheck);
138
/* Write Exponential Interpolation function parameters on a parameter list. */
140
fn_ElIn_get_params(const gs_function_t *pfn_common, gs_param_list *plist)
142
const gs_function_ElIn_t *const pfn =
143
(const gs_function_ElIn_t *)pfn_common;
144
int ecode = fn_common_get_params(pfn_common, plist);
147
if (pfn->params.C0) {
148
if ((code = param_write_float_values(plist, "C0", pfn->params.C0,
149
pfn->params.n, false)) < 0)
152
if (pfn->params.C1) {
153
if ((code = param_write_float_values(plist, "C1", pfn->params.C1,
154
pfn->params.n, false)) < 0)
157
if ((code = param_write_float(plist, "N", &pfn->params.N)) < 0)
162
/* Make a scaled copy of an Exponential Interpolation function. */
164
fn_ElIn_make_scaled(const gs_function_ElIn_t *pfn,
165
gs_function_ElIn_t **ppsfn,
166
const gs_range_t *pranges, gs_memory_t *mem)
168
gs_function_ElIn_t *psfn =
169
gs_alloc_struct(mem, gs_function_ElIn_t, &st_function_ElIn,
170
"fn_ElIn_make_scaled");
176
return_error(gs_error_VMerror);
177
psfn->params = pfn->params;
178
psfn->params.C0 = c0 =
179
fn_copy_values(pfn->params.C0, pfn->params.n, sizeof(float), mem);
180
psfn->params.C1 = c1 =
181
fn_copy_values(pfn->params.C1, pfn->params.n, sizeof(float), mem);
182
if ((code = ((c0 == 0 && pfn->params.C0 != 0) ||
183
(c1 == 0 && pfn->params.C1 != 0) ?
184
gs_note_error(gs_error_VMerror) : 0)) < 0 ||
185
(code = fn_common_scale((gs_function_t *)psfn,
186
(const gs_function_t *)pfn,
187
pranges, mem)) < 0) {
188
gs_function_free((gs_function_t *)psfn, true, mem);
191
for (i = 0; i < pfn->params.n; ++i) {
192
double base = pranges[i].rmin, factor = pranges[i].rmax - base;
194
c1[i] = c1[i] * factor + base;
195
c0[i] = c0[i] * factor + base;
201
/* Free the parameters of an Exponential Interpolation function. */
203
gs_function_ElIn_free_params(gs_function_ElIn_params_t * params,
206
gs_free_const_object(mem, params->C1, "C1");
207
gs_free_const_object(mem, params->C0, "C0");
208
fn_common_free_params((gs_function_params_t *) params, mem);
213
gs_function_ElIn_serialize(const gs_function_t * pfn, stream *s)
216
const gs_function_ElIn_params_t * p = (const gs_function_ElIn_params_t *)&pfn->params;
217
int code = fn_common_serialize(pfn, s);
221
code = sputs(s, (const byte *)&p->C0[0], sizeof(p->C0[0]) * p->n, &n);
224
code = sputs(s, (const byte *)&p->C1[0], sizeof(p->C1[0]) * p->n, &n);
227
return sputs(s, (const byte *)&p->N, sizeof(p->N), &n);
230
/* Allocate and initialize an Exponential Interpolation function. */
232
gs_function_ElIn_init(gs_function_t ** ppfn,
233
const gs_function_ElIn_params_t * params,
236
static const gs_function_head_t function_ElIn_head = {
237
function_type_ExponentialInterpolation,
239
(fn_evaluate_proc_t) fn_ElIn_evaluate,
240
(fn_is_monotonic_proc_t) fn_ElIn_is_monotonic,
241
gs_function_get_info_default,
242
(fn_get_params_proc_t) fn_ElIn_get_params,
243
(fn_make_scaled_proc_t) fn_ElIn_make_scaled,
244
(fn_free_params_proc_t) gs_function_ElIn_free_params,
246
(fn_serialize_proc_t) gs_function_ElIn_serialize,
251
*ppfn = 0; /* in case of error */
252
code = fn_check_mnDR((const gs_function_params_t *)params, 1, params->n);
255
if ((params->C0 == 0 || params->C1 == 0) && params->n != 1)
256
return_error(gs_error_rangecheck);
257
if (params->N != floor(params->N)) {
258
/* Non-integral exponent, all inputs must be non-negative. */
259
if (params->Domain[0] < 0)
260
return_error(gs_error_rangecheck);
263
/* Negative exponent, input must not be zero. */
264
if (params->Domain[0] <= 0 && params->Domain[1] >= 0)
265
return_error(gs_error_rangecheck);
267
gs_function_ElIn_t *pfn =
268
gs_alloc_struct(mem, gs_function_ElIn_t, &st_function_ElIn,
269
"gs_function_ElIn_init");
272
return_error(gs_error_VMerror);
273
pfn->params = *params;
275
pfn->head = function_ElIn_head;
276
*ppfn = (gs_function_t *) pfn;
281
/* ---------------- 1-Input Stitching functions ---------------- */
283
typedef struct gs_function_1ItSg_s {
284
gs_function_head_t head;
285
gs_function_1ItSg_params_t params;
286
} gs_function_1ItSg_t;
288
private_st_function_1ItSg();
290
/* Evaluate a 1-Input Stitching function. */
292
fn_1ItSg_evaluate(const gs_function_t * pfn_common, const float *in, float *out)
294
const gs_function_1ItSg_t *const pfn =
295
(const gs_function_1ItSg_t *)pfn_common;
296
float arg = in[0], b0, b1, e0, encoded;
297
int k = pfn->params.k;
300
if (arg < pfn->params.Domain[0]) {
301
arg = pfn->params.Domain[0];
303
} else if (arg > pfn->params.Domain[1]) {
304
arg = pfn->params.Domain[1];
307
for (i = 0; i < k - 1; ++i)
308
if (arg <= pfn->params.Bounds[i])
311
b0 = (i == 0 ? pfn->params.Domain[0] : pfn->params.Bounds[i - 1]);
312
b1 = (i == k - 1 ? pfn->params.Domain[1] : pfn->params.Bounds[i]);
313
e0 = pfn->params.Encode[2 * i];
318
(arg - b0) * (pfn->params.Encode[2 * i + 1] - e0) / (b1 - b0) + e0;
319
if_debug3('~', "[~]1ItSg %g in %d => %g\n", arg, i, encoded);
320
return gs_function_evaluate(pfn->params.Functions[i], &encoded, out);
323
/* Test whether a 1-Input Stitching function is monotonic. */
325
fn_1ItSg_is_monotonic(const gs_function_t * pfn_common,
326
const float *lower, const float *upper, uint *mask)
328
const gs_function_1ItSg_t *const pfn =
329
(const gs_function_1ItSg_t *)pfn_common;
330
float v0 = lower[0], v1 = upper[0];
331
float d0 = pfn->params.Domain[0], d1 = pfn->params.Domain[1];
332
int k = pfn->params.k;
337
v0 = v1; v1 = lower[0];
339
if (v0 > d1 || v1 < d0)
340
return_error(gs_error_rangecheck);
345
for (i = 0; i < pfn->params.k; ++i) {
346
float b0 = (i == 0 ? d0 : pfn->params.Bounds[i - 1]);
347
float b1 = (i == k - 1 ? d1 : pfn->params.Bounds[i]);
348
const float bsmall = (float)1e-6 * (b1 - b0);
357
if (v0 >= b1 - bsmall)
358
continue; /* Ignore a small noise */
361
if (vv1 > b1 && v1 < b1 + bsmall)
362
vv1 = b1; /* Ignore a small noise */
365
if (vv0 < b1 && vv1 > b1) {
367
return 0; /* Consider stitches as monotonity breaks. */
369
e0 = pfn->params.Encode[2 * i];
370
e1 = pfn->params.Encode[2 * i + 1];
371
esmall = (float)1e-6 * any_abs(e1 - e0);
374
w0 = (float)(vb0 - b0) * (e1 - e0) / (b1 - b0) + e0;
375
w1 = (float)(vb1 - b0) * (e1 - e0) / (b1 - b0) + e0;
376
/* Note that w0 > w1 is now possible if e0 > e1. */
378
if (w0 > e0 && w0 - esmall <= e0)
379
w0 = e0; /* Suppress a small noise */
380
if (w1 < e1 && w1 + esmall >= e1)
381
w1 = e1; /* Suppress a small noise */
383
if (w0 < e0 && w0 + esmall >= e0)
384
w0 = e0; /* Suppress a small noise */
385
if (w1 > e1 && w1 - esmall <= e1)
386
w1 = e1; /* Suppress a small noise */
389
return gs_function_is_monotonic(pfn->params.Functions[i],
392
return gs_function_is_monotonic(pfn->params.Functions[i],
395
/* v0 is equal to the range end. */
400
/* Return 1-Input Stitching function information. */
402
fn_1ItSg_get_info(const gs_function_t *pfn_common, gs_function_info_t *pfi)
404
const gs_function_1ItSg_t *const pfn =
405
(const gs_function_1ItSg_t *)pfn_common;
407
gs_function_get_info_default(pfn_common, pfi);
408
pfi->Functions = pfn->params.Functions;
409
pfi->num_Functions = pfn->params.k;
412
/* Write 1-Input Stitching function parameters on a parameter list. */
414
fn_1ItSg_get_params(const gs_function_t *pfn_common, gs_param_list *plist)
416
const gs_function_1ItSg_t *const pfn =
417
(const gs_function_1ItSg_t *)pfn_common;
418
int ecode = fn_common_get_params(pfn_common, plist);
421
if ((code = param_write_float_values(plist, "Bounds", pfn->params.Bounds,
422
pfn->params.k - 1, false)) < 0)
424
if ((code = param_write_float_values(plist, "Encode", pfn->params.Encode,
425
2 * pfn->params.k, false)) < 0)
430
/* Make a scaled copy of a 1-Input Stitching function. */
432
fn_1ItSg_make_scaled(const gs_function_1ItSg_t *pfn,
433
gs_function_1ItSg_t **ppsfn,
434
const gs_range_t *pranges, gs_memory_t *mem)
436
gs_function_1ItSg_t *psfn =
437
gs_alloc_struct(mem, gs_function_1ItSg_t, &st_function_1ItSg,
438
"fn_1ItSg_make_scaled");
442
return_error(gs_error_VMerror);
443
psfn->params = pfn->params;
444
psfn->params.Functions = 0; /* in case of failure */
445
psfn->params.Bounds =
446
fn_copy_values(pfn->params.Bounds, pfn->params.k - 1, sizeof(float),
448
psfn->params.Encode =
449
fn_copy_values(pfn->params.Encode, 2 * pfn->params.k, sizeof(float),
451
if ((code = (psfn->params.Bounds == 0 || psfn->params.Encode == 0 ?
452
gs_note_error(gs_error_VMerror) : 0)) < 0 ||
453
(code = fn_common_scale((gs_function_t *)psfn,
454
(const gs_function_t *)pfn,
455
pranges, mem)) < 0 ||
456
(code = fn_scale_functions((gs_function_t ***)&psfn->params.Functions,
457
pfn->params.Functions,
458
pfn->params.n, pranges, false, mem)) < 0) {
459
gs_function_free((gs_function_t *)psfn, true, mem);
466
/* Free the parameters of a 1-Input Stitching function. */
468
gs_function_1ItSg_free_params(gs_function_1ItSg_params_t * params,
471
gs_free_const_object(mem, params->Encode, "Encode");
472
gs_free_const_object(mem, params->Bounds, "Bounds");
473
fn_free_functions(params->Functions, params->k, mem);
474
fn_common_free_params((gs_function_params_t *) params, mem);
479
gs_function_1ItSg_serialize(const gs_function_t * pfn, stream *s)
482
const gs_function_1ItSg_params_t * p = (const gs_function_1ItSg_params_t *)&pfn->params;
483
int code = fn_common_serialize(pfn, s);
488
code = sputs(s, (const byte *)&p->k, sizeof(p->k), &n);
492
for (k = 0; k < p->k && code >= 0; k++)
493
code = gs_function_serialize(p->Functions[k], s);
496
code = sputs(s, (const byte *)&p->Bounds[0], sizeof(p->Bounds[0]) * (p->k - 1), &n);
499
return sputs(s, (const byte *)&p->Encode[0], sizeof(p->Encode[0]) * (p->k * 2), &n);
502
/* Allocate and initialize a 1-Input Stitching function. */
504
gs_function_1ItSg_init(gs_function_t ** ppfn,
505
const gs_function_1ItSg_params_t * params, gs_memory_t * mem)
507
static const gs_function_head_t function_1ItSg_head = {
508
function_type_1InputStitching,
510
(fn_evaluate_proc_t) fn_1ItSg_evaluate,
511
(fn_is_monotonic_proc_t) fn_1ItSg_is_monotonic,
512
(fn_get_info_proc_t) fn_1ItSg_get_info,
513
(fn_get_params_proc_t) fn_1ItSg_get_params,
514
(fn_make_scaled_proc_t) fn_1ItSg_make_scaled,
515
(fn_free_params_proc_t) gs_function_1ItSg_free_params,
517
(fn_serialize_proc_t) gs_function_1ItSg_serialize,
520
int n = (params->Range == 0 ? 0 : params->n);
521
float prev = params->Domain[0];
524
*ppfn = 0; /* in case of error */
525
for (i = 0; i < params->k; ++i) {
526
const gs_function_t *psubfn = params->Functions[i];
528
if (psubfn->params.m != 1)
529
return_error(gs_error_rangecheck);
531
n = psubfn->params.n;
532
else if (psubfn->params.n != n)
533
return_error(gs_error_rangecheck);
534
/* There are only k - 1 Bounds, not k. */
535
if (i < params->k - 1) {
536
if (params->Bounds[i] < prev)
537
return_error(gs_error_rangecheck);
538
prev = params->Bounds[i];
541
if (params->Domain[1] < prev)
542
return_error(gs_error_rangecheck);
543
fn_check_mnDR((const gs_function_params_t *)params, 1, n);
545
gs_function_1ItSg_t *pfn =
546
gs_alloc_struct(mem, gs_function_1ItSg_t, &st_function_1ItSg,
547
"gs_function_1ItSg_init");
550
return_error(gs_error_VMerror);
551
pfn->params = *params;
554
pfn->head = function_1ItSg_head;
555
*ppfn = (gs_function_t *) pfn;
560
/* ---------------- Arrayed Output functions ---------------- */
562
typedef struct gs_function_AdOt_s {
563
gs_function_head_t head;
564
gs_function_AdOt_params_t params;
565
} gs_function_AdOt_t;
567
private_st_function_AdOt();
569
/* Evaluate an Arrayed Output function. */
571
fn_AdOt_evaluate(const gs_function_t *pfn_common, const float *in0, float *out)
573
const gs_function_AdOt_t *const pfn =
574
(const gs_function_AdOt_t *)pfn_common;
575
const float *in = in0;
576
#define MAX_ADOT_IN 16
577
float in_buf[MAX_ADOT_IN];
581
* We have to take special care to handle the case where in and out
582
* overlap. For the moment, handle it only for a limited number of
585
if (in <= out + (pfn->params.n - 1) && out <= in + (pfn->params.m - 1)) {
586
if (pfn->params.m > MAX_ADOT_IN)
587
return_error(gs_error_rangecheck);
588
memcpy(in_buf, in, pfn->params.m * sizeof(*in));
591
for (i = 0; i < pfn->params.n; ++i) {
593
gs_function_evaluate(pfn->params.Functions[i], in, out + i);
602
/* Test whether an Arrayed Output function is monotonic. */
604
fn_AdOt_is_monotonic(const gs_function_t * pfn_common,
605
const float *lower, const float *upper, uint *mask)
607
const gs_function_AdOt_t *const pfn =
608
(const gs_function_AdOt_t *)pfn_common;
611
for (i = 0; i < pfn->params.n; ++i) {
613
gs_function_is_monotonic(pfn->params.Functions[i], lower, upper, mask);
621
/* Return Arrayed Output function information. */
623
fn_AdOt_get_info(const gs_function_t *pfn_common, gs_function_info_t *pfi)
625
const gs_function_AdOt_t *const pfn =
626
(const gs_function_AdOt_t *)pfn_common;
628
gs_function_get_info_default(pfn_common, pfi);
629
pfi->Functions = pfn->params.Functions;
630
pfi->num_Functions = pfn->params.n;
633
/* Make a scaled copy of an Arrayed Output function. */
635
fn_AdOt_make_scaled(const gs_function_AdOt_t *pfn, gs_function_AdOt_t **ppsfn,
636
const gs_range_t *pranges, gs_memory_t *mem)
638
gs_function_AdOt_t *psfn =
639
gs_alloc_struct(mem, gs_function_AdOt_t, &st_function_AdOt,
640
"fn_AdOt_make_scaled");
644
return_error(gs_error_VMerror);
645
psfn->params = pfn->params;
646
psfn->params.Functions = 0; /* in case of failure */
647
if ((code = fn_common_scale((gs_function_t *)psfn,
648
(const gs_function_t *)pfn,
649
pranges, mem)) < 0 ||
650
(code = fn_scale_functions((gs_function_t ***)&psfn->params.Functions,
651
pfn->params.Functions,
652
pfn->params.n, pranges, true, mem)) < 0) {
653
gs_function_free((gs_function_t *)psfn, true, mem);
660
/* Free the parameters of an Arrayed Output function. */
662
gs_function_AdOt_free_params(gs_function_AdOt_params_t * params,
665
fn_free_functions(params->Functions, params->n, mem);
666
fn_common_free_params((gs_function_params_t *) params, mem);
671
gs_function_AdOt_serialize(const gs_function_t * pfn, stream *s)
673
const gs_function_AdOt_params_t * p = (const gs_function_AdOt_params_t *)&pfn->params;
674
int code = fn_common_serialize(pfn, s);
679
for (k = 0; k < p->n && code >= 0; k++)
680
code = gs_function_serialize(p->Functions[k], s);
684
/* Allocate and initialize an Arrayed Output function. */
686
gs_function_AdOt_init(gs_function_t ** ppfn,
687
const gs_function_AdOt_params_t * params, gs_memory_t * mem)
689
static const gs_function_head_t function_AdOt_head = {
690
function_type_ArrayedOutput,
692
(fn_evaluate_proc_t) fn_AdOt_evaluate,
693
(fn_is_monotonic_proc_t) fn_AdOt_is_monotonic,
694
(fn_get_info_proc_t) fn_AdOt_get_info,
695
fn_common_get_params, /****** WHAT TO DO ABOUT THIS? ******/
696
(fn_make_scaled_proc_t) fn_AdOt_make_scaled,
697
(fn_free_params_proc_t) gs_function_AdOt_free_params,
699
(fn_serialize_proc_t) gs_function_AdOt_serialize,
702
int m = params->m, n = params->n;
704
*ppfn = 0; /* in case of error */
705
if (m <= 0 || n <= 0)
706
return_error(gs_error_rangecheck);
708
gs_function_AdOt_t *pfn =
709
gs_alloc_struct(mem, gs_function_AdOt_t, &st_function_AdOt,
710
"gs_function_AdOt_init");
711
float *domain = (float *)
712
gs_alloc_byte_array(mem, 2 * m, sizeof(float),
713
"gs_function_AdOt_init(Domain)");
717
return_error(gs_error_VMerror);
718
pfn->params = *params;
719
pfn->params.Domain = domain;
720
pfn->params.Range = 0;
721
pfn->head = function_AdOt_head;
723
gs_function_free((gs_function_t *)pfn, true, mem);
724
return_error(gs_error_VMerror);
727
* We compute the Domain as the intersection of the Domains of
728
* the individual subfunctions. This isn't quite right: some
729
* subfunction might actually make use of a larger domain of
730
* input values. However, the only place that Arrayed Output
731
* functions are used is in Shading and similar dictionaries,
732
* where the input values are clamped to the intersection of
733
* the individual Domains anyway.
735
memcpy(domain, params->Functions[0]->params.Domain,
736
2 * sizeof(float) * m);
737
for (i = 1; i < n; ++i) {
738
const float *dom = params->Functions[i]->params.Domain;
740
for (j = 0; j < 2 * m; j += 2, dom += 2) {
741
domain[j] = max(domain[j], dom[0]);
742
domain[j + 1] = min(domain[j + 1], dom[1]);
745
*ppfn = (gs_function_t *) pfn;