Returns the remainder from dividing two integers.

1. Description

The mod operator pops two integers from the operand stack, divides int1 by int2, and pushes the remainder back onto the stack. The sign of the result is the same as the sign of the dividend (int1). Both operands must be integers, and the result is always an integer.

This is a remainder operation, not a true modulo operation in the mathematical sense, because the sign follows the dividend rather than the divisor.

This is a Level 1 operator, available in all PostScript implementations.

2. Syntax

int1 int2 mod remainder

2.1. Stack Effect

Table 1. Before Execution
Position Content

Top

int2 (integer) - Divisor (must be non-zero)

Top-1

int1 (integer) - Dividend

Table 2. After Execution
Position Content

Top

remainder (integer) - Remainder of int1 ÷ int2

3. Parameters

int1

The dividend - the integer to be divided

int2

The divisor - the integer to divide by (must be non-zero)

4. Return Values

remainder

The remainder when int1 is divided by int2. The sign matches int1’s sign.

5. Examples

5.1. Basic Modulo

% Simple remainders
5 3 mod        % → 2 (5 = 3×1 + 2)
7 4 mod        % → 3 (7 = 4×1 + 3)
8 4 mod        % → 0 (8 = 4×2 + 0, exact division)
10 7 mod       % → 3 (10 = 7×1 + 3)

5.2. Sign Behavior

% Positive dividend → positive remainder
5 3 mod        % → 2
5 -3 mod       % → 2 (sign follows dividend)

% Negative dividend → negative remainder
-5 3 mod       % → -2 (sign follows dividend!)
-5 -3 mod      % → -2

% Comparison with mathematical modulo
% PostScript mod is remainder, not true modulo
-7 3 mod       % → -1 (remainder)
% True modulo would be 2

5.3. Quotient and Remainder Together

% Get both quotient and remainder
/divAndMod {  % int1 int2 -> quotient remainder
    2 copy idiv    % int1 int2 quotient
    3 1 roll mod   % quotient remainder
} def

17 5 divAndMod % → 3 2 (17 = 5×3 + 2)
23 7 divAndMod % → 3 2 (23 = 7×3 + 2)

5.4. Even/Odd Testing

% Check if number is even
/isEven {  % int -> bool
    2 mod 0 eq
} def

% Check if number is odd
/isOdd {  % int -> bool
    2 mod 0 ne
} def

4 isEven   % → true
5 isEven   % → false
5 isOdd    % → true

5.5. Cyclic Indexing

% Wrap index within array bounds
/wrapIndex {  % index arrayLength -> wrappedIndex
    mod
    dup 0 lt {
        % Handle negative indices
        1 index add
    } if
    exch pop
} def

5 3 wrapIndex   % → 2 (5 mod 3)
-1 5 wrapIndex  % → 4 (wraps to end)

6. Advanced Examples

6.1. RGB Color Cycling

% Cycle through colors
/colorFromIndex {  % index -> r g b
    % Generate different colors based on index
    dup 3 mod 0 eq { pop 1 0 0 } if  % Red
    dup 3 mod 1 eq { pop 0 1 0 } if  % Green
    dup 3 mod 2 eq { pop 0 0 1 } if  % Blue
} def

0 colorFromIndex  % → 1 0 0 (red)
1 colorFromIndex  % → 0 1 0 (green)
2 colorFromIndex  % → 0 0 1 (blue)
3 colorFromIndex  % → 1 0 0 (red again)

6.2. Checksum Calculation

% Simple checksum (sum mod 256)
/checksum {  % string -> checksum
    0 exch     % Accumulator
    {
        add    % Add each character code
    } forall
    256 mod    % Keep in byte range
} def

(Hello) checksum  % → 244

6.3. Circular Buffer

% Implement circular buffer indexing
/circularIndex {  % currentIndex increment bufferSize -> newIndex
    3 -1 roll add  % increment bufferSize (currentIndex+increment)
    exch mod       % (currentIndex+increment) mod bufferSize
    dup 0 lt {     % Handle negative results
        2 index add
    } if
    exch pop
} def

5 3 10 circularIndex   % → 8 (5+3 in buffer of size 10)
8 5 10 circularIndex   % → 3 (wraps around: 8+5=13, 13 mod 10=3)

6.4. Digit Extraction

% Extract individual digits
/getDigit {  % number position -> digit
    % Position 0 is ones, 1 is tens, etc.
    1 exch {
        10 mul
    } repeat
    2 copy idiv    % number divisor quotient
    10 mod         % number divisor (quotient mod 10)
    3 1 roll pop pop
} def

12345 0 getDigit  % → 5 (ones place)
12345 2 getDigit  % → 3 (hundreds place)

7. Edge Cases and Common Pitfalls

mod is a remainder operation, not true mathematical modulo.

7.1. Remainder vs. Modulo

% PostScript mod is remainder (sign follows dividend)
-5 3 mod       % → -2 (remainder)

% True mathematical modulo would give: 1
% To get true modulo:
/truemod {  % int1 int2 -> modulo
    2 copy mod       % int1 int2 remainder
    dup 0 lt {       % If remainder is negative
        add          % Add divisor to make positive
    } {
        exch pop     % Just use remainder
    } ifelse
} def

-5 3 truemod   % → 1 (true modulo)
5 3 truemod    % → 2 (same as mod for positive)

7.2. Division by Zero

% WRONG: Division by zero
10 0 mod       % ERROR: undefinedresult

% CORRECT: Validate divisor
/safeMod {  % int1 int2 -> remainder
    dup 0 eq {
        pop pop 0
    } {
        mod
    } ifelse
} def

7.3. Type Requirements

% WRONG: Real operands not allowed
5.5 2 mod      % ERROR: typecheck
7 2.0 mod      % ERROR: typecheck

% CORRECT: Use integers only
7 2 mod        % → 1

8. Type Requirements

Both operands must be integers. Real numbers or other types will cause a typecheck error:

% BAD: Non-integer operands
7.5 3 mod           % ERROR: typecheck
10 3.0 mod          % ERROR: typecheck
(text) 5 mod        % ERROR: typecheck
  • idiv - Integer division (quotient)

  • div - Division with real result

  • add - Add two numbers

  • sub - Subtract two numbers

  • mul - Multiply two numbers

10. PostScript Level

Available in: PostScript Level 1 and higher

This is a fundamental arithmetic operator available in all PostScript implementations.

11. Error Conditions

stackunderflow

The operand stack contains fewer than two elements.

5 mod          % ERROR: stackunderflow (need 2 operands)
typecheck

One or both operands are not integers.

5.5 2 mod      % ERROR: typecheck (must be integers)
7 2.0 mod      % ERROR: typecheck
undefinedresult

The divisor is zero.

10 0 mod       % ERROR: undefinedresult (division by zero)

12. Performance Considerations

The mod operator is fast, typically implemented as a single hardware instruction:

  • Similar performance to idiv

  • Often paired with idiv for efficiency

  • Useful for array wraparound and cyclic operations

13. Best Practices

  1. Combine with idiv when you need both quotient and remainder

  2. Remember sign behavior - result sign matches dividend

  3. Validate divisor is non-zero in user-facing code

  4. Use for cyclic operations - wraparound, rotation, etc.

13.1. Common Patterns

% Check divisibility
/isDivisibleBy {  % num divisor -> bool
    mod 0 eq
} def

10 5 isDivisibleBy  % → true
10 3 isDivisibleBy  % → false

% Wrap to range [0, n-1]
/wrapTo {  % value n -> wrapped
    mod
    dup 0 lt { 1 index add } if
    exch pop
} def

-1 5 wrapTo  % → 4
7 5 wrapTo   % → 2

14. See Also


Back to top

Copyright © 2025 Ribose. PostScript is a trademark of Adobe. Distributed under the MIT License.