function_spec.js 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645
  1. /**
  2. * @licstart The following is the entire license notice for the
  3. * Javascript code in this page
  4. *
  5. * Copyright 2021 Mozilla Foundation
  6. *
  7. * Licensed under the Apache License, Version 2.0 (the "License");
  8. * you may not use this file except in compliance with the License.
  9. * You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing, software
  14. * distributed under the License is distributed on an "AS IS" BASIS,
  15. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16. * See the License for the specific language governing permissions and
  17. * limitations under the License.
  18. *
  19. * @licend The above is the entire license notice for the
  20. * Javascript code in this page
  21. */
  22. "use strict";
  23. var _function = require("../../core/function.js");
  24. var _ps_parser = require("../../core/ps_parser.js");
  25. var _stream = require("../../core/stream.js");
  26. describe("function", function () {
  27. beforeEach(function () {
  28. jasmine.addMatchers({
  29. toMatchArray(util, customEqualityTesters) {
  30. return {
  31. compare(actual, expected) {
  32. const result = {};
  33. if (actual.length !== expected.length) {
  34. result.pass = false;
  35. result.message = "Array length: " + actual.length + ", expected: " + expected.length;
  36. return result;
  37. }
  38. result.pass = true;
  39. for (let i = 0; i < expected.length; i++) {
  40. const a = actual[i],
  41. b = expected[i];
  42. if (Array.isArray(b)) {
  43. if (a.length !== b.length) {
  44. result.pass = false;
  45. break;
  46. }
  47. for (let j = 0; j < a.length; j++) {
  48. const suba = a[j],
  49. subb = b[j];
  50. if (suba !== subb) {
  51. result.pass = false;
  52. break;
  53. }
  54. }
  55. } else {
  56. if (a !== b) {
  57. result.pass = false;
  58. break;
  59. }
  60. }
  61. }
  62. return result;
  63. }
  64. };
  65. }
  66. });
  67. });
  68. describe("PostScriptParser", function () {
  69. function parse(program) {
  70. const stream = new _stream.StringStream(program);
  71. const parser = new _ps_parser.PostScriptParser(new _ps_parser.PostScriptLexer(stream));
  72. return parser.parse();
  73. }
  74. it("parses empty programs", function () {
  75. const output = parse("{}");
  76. expect(output.length).toEqual(0);
  77. });
  78. it("parses positive numbers", function () {
  79. const number = 999;
  80. const program = parse("{ " + number + " }");
  81. const expectedProgram = [number];
  82. expect(program).toMatchArray(expectedProgram);
  83. });
  84. it("parses negative numbers", function () {
  85. const number = -999;
  86. const program = parse("{ " + number + " }");
  87. const expectedProgram = [number];
  88. expect(program).toMatchArray(expectedProgram);
  89. });
  90. it("parses negative floats", function () {
  91. const number = 3.3;
  92. const program = parse("{ " + number + " }");
  93. const expectedProgram = [number];
  94. expect(program).toMatchArray(expectedProgram);
  95. });
  96. it("parses operators", function () {
  97. const program = parse("{ sub }");
  98. const expectedProgram = ["sub"];
  99. expect(program).toMatchArray(expectedProgram);
  100. });
  101. it("parses if statements", function () {
  102. const program = parse("{ { 99 } if }");
  103. const expectedProgram = [3, "jz", 99];
  104. expect(program).toMatchArray(expectedProgram);
  105. });
  106. it("parses ifelse statements", function () {
  107. const program = parse("{ { 99 } { 44 } ifelse }");
  108. const expectedProgram = [5, "jz", 99, 6, "j", 44];
  109. expect(program).toMatchArray(expectedProgram);
  110. });
  111. it("handles missing brackets", function () {
  112. expect(function () {
  113. parse("{");
  114. }).toThrow(new Error("Unexpected symbol: found undefined expected 1."));
  115. });
  116. it("handles junk after the end", function () {
  117. const number = 3.3;
  118. const program = parse("{ " + number + " }#");
  119. const expectedProgram = [number];
  120. expect(program).toMatchArray(expectedProgram);
  121. });
  122. });
  123. describe("PostScriptEvaluator", function () {
  124. function evaluate(program) {
  125. const stream = new _stream.StringStream(program);
  126. const parser = new _ps_parser.PostScriptParser(new _ps_parser.PostScriptLexer(stream));
  127. const code = parser.parse();
  128. const evaluator = new _function.PostScriptEvaluator(code);
  129. const output = evaluator.execute();
  130. return output;
  131. }
  132. it("pushes stack", function () {
  133. const stack = evaluate("{ 99 }");
  134. const expectedStack = [99];
  135. expect(stack).toMatchArray(expectedStack);
  136. });
  137. it("handles if with true", function () {
  138. const stack = evaluate("{ 1 {99} if }");
  139. const expectedStack = [99];
  140. expect(stack).toMatchArray(expectedStack);
  141. });
  142. it("handles if with false", function () {
  143. const stack = evaluate("{ 0 {99} if }");
  144. const expectedStack = [];
  145. expect(stack).toMatchArray(expectedStack);
  146. });
  147. it("handles ifelse with true", function () {
  148. const stack = evaluate("{ 1 {99} {77} ifelse }");
  149. const expectedStack = [99];
  150. expect(stack).toMatchArray(expectedStack);
  151. });
  152. it("handles ifelse with false", function () {
  153. const stack = evaluate("{ 0 {99} {77} ifelse }");
  154. const expectedStack = [77];
  155. expect(stack).toMatchArray(expectedStack);
  156. });
  157. it("handles nested if", function () {
  158. const stack = evaluate("{ 1 {1 {77} if} if }");
  159. const expectedStack = [77];
  160. expect(stack).toMatchArray(expectedStack);
  161. });
  162. it("abs", function () {
  163. const stack = evaluate("{ -2 abs }");
  164. const expectedStack = [2];
  165. expect(stack).toMatchArray(expectedStack);
  166. });
  167. it("adds", function () {
  168. const stack = evaluate("{ 1 2 add }");
  169. const expectedStack = [3];
  170. expect(stack).toMatchArray(expectedStack);
  171. });
  172. it("boolean and", function () {
  173. const stack = evaluate("{ true false and }");
  174. const expectedStack = [false];
  175. expect(stack).toMatchArray(expectedStack);
  176. });
  177. it("bitwise and", function () {
  178. const stack = evaluate("{ 254 1 and }");
  179. const expectedStack = [254 & 1];
  180. expect(stack).toMatchArray(expectedStack);
  181. });
  182. it("calculates the inverse tangent of a number", function () {
  183. const stack = evaluate("{ 90 atan }");
  184. const expectedStack = [Math.atan(90)];
  185. expect(stack).toMatchArray(expectedStack);
  186. });
  187. it("handles bitshifting ", function () {
  188. const stack = evaluate("{ 50 2 bitshift }");
  189. const expectedStack = [200];
  190. expect(stack).toMatchArray(expectedStack);
  191. });
  192. it("calculates the ceiling value", function () {
  193. const stack = evaluate("{ 9.9 ceiling }");
  194. const expectedStack = [10];
  195. expect(stack).toMatchArray(expectedStack);
  196. });
  197. it("copies", function () {
  198. const stack = evaluate("{ 99 98 2 copy }");
  199. const expectedStack = [99, 98, 99, 98];
  200. expect(stack).toMatchArray(expectedStack);
  201. });
  202. it("calculates the cosine of a number", function () {
  203. const stack = evaluate("{ 90 cos }");
  204. const expectedStack = [Math.cos(90)];
  205. expect(stack).toMatchArray(expectedStack);
  206. });
  207. it("converts to int", function () {
  208. const stack = evaluate("{ 9.9 cvi }");
  209. const expectedStack = [9];
  210. expect(stack).toMatchArray(expectedStack);
  211. });
  212. it("converts negatives to int", function () {
  213. const stack = evaluate("{ -9.9 cvi }");
  214. const expectedStack = [-9];
  215. expect(stack).toMatchArray(expectedStack);
  216. });
  217. it("converts to real", function () {
  218. const stack = evaluate("{ 55.34 cvr }");
  219. const expectedStack = [55.34];
  220. expect(stack).toMatchArray(expectedStack);
  221. });
  222. it("divides", function () {
  223. const stack = evaluate("{ 6 5 div }");
  224. const expectedStack = [1.2];
  225. expect(stack).toMatchArray(expectedStack);
  226. });
  227. it("maps division by zero to infinity", function () {
  228. const stack = evaluate("{ 6 0 div }");
  229. const expectedStack = [Infinity];
  230. expect(stack).toMatchArray(expectedStack);
  231. });
  232. it("duplicates", function () {
  233. const stack = evaluate("{ 99 dup }");
  234. const expectedStack = [99, 99];
  235. expect(stack).toMatchArray(expectedStack);
  236. });
  237. it("accepts an equality", function () {
  238. const stack = evaluate("{ 9 9 eq }");
  239. const expectedStack = [true];
  240. expect(stack).toMatchArray(expectedStack);
  241. });
  242. it("rejects an inequality", function () {
  243. const stack = evaluate("{ 9 8 eq }");
  244. const expectedStack = [false];
  245. expect(stack).toMatchArray(expectedStack);
  246. });
  247. it("exchanges", function () {
  248. const stack = evaluate("{ 44 99 exch }");
  249. const expectedStack = [99, 44];
  250. expect(stack).toMatchArray(expectedStack);
  251. });
  252. it("handles exponentiation", function () {
  253. const stack = evaluate("{ 10 2 exp }");
  254. const expectedStack = [100];
  255. expect(stack).toMatchArray(expectedStack);
  256. });
  257. it("pushes false onto the stack", function () {
  258. const stack = evaluate("{ false }");
  259. const expectedStack = [false];
  260. expect(stack).toMatchArray(expectedStack);
  261. });
  262. it("calculates the floor value", function () {
  263. const stack = evaluate("{ 9.9 floor }");
  264. const expectedStack = [9];
  265. expect(stack).toMatchArray(expectedStack);
  266. });
  267. it("handles greater than or equal to", function () {
  268. const stack = evaluate("{ 10 9 ge }");
  269. const expectedStack = [true];
  270. expect(stack).toMatchArray(expectedStack);
  271. });
  272. it("rejects less than for greater than or equal to", function () {
  273. const stack = evaluate("{ 8 9 ge }");
  274. const expectedStack = [false];
  275. expect(stack).toMatchArray(expectedStack);
  276. });
  277. it("handles greater than", function () {
  278. const stack = evaluate("{ 10 9 gt }");
  279. const expectedStack = [true];
  280. expect(stack).toMatchArray(expectedStack);
  281. });
  282. it("rejects less than or equal for greater than", function () {
  283. const stack = evaluate("{ 9 9 gt }");
  284. const expectedStack = [false];
  285. expect(stack).toMatchArray(expectedStack);
  286. });
  287. it("divides to integer", function () {
  288. const stack = evaluate("{ 2 3 idiv }");
  289. const expectedStack = [0];
  290. expect(stack).toMatchArray(expectedStack);
  291. });
  292. it("divides to negative integer", function () {
  293. const stack = evaluate("{ -2 3 idiv }");
  294. const expectedStack = [0];
  295. expect(stack).toMatchArray(expectedStack);
  296. });
  297. it("duplicates index", function () {
  298. const stack = evaluate("{ 4 3 2 1 2 index }");
  299. const expectedStack = [4, 3, 2, 1, 3];
  300. expect(stack).toMatchArray(expectedStack);
  301. });
  302. it("handles less than or equal to", function () {
  303. const stack = evaluate("{ 9 10 le }");
  304. const expectedStack = [true];
  305. expect(stack).toMatchArray(expectedStack);
  306. });
  307. it("rejects greater than for less than or equal to", function () {
  308. const stack = evaluate("{ 10 9 le }");
  309. const expectedStack = [false];
  310. expect(stack).toMatchArray(expectedStack);
  311. });
  312. it("calculates the natural logarithm", function () {
  313. const stack = evaluate("{ 10 ln }");
  314. const expectedStack = [Math.log(10)];
  315. expect(stack).toMatchArray(expectedStack);
  316. });
  317. it("calculates the base 10 logarithm", function () {
  318. const stack = evaluate("{ 100 log }");
  319. const expectedStack = [2];
  320. expect(stack).toMatchArray(expectedStack);
  321. });
  322. it("handles less than", function () {
  323. const stack = evaluate("{ 9 10 lt }");
  324. const expectedStack = [true];
  325. expect(stack).toMatchArray(expectedStack);
  326. });
  327. it("rejects greater than or equal to for less than", function () {
  328. const stack = evaluate("{ 10 9 lt }");
  329. const expectedStack = [false];
  330. expect(stack).toMatchArray(expectedStack);
  331. });
  332. it("performs the modulo operation", function () {
  333. const stack = evaluate("{ 4 3 mod }");
  334. const expectedStack = [1];
  335. expect(stack).toMatchArray(expectedStack);
  336. });
  337. it("multiplies two numbers (positive result)", function () {
  338. const stack = evaluate("{ 9 8 mul }");
  339. const expectedStack = [72];
  340. expect(stack).toMatchArray(expectedStack);
  341. });
  342. it("multiplies two numbers (negative result)", function () {
  343. const stack = evaluate("{ 9 -8 mul }");
  344. const expectedStack = [-72];
  345. expect(stack).toMatchArray(expectedStack);
  346. });
  347. it("accepts an inequality", function () {
  348. const stack = evaluate("{ 9 8 ne }");
  349. const expectedStack = [true];
  350. expect(stack).toMatchArray(expectedStack);
  351. });
  352. it("rejects an equality", function () {
  353. const stack = evaluate("{ 9 9 ne }");
  354. const expectedStack = [false];
  355. expect(stack).toMatchArray(expectedStack);
  356. });
  357. it("negates", function () {
  358. const stack = evaluate("{ 4.5 neg }");
  359. const expectedStack = [-4.5];
  360. expect(stack).toMatchArray(expectedStack);
  361. });
  362. it("boolean not", function () {
  363. const stack = evaluate("{ true not }");
  364. const expectedStack = [false];
  365. expect(stack).toMatchArray(expectedStack);
  366. });
  367. it("bitwise not", function () {
  368. const stack = evaluate("{ 12 not }");
  369. const expectedStack = [-13];
  370. expect(stack).toMatchArray(expectedStack);
  371. });
  372. it("boolean or", function () {
  373. const stack = evaluate("{ true false or }");
  374. const expectedStack = [true];
  375. expect(stack).toMatchArray(expectedStack);
  376. });
  377. it("bitwise or", function () {
  378. const stack = evaluate("{ 254 1 or }");
  379. const expectedStack = [254 | 1];
  380. expect(stack).toMatchArray(expectedStack);
  381. });
  382. it("pops stack", function () {
  383. const stack = evaluate("{ 1 2 pop }");
  384. const expectedStack = [1];
  385. expect(stack).toMatchArray(expectedStack);
  386. });
  387. it("rolls stack right", function () {
  388. const stack = evaluate("{ 1 3 2 2 4 1 roll }");
  389. const expectedStack = [2, 1, 3, 2];
  390. expect(stack).toMatchArray(expectedStack);
  391. });
  392. it("rolls stack left", function () {
  393. const stack = evaluate("{ 1 3 2 2 4 -1 roll }");
  394. const expectedStack = [3, 2, 2, 1];
  395. expect(stack).toMatchArray(expectedStack);
  396. });
  397. it("rounds a number", function () {
  398. const stack = evaluate("{ 9.52 round }");
  399. const expectedStack = [10];
  400. expect(stack).toMatchArray(expectedStack);
  401. });
  402. it("calculates the sine of a number", function () {
  403. const stack = evaluate("{ 90 sin }");
  404. const expectedStack = [Math.sin(90)];
  405. expect(stack).toMatchArray(expectedStack);
  406. });
  407. it("calculates a square root (integer)", function () {
  408. const stack = evaluate("{ 100 sqrt }");
  409. const expectedStack = [10];
  410. expect(stack).toMatchArray(expectedStack);
  411. });
  412. it("calculates a square root (float)", function () {
  413. const stack = evaluate("{ 99 sqrt }");
  414. const expectedStack = [Math.sqrt(99)];
  415. expect(stack).toMatchArray(expectedStack);
  416. });
  417. it("subtracts (positive result)", function () {
  418. const stack = evaluate("{ 6 4 sub }");
  419. const expectedStack = [2];
  420. expect(stack).toMatchArray(expectedStack);
  421. });
  422. it("subtracts (negative result)", function () {
  423. const stack = evaluate("{ 4 6 sub }");
  424. const expectedStack = [-2];
  425. expect(stack).toMatchArray(expectedStack);
  426. });
  427. it("pushes true onto the stack", function () {
  428. const stack = evaluate("{ true }");
  429. const expectedStack = [true];
  430. expect(stack).toMatchArray(expectedStack);
  431. });
  432. it("truncates a number", function () {
  433. const stack = evaluate("{ 35.004 truncate }");
  434. const expectedStack = [35];
  435. expect(stack).toMatchArray(expectedStack);
  436. });
  437. it("calculates an exclusive or value", function () {
  438. const stack = evaluate("{ 3 9 xor }");
  439. const expectedStack = [10];
  440. expect(stack).toMatchArray(expectedStack);
  441. });
  442. });
  443. describe("PostScriptCompiler", function () {
  444. function check(code, domain, range, samples) {
  445. const compiler = new _function.PostScriptCompiler();
  446. const compiledCode = compiler.compile(code, domain, range);
  447. if (samples === null) {
  448. expect(compiledCode).toBeNull();
  449. } else {
  450. expect(compiledCode).not.toBeNull();
  451. const fn = new Function("src", "srcOffset", "dest", "destOffset", compiledCode);
  452. for (let i = 0; i < samples.length; i++) {
  453. const out = new Float32Array(samples[i].output.length);
  454. fn(samples[i].input, 0, out, 0);
  455. expect(Array.prototype.slice.call(out, 0)).toMatchArray(samples[i].output);
  456. }
  457. }
  458. }
  459. it("check compiled add", function () {
  460. check([0.25, 0.5, "add"], [], [0, 1], [{
  461. input: [],
  462. output: [0.75]
  463. }]);
  464. check([0, "add"], [0, 1], [0, 1], [{
  465. input: [0.25],
  466. output: [0.25]
  467. }]);
  468. check([0.5, "add"], [0, 1], [0, 1], [{
  469. input: [0.25],
  470. output: [0.75]
  471. }]);
  472. check([0, "exch", "add"], [0, 1], [0, 1], [{
  473. input: [0.25],
  474. output: [0.25]
  475. }]);
  476. check([0.5, "exch", "add"], [0, 1], [0, 1], [{
  477. input: [0.25],
  478. output: [0.75]
  479. }]);
  480. check(["add"], [0, 1, 0, 1], [0, 1], [{
  481. input: [0.25, 0.5],
  482. output: [0.75]
  483. }]);
  484. check(["add"], [0, 1], [0, 1], null);
  485. });
  486. it("check compiled sub", function () {
  487. check([0.5, 0.25, "sub"], [], [0, 1], [{
  488. input: [],
  489. output: [0.25]
  490. }]);
  491. check([0, "sub"], [0, 1], [0, 1], [{
  492. input: [0.25],
  493. output: [0.25]
  494. }]);
  495. check([0.5, "sub"], [0, 1], [0, 1], [{
  496. input: [0.75],
  497. output: [0.25]
  498. }]);
  499. check([0, "exch", "sub"], [0, 1], [-1, 1], [{
  500. input: [0.25],
  501. output: [-0.25]
  502. }]);
  503. check([0.75, "exch", "sub"], [0, 1], [-1, 1], [{
  504. input: [0.25],
  505. output: [0.5]
  506. }]);
  507. check(["sub"], [0, 1, 0, 1], [-1, 1], [{
  508. input: [0.25, 0.5],
  509. output: [-0.25]
  510. }]);
  511. check(["sub"], [0, 1], [0, 1], null);
  512. check([1, "dup", 3, 2, "roll", "sub", "sub"], [0, 1], [0, 1], [{
  513. input: [0.75],
  514. output: [0.75]
  515. }]);
  516. });
  517. it("check compiled mul", function () {
  518. check([0.25, 0.5, "mul"], [], [0, 1], [{
  519. input: [],
  520. output: [0.125]
  521. }]);
  522. check([0, "mul"], [0, 1], [0, 1], [{
  523. input: [0.25],
  524. output: [0]
  525. }]);
  526. check([0.5, "mul"], [0, 1], [0, 1], [{
  527. input: [0.25],
  528. output: [0.125]
  529. }]);
  530. check([1, "mul"], [0, 1], [0, 1], [{
  531. input: [0.25],
  532. output: [0.25]
  533. }]);
  534. check([0, "exch", "mul"], [0, 1], [0, 1], [{
  535. input: [0.25],
  536. output: [0]
  537. }]);
  538. check([0.5, "exch", "mul"], [0, 1], [0, 1], [{
  539. input: [0.25],
  540. output: [0.125]
  541. }]);
  542. check([1, "exch", "mul"], [0, 1], [0, 1], [{
  543. input: [0.25],
  544. output: [0.25]
  545. }]);
  546. check(["mul"], [0, 1, 0, 1], [0, 1], [{
  547. input: [0.25, 0.5],
  548. output: [0.125]
  549. }]);
  550. check(["mul"], [0, 1], [0, 1], null);
  551. });
  552. it("check compiled max", function () {
  553. check(["dup", 0.75, "gt", 7, "jz", "pop", 0.75], [0, 1], [0, 1], [{
  554. input: [0.5],
  555. output: [0.5]
  556. }]);
  557. check(["dup", 0.75, "gt", 7, "jz", "pop", 0.75], [0, 1], [0, 1], [{
  558. input: [1],
  559. output: [0.75]
  560. }]);
  561. check(["dup", 0.75, "gt", 5, "jz", "pop", 0.75], [0, 1], [0, 1], null);
  562. });
  563. it("check pop/roll/index", function () {
  564. check([1, "pop"], [0, 1], [0, 1], [{
  565. input: [0.5],
  566. output: [0.5]
  567. }]);
  568. check([1, 3, -1, "roll"], [0, 1, 0, 1], [0, 1, 0, 1, 0, 1], [{
  569. input: [0.25, 0.5],
  570. output: [0.5, 1, 0.25]
  571. }]);
  572. check([1, 3, 1, "roll"], [0, 1, 0, 1], [0, 1, 0, 1, 0, 1], [{
  573. input: [0.25, 0.5],
  574. output: [1, 0.25, 0.5]
  575. }]);
  576. check([1, 3, 1.5, "roll"], [0, 1, 0, 1], [0, 1, 0, 1, 0, 1], null);
  577. check([1, 1, "index"], [0, 1], [0, 1, 0, 1, 0, 1], [{
  578. input: [0.5],
  579. output: [0.5, 1, 0.5]
  580. }]);
  581. check([1, 3, "index", "pop"], [0, 1], [0, 1], null);
  582. check([1, 0.5, "index", "pop"], [0, 1], [0, 1], null);
  583. });
  584. it("check input boundaries", function () {
  585. check([], [0, 0.5], [0, 1], [{
  586. input: [1],
  587. output: [0.5]
  588. }]);
  589. check([], [0.5, 1], [0, 1], [{
  590. input: [0],
  591. output: [0.5]
  592. }]);
  593. check(["dup"], [0.5, 0.75], [0, 1, 0, 1], [{
  594. input: [0],
  595. output: [0.5, 0.5]
  596. }]);
  597. check([], [100, 1001], [0, 10000], [{
  598. input: [1000],
  599. output: [1000]
  600. }]);
  601. });
  602. it("check output boundaries", function () {
  603. check([], [0, 1], [0, 0.5], [{
  604. input: [1],
  605. output: [0.5]
  606. }]);
  607. check([], [0, 1], [0.5, 1], [{
  608. input: [0],
  609. output: [0.5]
  610. }]);
  611. check(["dup"], [0, 1], [0.5, 1, 0.75, 1], [{
  612. input: [0],
  613. output: [0.5, 0.75]
  614. }]);
  615. check([], [0, 10000], [100, 1001], [{
  616. input: [1000],
  617. output: [1000]
  618. }]);
  619. });
  620. it("compile optimized", function () {
  621. const compiler = new _function.PostScriptCompiler();
  622. const code = [0, "add", 1, 1, 3, -1, "roll", "sub", "sub", 1, "mul"];
  623. const compiledCode = compiler.compile(code, [0, 1], [0, 1]);
  624. expect(compiledCode).toEqual("dest[destOffset + 0] = Math.max(0, Math.min(1, src[srcOffset + 0]));");
  625. });
  626. });
  627. });