gsfunc3.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746
  1. /* Copyright (C) 1997, 2000 Aladdin Enterprises. All rights reserved.
  2. This software is provided AS-IS with no warranty, either express or
  3. implied.
  4. This software is distributed under license and may not be copied,
  5. modified or distributed except as expressly authorized under the terms
  6. of the license contained in the file LICENSE in this distribution.
  7. For more information about licensing, please refer to
  8. http://www.ghostscript.com/licensing/. For information on
  9. commercial licensing, go to http://www.artifex.com/licensing/ or
  10. contact Artifex Software, Inc., 101 Lucas Valley Road #110,
  11. San Rafael, CA 94903, U.S.A., +1(415)492-9861.
  12. */
  13. /* $Id: gsfunc3.c,v 1.26 2005/05/03 10:50:48 igor Exp $ */
  14. /* Implementation of LL3 Functions */
  15. #include "math_.h"
  16. #include "memory_.h"
  17. #include "gx.h"
  18. #include "gserrors.h"
  19. #include "gsfunc3.h"
  20. #include "gsparam.h"
  21. #include "gxfunc.h"
  22. #include "stream.h"
  23. /* ---------------- Utilities ---------------- */
  24. #define MASK1 ((uint)(~0) / 3)
  25. /*
  26. * Free an array of subsidiary Functions. Note that this may be called
  27. * before the Functions array has been fully initialized. Note also that
  28. * its argument conforms to the Functions array in the parameter structure,
  29. * but it (necessarily) deconstifies it.
  30. */
  31. private void
  32. fn_free_functions(const gs_function_t *const * Functions, int count,
  33. gs_memory_t * mem)
  34. {
  35. int i;
  36. for (i = count; --i >= 0;)
  37. if (Functions[i])
  38. gs_function_free((gs_function_t *)Functions[i], true, mem);
  39. gs_free_const_object(mem, Functions, "Functions");
  40. }
  41. /*
  42. * Scale an array of subsidiary functions. Note that the scale may either
  43. * be propagated unchanged (step_ranges = false) or divided among the
  44. * (1-output) subfunctions (step_ranges = true).
  45. */
  46. private int
  47. fn_scale_functions(gs_function_t ***ppsfns, const gs_function_t *const *pfns,
  48. int count, const gs_range_t *pranges, bool step_ranges,
  49. gs_memory_t *mem)
  50. {
  51. gs_function_t **psfns;
  52. int code = alloc_function_array(count, &psfns, mem);
  53. const gs_range_t *ranges = pranges;
  54. int i;
  55. if (code < 0)
  56. return code;
  57. for (i = 0; i < count; ++i) {
  58. int code = gs_function_make_scaled(pfns[i], &psfns[i], ranges, mem);
  59. if (code < 0) {
  60. fn_free_functions((const gs_function_t *const *)psfns, count, mem);
  61. return code;
  62. }
  63. if (step_ranges)
  64. ++ranges;
  65. }
  66. *ppsfns = psfns;
  67. return 0;
  68. }
  69. /* ---------------- Exponential Interpolation functions ---------------- */
  70. typedef struct gs_function_ElIn_s {
  71. gs_function_head_t head;
  72. gs_function_ElIn_params_t params;
  73. } gs_function_ElIn_t;
  74. private_st_function_ElIn();
  75. /* Evaluate an Exponential Interpolation function. */
  76. private int
  77. fn_ElIn_evaluate(const gs_function_t * pfn_common, const float *in, float *out)
  78. {
  79. const gs_function_ElIn_t *const pfn =
  80. (const gs_function_ElIn_t *)pfn_common;
  81. double arg = in[0], raised;
  82. int i;
  83. if (arg < pfn->params.Domain[0])
  84. arg = pfn->params.Domain[0];
  85. else if (arg > pfn->params.Domain[1])
  86. arg = pfn->params.Domain[1];
  87. raised = pow(arg, pfn->params.N);
  88. for (i = 0; i < pfn->params.n; ++i) {
  89. float v0 = (pfn->params.C0 == 0 ? 0.0 : pfn->params.C0[i]);
  90. float v1 = (pfn->params.C1 == 0 ? 1.0 : pfn->params.C1[i]);
  91. double value = v0 + raised * (v1 - v0);
  92. if (pfn->params.Range) {
  93. float r0 = pfn->params.Range[2 * i],
  94. r1 = pfn->params.Range[2 * i + 1];
  95. if (value < r0)
  96. value = r0;
  97. else if (value > r1)
  98. value = r1;
  99. }
  100. out[i] = value;
  101. if_debug3('~', "[~]ElIn %g => [%d]%g\n", arg, i, out[i]);
  102. }
  103. return 0;
  104. }
  105. /* Test whether an Exponential function is monotonic. (They always are.) */
  106. private int
  107. fn_ElIn_is_monotonic(const gs_function_t * pfn_common,
  108. const float *lower, const float *upper, uint *mask)
  109. {
  110. const gs_function_ElIn_t *const pfn =
  111. (const gs_function_ElIn_t *)pfn_common;
  112. if (lower[0] > pfn->params.Domain[1] ||
  113. upper[0] < pfn->params.Domain[0]
  114. )
  115. return_error(gs_error_rangecheck);
  116. *mask = 0;
  117. return 1;
  118. }
  119. /* Write Exponential Interpolation function parameters on a parameter list. */
  120. private int
  121. fn_ElIn_get_params(const gs_function_t *pfn_common, gs_param_list *plist)
  122. {
  123. const gs_function_ElIn_t *const pfn =
  124. (const gs_function_ElIn_t *)pfn_common;
  125. int ecode = fn_common_get_params(pfn_common, plist);
  126. int code;
  127. if (pfn->params.C0) {
  128. if ((code = param_write_float_values(plist, "C0", pfn->params.C0,
  129. pfn->params.n, false)) < 0)
  130. ecode = code;
  131. }
  132. if (pfn->params.C1) {
  133. if ((code = param_write_float_values(plist, "C1", pfn->params.C1,
  134. pfn->params.n, false)) < 0)
  135. ecode = code;
  136. }
  137. if ((code = param_write_float(plist, "N", &pfn->params.N)) < 0)
  138. ecode = code;
  139. return ecode;
  140. }
  141. /* Make a scaled copy of an Exponential Interpolation function. */
  142. private int
  143. fn_ElIn_make_scaled(const gs_function_ElIn_t *pfn,
  144. gs_function_ElIn_t **ppsfn,
  145. const gs_range_t *pranges, gs_memory_t *mem)
  146. {
  147. gs_function_ElIn_t *psfn =
  148. gs_alloc_struct(mem, gs_function_ElIn_t, &st_function_ElIn,
  149. "fn_ElIn_make_scaled");
  150. float *c0;
  151. float *c1;
  152. int code, i;
  153. if (psfn == 0)
  154. return_error(gs_error_VMerror);
  155. psfn->params = pfn->params;
  156. psfn->params.C0 = c0 =
  157. fn_copy_values(pfn->params.C0, pfn->params.n, sizeof(float), mem);
  158. psfn->params.C1 = c1 =
  159. fn_copy_values(pfn->params.C1, pfn->params.n, sizeof(float), mem);
  160. if ((code = ((c0 == 0 && pfn->params.C0 != 0) ||
  161. (c1 == 0 && pfn->params.C1 != 0) ?
  162. gs_note_error(gs_error_VMerror) : 0)) < 0 ||
  163. (code = fn_common_scale((gs_function_t *)psfn,
  164. (const gs_function_t *)pfn,
  165. pranges, mem)) < 0) {
  166. gs_function_free((gs_function_t *)psfn, true, mem);
  167. return code;
  168. }
  169. for (i = 0; i < pfn->params.n; ++i) {
  170. double base = pranges[i].rmin, factor = pranges[i].rmax - base;
  171. c1[i] = c1[i] * factor + base;
  172. c0[i] = c0[i] * factor + base;
  173. }
  174. *ppsfn = psfn;
  175. return 0;
  176. }
  177. /* Free the parameters of an Exponential Interpolation function. */
  178. void
  179. gs_function_ElIn_free_params(gs_function_ElIn_params_t * params,
  180. gs_memory_t * mem)
  181. {
  182. gs_free_const_object(mem, params->C1, "C1");
  183. gs_free_const_object(mem, params->C0, "C0");
  184. fn_common_free_params((gs_function_params_t *) params, mem);
  185. }
  186. /* Serialize. */
  187. private int
  188. gs_function_ElIn_serialize(const gs_function_t * pfn, stream *s)
  189. {
  190. uint n;
  191. const gs_function_ElIn_params_t * p = (const gs_function_ElIn_params_t *)&pfn->params;
  192. int code = fn_common_serialize(pfn, s);
  193. if (code < 0)
  194. return code;
  195. code = sputs(s, (const byte *)&p->C0[0], sizeof(p->C0[0]) * p->n, &n);
  196. if (code < 0)
  197. return code;
  198. code = sputs(s, (const byte *)&p->C1[0], sizeof(p->C1[0]) * p->n, &n);
  199. if (code < 0)
  200. return code;
  201. return sputs(s, (const byte *)&p->N, sizeof(p->N), &n);
  202. }
  203. /* Allocate and initialize an Exponential Interpolation function. */
  204. int
  205. gs_function_ElIn_init(gs_function_t ** ppfn,
  206. const gs_function_ElIn_params_t * params,
  207. gs_memory_t * mem)
  208. {
  209. static const gs_function_head_t function_ElIn_head = {
  210. function_type_ExponentialInterpolation,
  211. {
  212. (fn_evaluate_proc_t) fn_ElIn_evaluate,
  213. (fn_is_monotonic_proc_t) fn_ElIn_is_monotonic,
  214. gs_function_get_info_default,
  215. (fn_get_params_proc_t) fn_ElIn_get_params,
  216. (fn_make_scaled_proc_t) fn_ElIn_make_scaled,
  217. (fn_free_params_proc_t) gs_function_ElIn_free_params,
  218. fn_common_free,
  219. (fn_serialize_proc_t) gs_function_ElIn_serialize,
  220. }
  221. };
  222. int code;
  223. *ppfn = 0; /* in case of error */
  224. code = fn_check_mnDR((const gs_function_params_t *)params, 1, params->n);
  225. if (code < 0)
  226. return code;
  227. if ((params->C0 == 0 || params->C1 == 0) && params->n != 1)
  228. return_error(gs_error_rangecheck);
  229. if (params->N != floor(params->N)) {
  230. /* Non-integral exponent, all inputs must be non-negative. */
  231. if (params->Domain[0] < 0)
  232. return_error(gs_error_rangecheck);
  233. }
  234. if (params->N < 0) {
  235. /* Negative exponent, input must not be zero. */
  236. if (params->Domain[0] <= 0 && params->Domain[1] >= 0)
  237. return_error(gs_error_rangecheck);
  238. } {
  239. gs_function_ElIn_t *pfn =
  240. gs_alloc_struct(mem, gs_function_ElIn_t, &st_function_ElIn,
  241. "gs_function_ElIn_init");
  242. if (pfn == 0)
  243. return_error(gs_error_VMerror);
  244. pfn->params = *params;
  245. pfn->params.m = 1;
  246. pfn->head = function_ElIn_head;
  247. *ppfn = (gs_function_t *) pfn;
  248. }
  249. return 0;
  250. }
  251. /* ---------------- 1-Input Stitching functions ---------------- */
  252. typedef struct gs_function_1ItSg_s {
  253. gs_function_head_t head;
  254. gs_function_1ItSg_params_t params;
  255. } gs_function_1ItSg_t;
  256. private_st_function_1ItSg();
  257. /* Evaluate a 1-Input Stitching function. */
  258. private int
  259. fn_1ItSg_evaluate(const gs_function_t * pfn_common, const float *in, float *out)
  260. {
  261. const gs_function_1ItSg_t *const pfn =
  262. (const gs_function_1ItSg_t *)pfn_common;
  263. float arg = in[0], b0, b1, e0, encoded;
  264. int k = pfn->params.k;
  265. int i;
  266. if (arg < pfn->params.Domain[0]) {
  267. arg = pfn->params.Domain[0];
  268. i = 0;
  269. } else if (arg > pfn->params.Domain[1]) {
  270. arg = pfn->params.Domain[1];
  271. i = k - 1;
  272. } else {
  273. for (i = 0; i < k - 1; ++i)
  274. if (arg <= pfn->params.Bounds[i])
  275. break;
  276. }
  277. b0 = (i == 0 ? pfn->params.Domain[0] : pfn->params.Bounds[i - 1]);
  278. b1 = (i == k - 1 ? pfn->params.Domain[1] : pfn->params.Bounds[i]);
  279. e0 = pfn->params.Encode[2 * i];
  280. if (b1 == b0)
  281. encoded = e0;
  282. else
  283. encoded =
  284. (arg - b0) * (pfn->params.Encode[2 * i + 1] - e0) / (b1 - b0) + e0;
  285. if_debug3('~', "[~]1ItSg %g in %d => %g\n", arg, i, encoded);
  286. return gs_function_evaluate(pfn->params.Functions[i], &encoded, out);
  287. }
  288. /* Test whether a 1-Input Stitching function is monotonic. */
  289. private int
  290. fn_1ItSg_is_monotonic(const gs_function_t * pfn_common,
  291. const float *lower, const float *upper, uint *mask)
  292. {
  293. const gs_function_1ItSg_t *const pfn =
  294. (const gs_function_1ItSg_t *)pfn_common;
  295. float v0 = lower[0], v1 = upper[0];
  296. float d0 = pfn->params.Domain[0], d1 = pfn->params.Domain[1];
  297. int k = pfn->params.k;
  298. int i;
  299. *mask = 0;
  300. if (v0 > v1) {
  301. v0 = v1; v1 = lower[0];
  302. }
  303. if (v0 > d1 || v1 < d0)
  304. return_error(gs_error_rangecheck);
  305. if (v0 < d0)
  306. v0 = d0;
  307. if (v1 > d1)
  308. v1 = d1;
  309. for (i = 0; i < pfn->params.k; ++i) {
  310. float b0 = (i == 0 ? d0 : pfn->params.Bounds[i - 1]);
  311. float b1 = (i == k - 1 ? d1 : pfn->params.Bounds[i]);
  312. const float small = 0.0000001 * (b1 - b0);
  313. float e0, e1;
  314. float w0, w1;
  315. float vv0, vv1;
  316. double vb0, vb1;
  317. if (v0 >= b1)
  318. continue;
  319. if (v0 >= b1 - small)
  320. continue; /* Ignore a small noize */
  321. vv0 = max(b0, v0);
  322. vv1 = v1;
  323. if (vv1 > b1 && v1 < b1 + small)
  324. vv1 = b1; /* Ignore a small noize */
  325. if (vv0 == vv1)
  326. return 1;
  327. if (vv0 < b1 && vv1 > b1)
  328. return 0; /* Consider stitches as monotonity beraks. */
  329. e0 = pfn->params.Encode[2 * i];
  330. e1 = pfn->params.Encode[2 * i + 1];
  331. vb0 = max(vv0, b0);
  332. vb1 = min(vv1, b1);
  333. w0 = (float)(vb0 - b0) * (e1 - e0) / (b1 - b0) + e0;
  334. w1 = (float)(vb1 - b0) * (e1 - e0) / (b1 - b0) + e0;
  335. /* Note that w0 > w1 is now possible if e0 > e1. */
  336. if (e0 > e1) {
  337. if (w0 > e0 && w0 - small <= e0)
  338. w0 = e0; /* Suppress a small noize */
  339. if (w1 < e1 && w1 + small >= e1)
  340. w1 = e1; /* Suppress a small noize */
  341. } else {
  342. if (w0 < e0 && w0 + small >= e0)
  343. w0 = e0; /* Suppress a small noize */
  344. if (w1 > e1 && w1 - small <= e1)
  345. w1 = e1; /* Suppress a small noize */
  346. }
  347. if (w0 > w1)
  348. return gs_function_is_monotonic(pfn->params.Functions[i],
  349. &w1, &w0, mask);
  350. else
  351. return gs_function_is_monotonic(pfn->params.Functions[i],
  352. &w0, &w1, mask);
  353. }
  354. /* v0 is equal to the range end. */
  355. *mask = 0;
  356. return 1;
  357. }
  358. /* Return 1-Input Stitching function information. */
  359. private void
  360. fn_1ItSg_get_info(const gs_function_t *pfn_common, gs_function_info_t *pfi)
  361. {
  362. const gs_function_1ItSg_t *const pfn =
  363. (const gs_function_1ItSg_t *)pfn_common;
  364. gs_function_get_info_default(pfn_common, pfi);
  365. pfi->Functions = pfn->params.Functions;
  366. pfi->num_Functions = pfn->params.k;
  367. }
  368. /* Write 1-Input Stitching function parameters on a parameter list. */
  369. private int
  370. fn_1ItSg_get_params(const gs_function_t *pfn_common, gs_param_list *plist)
  371. {
  372. const gs_function_1ItSg_t *const pfn =
  373. (const gs_function_1ItSg_t *)pfn_common;
  374. int ecode = fn_common_get_params(pfn_common, plist);
  375. int code;
  376. if ((code = param_write_float_values(plist, "Bounds", pfn->params.Bounds,
  377. pfn->params.k - 1, false)) < 0)
  378. ecode = code;
  379. if ((code = param_write_float_values(plist, "Encode", pfn->params.Encode,
  380. 2 * pfn->params.k, false)) < 0)
  381. ecode = code;
  382. return ecode;
  383. }
  384. /* Make a scaled copy of a 1-Input Stitching function. */
  385. private int
  386. fn_1ItSg_make_scaled(const gs_function_1ItSg_t *pfn,
  387. gs_function_1ItSg_t **ppsfn,
  388. const gs_range_t *pranges, gs_memory_t *mem)
  389. {
  390. gs_function_1ItSg_t *psfn =
  391. gs_alloc_struct(mem, gs_function_1ItSg_t, &st_function_1ItSg,
  392. "fn_1ItSg_make_scaled");
  393. int code;
  394. if (psfn == 0)
  395. return_error(gs_error_VMerror);
  396. psfn->params = pfn->params;
  397. psfn->params.Functions = 0; /* in case of failure */
  398. psfn->params.Bounds =
  399. fn_copy_values(pfn->params.Bounds, pfn->params.k - 1, sizeof(float),
  400. mem);
  401. psfn->params.Encode =
  402. fn_copy_values(pfn->params.Encode, 2 * pfn->params.k, sizeof(float),
  403. mem);
  404. if ((code = (psfn->params.Bounds == 0 || psfn->params.Encode == 0 ?
  405. gs_note_error(gs_error_VMerror) : 0)) < 0 ||
  406. (code = fn_common_scale((gs_function_t *)psfn,
  407. (const gs_function_t *)pfn,
  408. pranges, mem)) < 0 ||
  409. (code = fn_scale_functions((gs_function_t ***)&psfn->params.Functions,
  410. pfn->params.Functions,
  411. pfn->params.n, pranges, false, mem)) < 0) {
  412. gs_function_free((gs_function_t *)psfn, true, mem);
  413. return code;
  414. }
  415. *ppsfn = psfn;
  416. return 0;
  417. }
  418. /* Free the parameters of a 1-Input Stitching function. */
  419. void
  420. gs_function_1ItSg_free_params(gs_function_1ItSg_params_t * params,
  421. gs_memory_t * mem)
  422. {
  423. gs_free_const_object(mem, params->Encode, "Encode");
  424. gs_free_const_object(mem, params->Bounds, "Bounds");
  425. fn_free_functions(params->Functions, params->k, mem);
  426. fn_common_free_params((gs_function_params_t *) params, mem);
  427. }
  428. /* Serialize. */
  429. private int
  430. gs_function_1ItSg_serialize(const gs_function_t * pfn, stream *s)
  431. {
  432. uint n;
  433. const gs_function_1ItSg_params_t * p = (const gs_function_1ItSg_params_t *)&pfn->params;
  434. int code = fn_common_serialize(pfn, s);
  435. int k;
  436. if (code < 0)
  437. return code;
  438. code = sputs(s, (const byte *)&p->k, sizeof(p->k), &n);
  439. if (code < 0)
  440. return code;
  441. for (k = 0; k < p->k && code >= 0; k++)
  442. code = gs_function_serialize(p->Functions[k], s);
  443. if (code < 0)
  444. return code;
  445. code = sputs(s, (const byte *)&p->Bounds[0], sizeof(p->Bounds[0]) * (p->k - 1), &n);
  446. if (code < 0)
  447. return code;
  448. return sputs(s, (const byte *)&p->Encode[0], sizeof(p->Encode[0]) * (p->k * 2), &n);
  449. }
  450. /* Allocate and initialize a 1-Input Stitching function. */
  451. int
  452. gs_function_1ItSg_init(gs_function_t ** ppfn,
  453. const gs_function_1ItSg_params_t * params, gs_memory_t * mem)
  454. {
  455. static const gs_function_head_t function_1ItSg_head = {
  456. function_type_1InputStitching,
  457. {
  458. (fn_evaluate_proc_t) fn_1ItSg_evaluate,
  459. (fn_is_monotonic_proc_t) fn_1ItSg_is_monotonic,
  460. (fn_get_info_proc_t) fn_1ItSg_get_info,
  461. (fn_get_params_proc_t) fn_1ItSg_get_params,
  462. (fn_make_scaled_proc_t) fn_1ItSg_make_scaled,
  463. (fn_free_params_proc_t) gs_function_1ItSg_free_params,
  464. fn_common_free,
  465. (fn_serialize_proc_t) gs_function_1ItSg_serialize,
  466. }
  467. };
  468. int n = (params->Range == 0 ? 0 : params->n);
  469. float prev = params->Domain[0];
  470. int i;
  471. *ppfn = 0; /* in case of error */
  472. for (i = 0; i < params->k; ++i) {
  473. const gs_function_t *psubfn = params->Functions[i];
  474. if (psubfn->params.m != 1)
  475. return_error(gs_error_rangecheck);
  476. if (n == 0)
  477. n = psubfn->params.n;
  478. else if (psubfn->params.n != n)
  479. return_error(gs_error_rangecheck);
  480. /* There are only k - 1 Bounds, not k. */
  481. if (i < params->k - 1) {
  482. if (params->Bounds[i] < prev)
  483. return_error(gs_error_rangecheck);
  484. prev = params->Bounds[i];
  485. }
  486. }
  487. if (params->Domain[1] < prev)
  488. return_error(gs_error_rangecheck);
  489. fn_check_mnDR((const gs_function_params_t *)params, 1, n);
  490. {
  491. gs_function_1ItSg_t *pfn =
  492. gs_alloc_struct(mem, gs_function_1ItSg_t, &st_function_1ItSg,
  493. "gs_function_1ItSg_init");
  494. if (pfn == 0)
  495. return_error(gs_error_VMerror);
  496. pfn->params = *params;
  497. pfn->params.m = 1;
  498. pfn->params.n = n;
  499. pfn->head = function_1ItSg_head;
  500. *ppfn = (gs_function_t *) pfn;
  501. }
  502. return 0;
  503. }
  504. /* ---------------- Arrayed Output functions ---------------- */
  505. typedef struct gs_function_AdOt_s {
  506. gs_function_head_t head;
  507. gs_function_AdOt_params_t params;
  508. } gs_function_AdOt_t;
  509. private_st_function_AdOt();
  510. /* Evaluate an Arrayed Output function. */
  511. private int
  512. fn_AdOt_evaluate(const gs_function_t *pfn_common, const float *in0, float *out)
  513. {
  514. const gs_function_AdOt_t *const pfn =
  515. (const gs_function_AdOt_t *)pfn_common;
  516. const float *in = in0;
  517. #define MAX_ADOT_IN 16
  518. float in_buf[MAX_ADOT_IN];
  519. int i;
  520. /*
  521. * We have to take special care to handle the case where in and out
  522. * overlap. For the moment, handle it only for a limited number of
  523. * input values.
  524. */
  525. if (in <= out + (pfn->params.n - 1) && out <= in + (pfn->params.m - 1)) {
  526. if (pfn->params.m > MAX_ADOT_IN)
  527. return_error(gs_error_rangecheck);
  528. memcpy(in_buf, in, pfn->params.m * sizeof(*in));
  529. in = in_buf;
  530. }
  531. for (i = 0; i < pfn->params.n; ++i) {
  532. int code =
  533. gs_function_evaluate(pfn->params.Functions[i], in, out + i);
  534. if (code < 0)
  535. return code;
  536. }
  537. return 0;
  538. #undef MAX_ADOT_IN
  539. }
  540. /* Test whether an Arrayed Output function is monotonic. */
  541. private int
  542. fn_AdOt_is_monotonic(const gs_function_t * pfn_common,
  543. const float *lower, const float *upper, uint *mask)
  544. {
  545. const gs_function_AdOt_t *const pfn =
  546. (const gs_function_AdOt_t *)pfn_common;
  547. int i;
  548. for (i = 0; i < pfn->params.n; ++i) {
  549. int code =
  550. gs_function_is_monotonic(pfn->params.Functions[i], lower, upper, mask);
  551. if (code <= 0)
  552. return code;
  553. }
  554. return 1;
  555. }
  556. /* Return Arrayed Output function information. */
  557. private void
  558. fn_AdOt_get_info(const gs_function_t *pfn_common, gs_function_info_t *pfi)
  559. {
  560. const gs_function_AdOt_t *const pfn =
  561. (const gs_function_AdOt_t *)pfn_common;
  562. gs_function_get_info_default(pfn_common, pfi);
  563. pfi->Functions = pfn->params.Functions;
  564. pfi->num_Functions = pfn->params.n;
  565. }
  566. /* Make a scaled copy of an Arrayed Output function. */
  567. private int
  568. fn_AdOt_make_scaled(const gs_function_AdOt_t *pfn, gs_function_AdOt_t **ppsfn,
  569. const gs_range_t *pranges, gs_memory_t *mem)
  570. {
  571. gs_function_AdOt_t *psfn =
  572. gs_alloc_struct(mem, gs_function_AdOt_t, &st_function_AdOt,
  573. "fn_AdOt_make_scaled");
  574. int code;
  575. if (psfn == 0)
  576. return_error(gs_error_VMerror);
  577. psfn->params = pfn->params;
  578. psfn->params.Functions = 0; /* in case of failure */
  579. if ((code = fn_common_scale((gs_function_t *)psfn,
  580. (const gs_function_t *)pfn,
  581. pranges, mem)) < 0 ||
  582. (code = fn_scale_functions((gs_function_t ***)&psfn->params.Functions,
  583. pfn->params.Functions,
  584. pfn->params.n, pranges, true, mem)) < 0) {
  585. gs_function_free((gs_function_t *)psfn, true, mem);
  586. return code;
  587. }
  588. *ppsfn = psfn;
  589. return 0;
  590. }
  591. /* Free the parameters of an Arrayed Output function. */
  592. void
  593. gs_function_AdOt_free_params(gs_function_AdOt_params_t * params,
  594. gs_memory_t * mem)
  595. {
  596. fn_free_functions(params->Functions, params->n, mem);
  597. fn_common_free_params((gs_function_params_t *) params, mem);
  598. }
  599. /* Serialize. */
  600. private int
  601. gs_function_AdOt_serialize(const gs_function_t * pfn, stream *s)
  602. {
  603. const gs_function_AdOt_params_t * p = (const gs_function_AdOt_params_t *)&pfn->params;
  604. int code = fn_common_serialize(pfn, s);
  605. int k;
  606. if (code < 0)
  607. return code;
  608. for (k = 0; k < p->n && code >= 0; k++)
  609. code = gs_function_serialize(p->Functions[k], s);
  610. return code;
  611. }
  612. /* Allocate and initialize an Arrayed Output function. */
  613. int
  614. gs_function_AdOt_init(gs_function_t ** ppfn,
  615. const gs_function_AdOt_params_t * params, gs_memory_t * mem)
  616. {
  617. static const gs_function_head_t function_AdOt_head = {
  618. function_type_ArrayedOutput,
  619. {
  620. (fn_evaluate_proc_t) fn_AdOt_evaluate,
  621. (fn_is_monotonic_proc_t) fn_AdOt_is_monotonic,
  622. (fn_get_info_proc_t) fn_AdOt_get_info,
  623. fn_common_get_params, /****** WHAT TO DO ABOUT THIS? ******/
  624. (fn_make_scaled_proc_t) fn_AdOt_make_scaled,
  625. (fn_free_params_proc_t) gs_function_AdOt_free_params,
  626. fn_common_free,
  627. (fn_serialize_proc_t) gs_function_AdOt_serialize,
  628. }
  629. };
  630. int m = params->m, n = params->n;
  631. *ppfn = 0; /* in case of error */
  632. if (m <= 0 || n <= 0)
  633. return_error(gs_error_rangecheck);
  634. {
  635. gs_function_AdOt_t *pfn =
  636. gs_alloc_struct(mem, gs_function_AdOt_t, &st_function_AdOt,
  637. "gs_function_AdOt_init");
  638. float *domain = (float *)
  639. gs_alloc_byte_array(mem, 2 * m, sizeof(float),
  640. "gs_function_AdOt_init(Domain)");
  641. int i, j;
  642. if (pfn == 0)
  643. return_error(gs_error_VMerror);
  644. pfn->params = *params;
  645. pfn->params.Domain = domain;
  646. pfn->params.Range = 0;
  647. pfn->head = function_AdOt_head;
  648. if (domain == 0) {
  649. gs_function_free((gs_function_t *)pfn, true, mem);
  650. return_error(gs_error_VMerror);
  651. }
  652. /*
  653. * We compute the Domain as the intersection of the Domains of
  654. * the individual subfunctions. This isn't quite right: some
  655. * subfunction might actually make use of a larger domain of
  656. * input values. However, the only place that Arrayed Output
  657. * functions are used is in Shading and similar dictionaries,
  658. * where the input values are clamped to the intersection of
  659. * the individual Domains anyway.
  660. */
  661. memcpy(domain, params->Functions[0]->params.Domain,
  662. 2 * sizeof(float) * m);
  663. for (i = 1; i < n; ++i) {
  664. const float *dom = params->Functions[i]->params.Domain;
  665. for (j = 0; j < 2 * m; j += 2, dom += 2) {
  666. domain[j] = max(domain[j], dom[0]);
  667. domain[j + 1] = min(domain[j + 1], dom[1]);
  668. }
  669. }
  670. *ppfn = (gs_function_t *) pfn;
  671. }
  672. return 0;
  673. }