diff --git a/src/shared/function.js b/src/shared/function.js index 1ece43f91..630b20356 100644 --- a/src/shared/function.js +++ b/src/shared/function.js @@ -659,14 +659,14 @@ var PostScriptEvaluator = (function PostScriptEvaluatorClosure() { break; case 'neg': a = stack.pop(); - stack.push(-b); + stack.push(-a); break; case 'not': a = stack.pop(); - if (isBool(a) && isBool(b)) { - stack.push(a && b); + if (isBool(a)) { + stack.push(!a); } else { - stack.push(a & b); + stack.push(~a); } break; case 'or': diff --git a/test/unit/function_spec.js b/test/unit/function_spec.js index 10d0a38c1..fb6912311 100644 --- a/test/unit/function_spec.js +++ b/test/unit/function_spec.js @@ -81,7 +81,7 @@ describe('function', function() { }); it('handles missing brackets', function() { expect(function() { parse('{'); }).toThrow( - new Error('Unexpected symbol: found undefined expected 1.')); + new Error('Unexpected symbol: found undefined expected 1.')); }); it('handles junk after the end', function() { var number = 3.3; @@ -142,21 +142,41 @@ describe('function', function() { var expectedStack = [3]; expect(stack).toMatchArray(expectedStack); }); - it('boolean ands', function() { + it('boolean and', function() { var stack = evaluate('{ true false and }'); var expectedStack = [false]; expect(stack).toMatchArray(expectedStack); }); - it('bitwise ands', function() { + it('bitwise and', function() { var stack = evaluate('{ 254 1 and }'); var expectedStack = [254 & 1]; expect(stack).toMatchArray(expectedStack); }); - // TODO atan - // TODO bitshift - // TODO ceiling - // TODO copy - // TODO cos + it('calculates the inverse tangent of a number', function() { + var stack = evaluate('{ 90 atan }'); + var expectedStack = [Math.atan(90)]; + expect(stack).toMatchArray(expectedStack); + }); + it('handles bitshifting ', function() { + var stack = evaluate('{ 50 2 bitshift }'); + var expectedStack = [200]; + expect(stack).toMatchArray(expectedStack); + }); + it('calculates the ceiling value', function() { + var stack = evaluate('{ 9.9 ceiling }'); + var expectedStack = [10]; + expect(stack).toMatchArray(expectedStack); + }); + it('copies', function() { + var stack = evaluate('{ 99 98 2 copy }'); + var expectedStack = [99, 98, 99, 98]; + expect(stack).toMatchArray(expectedStack); + }); + it('calculates the cosine of a number', function() { + var stack = evaluate('{ 90 cos }'); + var expectedStack = [Math.cos(90)]; + expect(stack).toMatchArray(expectedStack); + }); it('converts to int', function() { var stack = evaluate('{ 9.9 cvi }'); var expectedStack = [9]; @@ -167,24 +187,76 @@ describe('function', function() { var expectedStack = [-9]; expect(stack).toMatchArray(expectedStack); }); - // TODO cvr - // TODO div + it('converts to real', function() { + var stack = evaluate('{ 55.34 cvr }'); + var expectedStack = [55.34]; + expect(stack).toMatchArray(expectedStack); + }); + it('divides', function() { + var stack = evaluate('{ 6 5 div }'); + var expectedStack = [1.2]; + expect(stack).toMatchArray(expectedStack); + }); + it('maps division by zero to infinity', function() { + var stack = evaluate('{ 6 0 div }'); + var expectedStack = [Infinity]; + expect(stack).toMatchArray(expectedStack); + }); it('duplicates', function() { var stack = evaluate('{ 99 dup }'); var expectedStack = [99, 99]; expect(stack).toMatchArray(expectedStack); }); - // TODO eq + it('accepts an equality', function() { + var stack = evaluate('{ 9 9 eq }'); + var expectedStack = [true]; + expect(stack).toMatchArray(expectedStack); + }); + it('rejects an inequality', function() { + var stack = evaluate('{ 9 8 eq }'); + var expectedStack = [false]; + expect(stack).toMatchArray(expectedStack); + }); it('exchanges', function() { var stack = evaluate('{ 44 99 exch }'); var expectedStack = [99, 44]; expect(stack).toMatchArray(expectedStack); }); - // TODO exp - // TODO false - // TODO floor - // TODO ge - // TODO gt + it('handles exponentiation', function() { + var stack = evaluate('{ 10 2 exp }'); + var expectedStack = [100]; + expect(stack).toMatchArray(expectedStack); + }); + it('pushes false onto the stack', function() { + var stack = evaluate('{ false }'); + var expectedStack = [false]; + expect(stack).toMatchArray(expectedStack); + }); + it('calculates the floor value', function() { + var stack = evaluate('{ 9.9 floor }'); + var expectedStack = [9]; + expect(stack).toMatchArray(expectedStack); + }); + it('handles greater than or equal to', function() { + var stack = evaluate('{ 10 9 ge }'); + var expectedStack = [true]; + expect(stack).toMatchArray(expectedStack); + }); + it('rejects less than for greater than or equal to', function() { + var stack = evaluate('{ 8 9 ge }'); + var expectedStack = [false]; + expect(stack).toMatchArray(expectedStack); + }); + it('handles greater than', function() { + var stack = evaluate('{ 10 9 gt }'); + var expectedStack = [true]; + expect(stack).toMatchArray(expectedStack); + }); + it('rejects less than or equal for greater than', function() { + var stack = evaluate('{ 9 9 gt }'); + var expectedStack = [false]; + expect(stack).toMatchArray(expectedStack); + }); it('divides to integer', function() { var stack = evaluate('{ 2 3 idiv }'); var expectedStack = [0]; @@ -200,16 +272,86 @@ describe('function', function() { var expectedStack = [4, 3, 2, 1, 3]; expect(stack).toMatchArray(expectedStack); }); - // TODO le - // TODO ln - // TODO log - // TODO lt - // TODO mod - // TODO mul - // TODO ne - // TODO neg - // TODO not - // TODO or + it('handles less than or equal to', function() { + var stack = evaluate('{ 9 10 le }'); + var expectedStack = [true]; + expect(stack).toMatchArray(expectedStack); + }); + it('rejects greater than for less than or equal to', function() { + var stack = evaluate('{ 10 9 le }'); + var expectedStack = [false]; + expect(stack).toMatchArray(expectedStack); + }); + it('calculates the natural logarithm', function() { + var stack = evaluate('{ 10 ln }'); + var expectedStack = [Math.log(10)]; + expect(stack).toMatchArray(expectedStack); + }); + it('calculates the base 10 logarithm', function() { + var stack = evaluate('{ 100 log }'); + var expectedStack = [2]; + expect(stack).toMatchArray(expectedStack); + }); + it('handles less than', function() { + var stack = evaluate('{ 9 10 lt }'); + var expectedStack = [true]; + expect(stack).toMatchArray(expectedStack); + }); + it('rejects greater than or equal to for less than', function() { + var stack = evaluate('{ 10 9 lt }'); + var expectedStack = [false]; + expect(stack).toMatchArray(expectedStack); + }); + it('performs the modulo operation', function() { + var stack = evaluate('{ 4 3 mod }'); + var expectedStack = [1]; + expect(stack).toMatchArray(expectedStack); + }); + it('multiplies two numbers (positive result)', function() { + var stack = evaluate('{ 9 8 mul }'); + var expectedStack = [72]; + expect(stack).toMatchArray(expectedStack); + }); + it('multiplies two numbers (negative result)', function() { + var stack = evaluate('{ 9 -8 mul }'); + var expectedStack = [-72]; + expect(stack).toMatchArray(expectedStack); + }); + it('accepts an inequality', function() { + var stack = evaluate('{ 9 8 ne }'); + var expectedStack = [true]; + expect(stack).toMatchArray(expectedStack); + }); + it('rejects an equality', function() { + var stack = evaluate('{ 9 9 ne }'); + var expectedStack = [false]; + expect(stack).toMatchArray(expectedStack); + }); + it('negates', function() { + var stack = evaluate('{ 4.5 neg }'); + var expectedStack = [-4.5]; + expect(stack).toMatchArray(expectedStack); + }); + it('boolean not', function() { + var stack = evaluate('{ true not }'); + var expectedStack = [false]; + expect(stack).toMatchArray(expectedStack); + }); + it('bitwise not', function() { + var stack = evaluate('{ 12 not }'); + var expectedStack = [-13]; + expect(stack).toMatchArray(expectedStack); + }); + it('boolean or', function() { + var stack = evaluate('{ true false or }'); + var expectedStack = [true]; + expect(stack).toMatchArray(expectedStack); + }); + it('bitwise or', function() { + var stack = evaluate('{ 254 1 or }'); + var expectedStack = [254 | 1]; + expect(stack).toMatchArray(expectedStack); + }); it('pops stack', function() { var stack = evaluate('{ 1 2 pop }'); var expectedStack = [1]; @@ -225,13 +367,51 @@ describe('function', function() { var expectedStack = [3, 2, 2, 1]; expect(stack).toMatchArray(expectedStack); }); - // TODO round - // TODO sin - // TODO sqrt - // TODO sub - // TODO true - // TODO truncate - // TODO xor + it('rounds a number', function() { + var stack = evaluate('{ 9.52 round }'); + var expectedStack = [10]; + expect(stack).toMatchArray(expectedStack); + }); + it('calculates the sine of a number', function() { + var stack = evaluate('{ 90 sin }'); + var expectedStack = [Math.sin(90)]; + expect(stack).toMatchArray(expectedStack); + }); + it('calculates a square root (integer)', function() { + var stack = evaluate('{ 100 sqrt }'); + var expectedStack = [10]; + expect(stack).toMatchArray(expectedStack); + }); + it('calculates a square root (float)', function() { + var stack = evaluate('{ 99 sqrt }'); + var expectedStack = [Math.sqrt(99)]; + expect(stack).toMatchArray(expectedStack); + }); + it('subtracts (positive result)', function() { + var stack = evaluate('{ 6 4 sub }'); + var expectedStack = [2]; + expect(stack).toMatchArray(expectedStack); + }); + it('subtracts (negative result)', function() { + var stack = evaluate('{ 4 6 sub }'); + var expectedStack = [-2]; + expect(stack).toMatchArray(expectedStack); + }); + it('pushes true onto the stack', function() { + var stack = evaluate('{ true }'); + var expectedStack = [true]; + expect(stack).toMatchArray(expectedStack); + }); + it('truncates a number', function() { + var stack = evaluate('{ 35.004 truncate }'); + var expectedStack = [35]; + expect(stack).toMatchArray(expectedStack); + }); + it('calculates an exclusive or value', function() { + var stack = evaluate('{ 3 9 xor }'); + var expectedStack = [10]; + expect(stack).toMatchArray(expectedStack); + }); }); });