Showing posts with label Java. Show all posts
Showing posts with label Java. Show all posts

2012-01-12

File Sharing on the Spot

(now with highlighting!) Last time I complained that I couldn't find an easy way to share a source code archive that didn't involve signing up for a service I didn't care for. Blogging platforms only make easy to attach images to posts, so why not pack a file as a PNG? Enter PNGPack. I tried finding OCaml bindings to libpng; after a disheartening exploration I realized that Java is (for me at least) the ideal platform to make this possible, since it has a rich standard library to resort to:

import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import javax.imageio.ImageIO;

PNGPack is the simplest command-line utility I could get away with. It processes its arguments one by one, checking that they actually are regular files and determining by their extension whether to pack them as PNGs or to extract them:

public class PNGPack {
  public static void main(String[] args) {
    if (args.length == 0) {
      System.err.println("usage - java PNGPack <file>...");
      System.exit(2);
    }
    for (int i = 0; i != args.length; i++) {
      final File file = new File(args[i]);
      if (!file.isFile()) {
        System.err.printf("File \"%s\" is not a regular file\n", file.toString());
        continue;
      }
      final String fileName = file.getName();
      final int index = fileName.lastIndexOf('.');
      final String baseName, extension;
      if (index < 1) {
        baseName  = fileName;
        extension = null;
      } else {
        baseName  = fileName.substring(0, index);
        extension = fileName.substring(index + 1).toLowerCase();
      }
      try {
        if ("png".equals(extension)) {
          final File out = new File(file.getParentFile(), baseName);
          decode(file, out);
        } else {
          final File out = new File(file.getParentFile(), fileName + ".png");
          encode(file, out);
        }
      } catch (IOException e) {
        System.err.printf("Can't read \"%s\"\n", file.toString());
        e.printStackTrace(System.err);
      }
    }
  }

The image is headed by 24 bytes comprised by:

OffsetLengthField
04Signature 'PNGP'
44File length (big endian)
816MD5 digest
  private static final int PNGP_SIG  = 0x504e4750; // 'PNGP'
  private static final int HEADER_SZ = 24;

The image dimensions are selected so that the result is as square as possible. The image uses 4-byte ABGR pixels for maximum compactness and round-trip fidelity. The image is padded to size with 0 bytes, and the MD5 digest is computed over all the contents, padding included to avoid opening a steganographic channel:

  private static void encode(File inp, File out) throws IOException {
    final long length = inp.length();
    if (length >= 0x80000000L)
      throw new IOException("Overlong file");
    final int pixels = (int) (length + HEADER_SZ) >> 2;
    final int height = (int) Math.floor(Math.sqrt((double) pixels));
    final int width  = (int) Math.ceil((double) pixels / (double) height);
    final BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR);
    final byte[] frame = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
    final MessageDigest md5 = getMD5Digest();
    final InputStream is = new DigestInputStream(new FileInputStream(inp), md5);
    try {
      int nread;
      int index = HEADER_SZ;
      while ( (nread = is.read(frame, index, frame.length - index)) != -1 )
        index += nread;
      for (int i = index; i != frame.length; i++)
        frame[i] = 0;
      md5.update(frame, index, frame.length - index);
    }
    finally {
      is.close();
    }
    final byte[] digest = md5.digest();
    assert (digest.length == 16);
    intToBytes(frame, 0, PNGP_SIG);
    intToBytes(frame, 4, (int) length);
    for (int i = 0; i != digest.length; i++)
      frame[8 + i] = digest[i];
    final OutputStream os = new BufferedOutputStream(new FileOutputStream(out));
    try {
      ImageIO.write(image, "PNG", os);
    } finally {
      os.close();
    }
    System.out.printf("<img width=\"%d\" height=\"%d\" src=\"%s\" alt=\"%s\" />\n",
      width, height, out.getName(), inp.getName());
  }

The encoding ends by outputting a handy <img> tag. Decoding an image is equally straightforward, except for a number of safety checks trying to ensure that only proper PNGPack images are decoded:

  private static void decode(File inp, File out) throws IOException {
    final InputStream is = new BufferedInputStream(new FileInputStream(inp));
    final BufferedImage image;
    try {
      image = ImageIO.read(is);
    } finally {
      is.close();
    }
    if (image.getType() != BufferedImage.TYPE_4BYTE_ABGR)
      throw new IOException("Invalid PNGPack image (bad image type)");
    final byte[] frame = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
    if (bytesToInt(frame, 0) != PNGP_SIG)
      throw new IOException("Invalid PNGPack image (bad signature)");
    final int length = bytesToInt(frame, 4);
    final int pixels = (int) (length + HEADER_SZ) >> 2;
    final int height = (int) Math.floor(Math.sqrt((double) pixels));
    final int width  = (int) Math.ceil((double) pixels / (double) height);
    if (!(height == image.getHeight() && width == image.getWidth()))
      throw new IOException("Invalid PNGPack image (bad dimensions)");
    final MessageDigest md5 = getMD5Digest();
    md5.update(frame, HEADER_SZ, frame.length - HEADER_SZ);
    final byte[] digest = md5.digest();
    assert (digest.length == 16);
    for (int i = 0; i != digest.length; i += 4)
      if (frame[8 + i] != digest[i])
        throw new IOException("Invalid PNGPack image (bad MD5 digest)");
    final OutputStream os = new FileOutputStream(out);
    try {
      os.write(frame, HEADER_SZ, length);
    } finally {
      os.close();
    }
  }

The code is hyper-compact in order to minimize the number of lines shown in this post. Feel free to add whitespace and comments to suit taste. The only thing left is a couple of helper functions:

  private static void intToBytes(byte[] buf, int off, int n) {
    buf[off + 0] = (byte) ((n >> 24) & 255);
    buf[off + 1] = (byte) ((n >> 16) & 255);
    buf[off + 2] = (byte) ((n >>  8) & 255);
    buf[off + 3] = (byte) ( n        & 255);
  }

  private static int bytesToInt(byte[] buf, int off) {
    return (((int) buf[off + 0] & 255) << 24)
      |  (((int) buf[off + 1] & 255) << 16)
      |  (((int) buf[off + 2] & 255) <<  8)
      |   ((int) buf[off + 3] & 255);
  }

  private static MessageDigest getMD5Digest() {
    try {
      return MessageDigest.getInstance("MD5");
    } catch (NoSuchAlgorithmException _) {
      System.err.println("No instance of MD5 digest algorithm!");
      System.exit(1);
      return null; // not reached
    }
  }
}

I've updated the last post to include the PNGPacked code archive. Use it responsibly, and enjoy!

2012-01-11

Eighteen Million Noises

Update: Here is the PNGPack source-code archive:

noise.tgz

Per second. Yes, it's benchmark time. I pitted Prof. Perlin's original implementation against Stefan Gustavson's, and the results are in! I ran two sets of benchmarks, one in Java and the other in OCaml. In both cases I compared three versions of Simplex Noise: Perlin's pipelined 3D Noise, and Gustavson's 2D Noise and 3D Noise:


  • noisep: Perlin's 3D Simplex Noise
  • noise2: Gustavson's 2D Simplex Noise
  • noise3: Gustavson's 3D Simplex Noise

The Java programs are copied directly from the linked papers (except for one modification, noted below); the OCaml versions are pixel-faithful translations. Each benchmarked function calls noise 1,000 times in a tight loop. The benchmark runs the functions three times for 10 seconds each. I ran the benchmark on a lightly loaded, cool MacBook (2 GHz Intel Core 2 Duo, 2 GB 533 Mhz DDR2 SDRAM running Mac OS X 10.6.8). By cool I mean "left to cool down"; the temperature reached 37 °C yesterday. These are the best-of-three timings for each function:


FunctionCalls/s
OCamlJava
noisep 2,123,490 3,417,300
noise218,206,09018,239,810
noise310,506,63010,404,280

The timings relative to Java's noisep are:


FunctionRelative speed
OCamlJava
noisep0.62141.0000
noise25.32765.3375
noise33.07453.0446

The big difference between OCaml's and Java's noisep is attributable to the fact that my translation is more structured than Perlin's version; for the other two functions the difference is within 1% (which I find quite amazing in and of itself).


In the case of Gustavson's Noise, I modified the code to randomly choose among 16 gradients on the unit cell, not 12 as in the code given in the paper. In contrast to Perlin's suggestion of duplicating existing vectors, I added four cell vertices so that the 2D projection of the gradient vectors onto the XY plane is unbiased. This allows indexing the gradient vector with a bit-mask instead of a modulo operation:


let grad3 = [|
( 1., 1., 0.);(-1., 1., 0.);( 1.,-1., 0.);(-1.,-1., 0.);
( 1., 0., 1.);(-1., 0., 1.);( 1., 0.,-1.);(-1., 0.,-1.);
( 0., 1., 1.);( 0.,-1., 1.);( 0., 1.,-1.);( 0.,-1.,-1.);
( 1., 1., 1.);(-1., 1., 1.);( 1.,-1.,-1.);(-1.,-1., 1.);
|]

These are the raw timings, for OCaml:


noisep: 10.45 WALL (10.44 usr +  0.01 sys = 10.45 CPU) @ 2122.11/s (n=22184)
        10.45 WALL (10.44 usr +  0.01 sys = 10.45 CPU) @ 2123.49/s (n=22184)
        10.45 WALL (10.44 usr +  0.01 sys = 10.45 CPU) @ 2122.31/s (n=22184)
noise2: 10.51 WALL (10.50 usr +  0.01 sys = 10.51 CPU) @ 18198.59/s (n=191223)
        10.50 WALL (10.50 usr +  0.01 sys = 10.50 CPU) @ 18206.09/s (n=191223)
        10.50 WALL (10.50 usr +  0.01 sys = 10.50 CPU) @ 18204.68/s (n=191223)
noise3: 10.51 WALL (10.51 usr +  0.01 sys = 10.51 CPU) @ 10504.05/s (n=110443)
        10.51 WALL (10.51 usr +  0.01 sys = 10.51 CPU) @ 10506.63/s (n=110443)
        10.57 WALL (10.56 usr +  0.01 sys = 10.57 CPU) @ 10449.81/s (n=110443)

          Rate     noisep noise3 noise2
noisep  2123+- 1/s     --   -80%   -88%
noise3 10487+-25/s   394%     --   -42%
noise2 18203+- 3/s   758%    74%     --

and for Java:


noisep: 10.04 WALL @ 3386.12/s (n=34000)
noisep: 10.24 WALL @ 3417.30/s (n=35000)
noisep: 10.24 WALL @ 3416.97/s (n=35000)
noise2: 10.01 WALL @ 18181.82/s (n=182000)
noise2: 10.00 WALL @ 18100.00/s (n=181000)
noise2: 10.03 WALL @ 18239.81/s (n=183000)
noise3: 10.04 WALL @ 10357.53/s (n=104000)
noise3: 10.09 WALL @ 10404.28/s (n=105000)
noise3: 10.01 WALL @ 10390.65/s (n=104000)

I used the following benchmark harness in OCaml:


let rand w = w *. (Random.float 1. -. 0.5)

let max_iter = 1_000
let width    = 4.

let noisep () =
  let p = (rand width, rand width, rand width) in
  for i = 1 to max_iter do ignore (Noise.noise p) done

let noise2 () =
  let p = (rand width, rand width) in
  for i = 1 to max_iter do ignore (Noise.noise2 p) done

let noise3 () =
  let p = (rand width, rand width, rand width) in
  for i = 1 to max_iter do ignore (Noise.noise3 p) done

let () =
  let open Benchmark in
  let bm = throughputN ~style:Auto ~repeat:3 10 [
    ("noisep", noisep, ());
    ("noise2", noise2, ());
    ("noise3", noise3, ());
  ] in
    print_newline();
  tabulate bm;

It uses Christophe Troestler's ocaml-benchmark module. The Java harness is similar but hand-coded:


public class NoiseBench {
  private static final double WIDTH = 4.0;
  private static final int NITER = 1000;
  private static final int NTEST = 3;
  private static final int NSECS = 10;

  private static void benchmark(String name, Runnable test) {
    for (int i = 0; i != NTEST; i++) {
      long now = System.currentTimeMillis(), lap = 0;
      int count = 0;
      while (lap < NSECS * 1000) {
        for (int j = 0; j != NITER; j++)
          test.run();
        lap = System.currentTimeMillis() - now;
        count += NITER;
      }
      System.out.printf("%s: %.2f WALL @ %.2f/s (n=%d)\n",
        name,
        (double) lap / 1000.0,
        (double) count * 1000. / (double) lap,
        count);
      System.out.flush();
    }
  }

  private static double rand() {
    return WIDTH * (Math.random() - 0.5);
  }

  private static void noisep() {
    double x = rand(), y = rand(), z = rand();
    for (int i = 0; i != NITER; i++)
      Noise3.noise(x, y, z);
  }

  private static void noise2() {
    double x = rand(), y = rand();
    for (int i = 0; i != NITER; i++)
      SimplexNoise.noise(x, y);
  }

  private static void noise3() {
    double x = rand(), y = rand(), z = rand();
    for (int i = 0; i != NITER; i++)
      SimplexNoise.noise(x, y, z);
  }

  public static void main(String[] args) {
    benchmark("noisep", new Runnable() { public void run() { noisep(); } });
    benchmark("noise2", new Runnable() { public void run() { noise2(); } });
    benchmark("noise3", new Runnable() { public void run() { noise3(); } });
  }
}

2011-12-29

Vose's Alias Method

This is a note regarding the implementation of Vose's Method to construct the alias tables for non-uniform discrete probability sampling presented by Keith Schwartz (as of 2011-12-29). Mr. Schwartz otherwise very informative write-up contains an error in the presentation of the Method. Step 5 of the algorithm fails if the Small list is nonempty but the Large list is. This can happen either:


  1. if the initial probabilities sum to less than 1, or
  2. if updating in step 5.5 the Large probability results in cancellation so that pg results in an approximation less than its true value

The first case can be mitigated by scaling by n / ∑ pj in step 3. The second case can be mitigated by replacing 5.5 by "Set pg := (pg + pl) - 1." In any case, there is no proof that the algorithm as shown is correct, which is not the case for Vose's presentation. In the interest of correctness and completeness, here is an OCaml implementation of Vose's Method:


type alias = { n : int; prob : float array; alias : int array; }

let alias pa =
  let rec split pa n j (small, large as part) =
    if j == n then part else
    if pa.(j) > 1.
      then split pa n (succ j) (     small, j :: large)
      else split pa n (succ j) (j :: small,      large)
  in
  let rec init r pa part = match part with
  | j :: small, k :: large ->
    r.prob.(j)  <- pa.(j);
    r.alias.(j) <- k;
    pa.(k)      <- (pa.(k) +. pa.(j)) -. 1.;
    if pa.(k) > 1.
      then init r pa (small, k :: large)
      else init r pa (k :: small, large)
  | j :: small, []         ->
    r.prob.(j) <- 1.;
    init r pa (small, [])
  | []        , k :: large ->
    r.prob.(k) <- 1.;
    init r pa ([], large)
  | []        , []         -> r
  in
  let n  = Array.length pa in
  if n == 0 then invalid_arg "alias" else
  let sc = float n /. Array.fold_left (fun s p ->
    if p < 0. then invalid_arg "alias" else
    s +. p) 0. pa in
  let sa = Array.map (( *. ) sc) pa in
  let r  = { n; prob = Array.make n 0.; alias = Array.make n (-1); } in
  init r sa (split sa n 0 ([], []))

let choose r =
  let p, e = modf (Random.float (float r.n)) in
  let j = truncate e in
  if p <= r.prob.(j) then j else r.alias.(j)

Since this algorithm is recursive, it might not be immediately obvious how to translate it to more mainstream languages. A perhaps more faithful rendition in rather low-level Java is the following:


import java.util.Random;

public class Vose {
  private final Random random;
  private final int limit;
  private final double[] prob;
  private final int[] alias;

  public Vose(final double[] pa) {
    this(pa, new Random());
  }

  public int getLimit() {
    return limit;
  }

  public Vose(final double[] pa, final Random random) {
    final int limit = pa.length;
    if (limit == 0)
      throw new IllegalArgumentException("Vose");
    double sum = 0;
    for (int j = 0; j != limit; j++) {
      if (pa[j] < 0)
        throw new IllegalArgumentException("Vose");
      sum += pa[j];
    }
    final double scale = (double) limit / sum;
    final double[] sa = new double[limit];
    for (int j = 0; j != limit; j++)
      sa[j] = pa[j] * scale;

    this.random = random;
    this.limit  = limit;
    this.prob   = new double[limit];
    this.alias  = new int[limit];
    init(sa);
  }

  private void init(final double[] sa) {
    final int[] small = new int[limit];
    final int[] large = new int[limit];
    int ns = 0;
    int nl = 0;
    for (int j = 0; j != limit; j++)
      if (sa[j] > 1)
        large[nl++] = j;
      else
        small[ns++] = j;
    while (ns != 0 && nl != 0) {
      final int j = small[--ns];
      final int k = large[--nl];
      prob[j]  = sa[j];
      alias[j] = k;
      sa[k]    = (sa[k] + sa[j]) - 1; // sic
      if (sa[k] > 1)
        large[nl++] = k;
      else
        small[ns++] = k;
    }
    while (ns != 0)
      prob[small[--ns]] = 1;
    while (nl != 0)
      prob[large[--nl]] = 1;
  }

  public int choose() {
    final double u = limit * random.nextDouble();
    final int    j = (int) Math.floor(u);
    final double p = u - (double) j;
    return p <= prob[j] ? j : alias[j];
  }
}

In all generality, it is sufficient that the "probabilities" be non-negative, since dividing the values by the mean normalizes them so that the conditions of the Method are satisfied.


References


  1. Michael D. Vose. A Linear Algorithm For Generating Random Numbers With a Given Distribution, IEEE TRANSACTIONS ON SOFTWARE ENGINEERING VOL. 17, NO. 9 SEPTEMBER 1991. Online.

2011-11-17

Brainfuck in Java

(I don't feel like writing a punning title.) Last time I showed how the use of functors allows for modular and type-safe specification of semantics. I wrote I can't imagine this flexibility in object-oriented languages like Java or Python; fighting words for which I was justly taken to task. Here's my penance: a morally equivalent reimplementation in Java of the Brainfuck interpreter. The translation was mechanic, but I realized with some surprise that the result is more flexible than the original OCaml: whereas the latter only allows static composition of semantics (unless you use first-class modules), Java allows fully dynamic, run-time stacking of semantics.

Even though the Java is better decoupled than the original (which uses the same memory representation for every interpreter variant), this is more by necessity than design. In the process, the interpreter suffered more than a 300% code expansion by line count at 520 lines. Bear with me! This is a single-file, multiple-class program; feel free to package and refactor it to your heart's content. The external requirements are minimal:

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

As advertised, the top-level Brainfuck class parses, prints and evaluates Brainfuck programs (a List of Instructions) using fully compositional semantics:

public final class Brainfuck {
    public static void main(String[] args) {
        String hello =
">+++++++++[<++++++++>-]<.>+++++++[<++++>-]<+.+++++++..+++.>>>++++++++[<++++>-]"+
"<.>>>++++++++++[<+++++++++>-]<---.<<<<.+++.------.--------.>>+.";
        Semantics semantics = new S3_(5000, new S2(new S1_(new S0())));
        List<Instruction> program = Brainfuck.parse(hello);
        System.out.print(Brainfuck.print(program));
        Brainfuck.evaluate(semantics, program);
    }

The class is completely static and reentrant; the main operations delegate to appropriate visitors:

private Brainfuck() { }

    public static void evaluate(Semantics semantics, List<Instruction> program) {
        new Evaluator(semantics).evaluate(program);
    }

    public static String print(List<Instruction> program) {
        return new Printer().print(program);
    }

The parser is standard, recursive-descent but with explicitly-managed recursion. For simple (concrete) instructions it just adds the corresponding Instruction to the current program. When it sees an opening bracket it uses a Stack to hold the partially-parsed List of Instructions and starts fresh. When it encounters a closing bracket, it builds a Repeat instruction from the just-parsed program, pops the context and adds the former to the latter:

public static List<Instruction> parse(String text) {
        final Stack<List<Instruction> > stack = new Stack<List<Instruction> >();
        List<Instruction> program = new ArrayList<Instruction>();

        for (int i = 0; i != text.length(); i++)
            switch (text.charAt(i)) {
            case '>': program.add(Instruction.FWD); break;
            case '<': program.add(Instruction.BAK); break;
            case '+': program.add(Instruction.INC); break;
            case '-': program.add(Instruction.DEC); break;
            case '.': program.add(Instruction.OUT); break;
            case ',': program.add(Instruction.INP); break;
            case '[':
                stack.push(program);
                program = new ArrayList<Instruction>();
                break;
            case ']':
                if (stack.empty())
                    throw new IllegalArgumentException("unmatched `]'");
                final Instruction rep = Instruction.REP(program);
                program = stack.pop();
                program.add(rep);
                break;
            }
        if (!stack.empty())
            throw new IllegalArgumentException("unmatched `['");
        return program;
    }
}

A textbook example that completes the class. Now for the real program. An Instruction is an abstract class implementing the case class pattern à la Scala (cf Wadler's expression problem). Every instruction supports two operations, evaluation and printing, by using the visitor pattern:

abstract class Instruction {
    private Instruction() { }

    public abstract void evaluate(Evaluator evaluator);
    public abstract void print(Printer printer);

Each concrete Instruction is tucked away inside this class. They simply forward the call to the passed-in visitor. The first six are mind-numbingly straightforward:

private static final class Forward extends Instruction {
        private Forward() { }

        @Override
        public void evaluate(Evaluator evaluator) {
            evaluator.evaluateForward();
        }

        @Override
        public void print(Printer printer) {
            printer.printForward();
        }

    private static final class Backward extends Instruction {
        private Backward() { }

        @Override
        public void evaluate(Evaluator evaluator) {
            evaluator.evaluateBackward();
        }

        @Override
        public void print(Printer printer) {
            printer.printBackward();
        }

    private static final class Increment extends Instruction {
        private Increment() { }

        @Override
        public void evaluate(Evaluator evaluator) {
            evaluator.evaluateIncrement();
        }

        @Override
        public void print(Printer printer) {
            printer.printIncrement();
        }

    private static final class Decrement extends Instruction {
        private Decrement() { }

        @Override
        public void evaluate(Evaluator evaluator) {
            evaluator.evaluateDecrement();
        }

        @Override
        public void print(Printer printer) {
            printer.printDecrement();
        }

    private static final class Output extends Instruction {
        private Output() { }

        @Override
        public void evaluate(Evaluator evaluator) {
            evaluator.evaluateOutput();
        }

        @Override
        public void print(Printer printer) {
            printer.printOutput();
        }

    private static final class Input extends Instruction {
        private Input() { }

        @Override
        public void evaluate(Evaluator evaluator) {
            evaluator.evaluateInput();
        }

        @Override
        public void print(Printer printer) {
            printer.printInput();
        }

The last Instruction is fractionally more interesting in that it has a program as a parameter:

private static final class Repeat extends Instruction {
        private final List<Instruction> program;

        private Repeat(List<Instruction> program) {
            this.program = program;
        }

        @Override
        public void evaluate(Evaluator evaluator) {
            evaluator.evaluateRepeat(program);
        }

        @Override
        public void print(Printer printer) {
            printer.printRepeat(program);
        }

These classes are fully private to the enclosing case class Instruction; the Brainfuck interpreter uses static members to refer to each:

public static final Instruction FWD = new Forward();
    public static final Instruction BAK = new Backward();
    public static final Instruction INC = new Increment();
    public static final Instruction DEC = new Decrement();
    public static final Instruction OUT = new Output();
    public static final Instruction INP = new Input();

    public static Instruction REP(List<Instruction> program) {
        return new Repeat(program);
    }
}

This is all the (essentially boilerplate) code necessary just to reproduce an algebraic data type over which OCaml code would pattern match. The visitors implement each arm of this match, so more boilerplate follows. The first one is the Evaluator:

class Evaluator {
    private final Semantics semantics;
    private final Memory memory;

It takes a Semantics and sets itself to operate upon an initial Memory:

public Evaluator(Semantics semantics) {
        this.semantics = semantics;
        this.memory = semantics.initial();
    }

This is all a bit abstract because both Semantics and Memory are interfaces that can be plugged-in at will. To evaluate a program, it visits each Instruction in turn:

public void evaluate(List<Instruction> program) {
        for (Instruction instruction : program)
            instruction.evaluate(this);
    }

Again, this is a bog-standard visitor. Each visiting method simply delegates to the chosen Semantics with the current state of the Memory:

public void evaluateForward() {
        semantics.forward(this.memory);
    }

    public void evaluateBackward() {
        semantics.backward(this.memory);
    }

    public void evaluateIncrement() {
        semantics.increment(this.memory);
    }

    public void evaluateDecrement() {
        semantics.decrement(this.memory);
    }

    public void evaluateOutput() {
        semantics.output(this.memory);
    }

    public void evaluateInput() {
        semantics.input(this.memory);
    }

The Repeat instruction is an Action over a Memory that corresponds to evaluate-ing the repeated program:

public void evaluateRepeat(final List<Instruction> program) {
        semantics.repeat(new Action<Memory>() {
            @Override
            public void apply(Memory _unused) {
                evaluate(program);
            }
        }, this.memory);
    }
}

(Why is the Memory _unused? Because evaluate already has it in scope, but the Semantics are fully parametric with respect to the store. If you find an elegant solution to this that doesn't involve each Instruction passing the Memory around, let me know.) This is the moral equivalent of a higher-order closure; someday you might be able to write a lambda instead of that. The second visitor is the Printer:

class Printer {
    private final StringBuffer buffer = new StringBuffer(72);
    private int linelen;

It formats the Brainfuck program in neat lines of 72 characters:

public Printer() {
        linelen = 0;
    }

    private void putc(char c)  {
        if (linelen == 72 || c == '\n') {
            buffer.append('\n');
            linelen = 0;
        }
        if (c != '\n') {
            buffer.append(c);
            linelen++;
        }
    }

The visitor sets the buffer up, prints each instruction by visiting them in turn and closes the buffer:

public String print(List<Instruction> program) {
        buffer.setLength(0);
        for (Instruction instruction : program)
            instruction.print(this);
        putc('\n');
        return buffer.toString();
    }

Each visited Instruction accumulates its representation in the buffer:

public void printForward()   { putc('>'); }
    public void printBackward()  { putc('<'); }
    public void printIncrement() { putc('+'); }
    public void printDecrement() { putc('-'); }
    public void printOutput()    { putc('.'); }
    public void printInput()     { putc(','); }

Aside: It is not the responsibility of the Instruction to know its external representation since it denotes Brainfuck's abstract syntax. Do not be misled by phony invocations to the Law of Demeter.

Repeat just emits its list of Instructions between brackets by mutual recursion between it and this visitor:

public void printRepeat(List<Instruction> program) {
        putc('[');
        for (Instruction instruction : program)
            instruction.print(this);
        putc(']');
    }
}

Neat. Now for the raison d'être of the exercise: A Semantics encapsulates the effects of each Brainfuck instruction upon the Memory:

interface Semantics {
    Memory initial();
    void forward(Memory memory);
    void backward(Memory memory);
    void increment(Memory memory);
    void decrement(Memory memory);
    void output(Memory memory);
    void input(Memory memory);
    void repeat(Action<Memory> program, Memory memory);
}

The effect of a repetition depends on the program being repeated; this is represented by an Action taking the Memory as a parameter:

interface Action<T> {
    void apply(T argument);
}

Aside: Don't confuse a program as a List of Instructions with its meaning as an Action or effect. It wouldn't be appropriate for repeat to take anything else.

In object-oriented languages there are two reuse mechanisms: inheritance and composition. The first is static, compile-time and determined by the providing (i.e. library) code; the second is dynamic, run-time and controlled by the consuming (i.e. client) code. Coplien's envelope pattern allows to combine both in a sort of dynamic inheritance:

abstract class DelegatingSemantics implements Semantics {
    private final Semantics delegate;

    public DelegatingSemantics(Semantics delegate) {
        this.delegate = delegate;
    }

    @Override
    public Memory initial()              { return delegate.initial(); }

    @Override
    public void forward(Memory memory)   { delegate.forward(memory); }

    @Override
    public void backward(Memory memory)  { delegate.backward(memory); }

    @Override
    public void increment(Memory memory) { delegate.increment(memory); }

    @Override
    public void decrement(Memory memory) { delegate.decrement(memory); }

    @Override
    public void output(Memory memory)    { delegate.output(memory); }

    @Override
    public void input(Memory memory)     { delegate.input(memory); }

    @Override
    public void repeat(Action<Memory> program, Memory memory) {
        delegate.repeat(program, memory);
    }
}

Envelopes take a delegating letter to which to forward by default the implemented methods; subclasses need only override the methods of interest and let the envelope handle the rest. The initial semantics S0 is, however, fully concrete. It operates on an unbounded memory of machine integers:

class S0 implements Semantics {
    @Override
    public Memory initial()              { return new UnboundedMemory(); }

    @Override
    public void forward(Memory memory)   { memory.next(); }

    @Override
    public void backward(Memory memory)  { memory.prev(); }

    @Override
    public void increment(Memory memory) { memory.set(memory.get() + 1); }

    @Override
    public void decrement(Memory memory) { memory.set(memory.get() - 1); }

    @Override
    public void output(Memory memory) {
        System.out.print((char) (memory.get() & 255));
    }

The input behavior on EOF is to leave the memory untouched:

@Override
    public void input(Memory memory) {
        try {
            final int c = System.in.read();
            if (c != -1) memory.set(c);
        } catch (IOException e) {
            System.err.println(e);
        }
    }

The meaning of repeat is to execute the enclosed program until the current memory cell is zero:

@Override
    public void repeat(Action<Memory> program, Memory memory) {
        int c;
        while ( (c = memory.get()) != 0 )
            program.apply(memory);
    }
}

This interpretation of repeat will probably never change (but consider a non-Turing-complete version of Brainfuck with bounded repetition, e.g. for server-side Core Wars competitions). The first difference, however, is on input:

class S1 extends DelegatingSemantics {
    public S1(Semantics delegate) { super(delegate); }

    @Override
    public void input(Memory memory) {
        try {
            final int c = System.in.read();
            memory.set(c == -1 ? 0 : c);
        } catch (IOException e) {
            System.err.println(e);
        }
    }
}

The S1 interpretation overrides a Semantics so that it sets the current cell to zero on EOF. The other variant is to set it to -1:

class S1_ extends DelegatingSemantics {
    public S1_(Semantics delegate) { super(delegate); }

    @Override
    public void input(Memory memory) {
        try {
            final int c = System.in.read();
            memory.set(c);
        } catch (IOException e) {
            System.err.println(e);
        }
    }
}

The second difference is in the memory cell size, in this case 8-bit-wide:

class S2 extends DelegatingSemantics {
    public S2(Semantics delegate) { super(delegate); }

    @Override
    public void increment(Memory memory) {
        memory.set((memory.get() + 1) & 255);
    }

    @Override
    public void decrement(Memory memory) {
        memory.set((memory.get() - 1) & 255);
    }
}

Although it uses the delegate Semantics's memory, it truncates it on mutation. The third difference is in the organization of the Memory itself:

class S3 extends DelegatingSemantics {
    protected final int length;

    public S3(int length, Semantics delegate) {
        super(delegate);
        this.length = length;
    }

    @Override
    public Memory initial() { return new BoundedMemory(length); }
}

It uses a bounded memory of the size provided, which disallows moving past its bounds. A variation is to wrap around the current cell when reaching either end:

class S3_ extends DelegatingSemantics {
    protected final int length;

    public S3_(int length, Semantics delegate) {
        super(delegate);
        this.length = length;
    }

    @Override
    public Memory initial() { return new CircularMemory(length); }
}

The same code except for the underlying store selected. The Memory interface itself is simple:

interface Memory {
    int get();
    void set(int value);
    void next();
    void prev();
}

The only operations on it are getting and setting the current cell's value and moving it one position in each direction. The implementation of an UnboundedMemory is, however, a bit sophisticated. It uses the standard Turing Machine trick of simulating a doubly-infinite tape with two semi-infinite ones:

class UnboundedMemory implements Memory {
    private final List<Integer> left  = new ArrayList<Integer>();
    private final List<Integer> right = new ArrayList<Integer>();
    private int cursor;

The right tape contains cells with index 0, 1, 2… while the left tape contains cells indexed by -1, -2, -3… Initially only the zero-th cell exists:

public UnboundedMemory() {
        right.add(0);
        cursor = 0;
    }

The class maintains the invariant that the current cell, to which cursor points, always exists:

@Override
    public int get() {
        if (cursor < 0)
            return left.get(-1 - cursor);
        else
            return right.get(cursor);
    }

    @Override
    public void set(int value) {
        if (cursor < 0)
            left.set(-1 - cursor, value);
        else
            right.set(cursor, value);
    }

New cells are created on demand on the appropriate tape upon cursor movement:

@Override
    public void next() {
        cursor++;
        if (cursor >= 0 && right.size() == cursor)
            right.add(0);
    }

    @Override
    public void prev() {
        --cursor;
        if (cursor < 0 && left.size() == -1 - cursor)
            left.add(0);
    }
}

A BoundedMemory is, by contrast, much simpler:

class BoundedMemory implements Memory {
    protected final int[] tape;
    protected int cursor;

    public BoundedMemory(int length) {
        this.tape = new int[length];
        cursor = 0;
    }

    @Override
    public int get() {
        return tape[cursor];
    }

    @Override
    public void set(int value) {
        tape[cursor] = value;
    }

The only intelligence required is in avoiding moving the cursor outside its bounds:

@Override
    public void next() {
        if (cursor != tape.length - 1)
            cursor++;
    }

    @Override
    public void prev() {
        if (cursor != 0)
            --cursor;
    }
}

A CircularMemory is just a BoundedMemory with a different out-of-bounds behavior:

class CircularMemory extends BoundedMemory {
    public CircularMemory(int length) {
        super(length);
    }

    @Override
    public void next() {
        cursor++;
        if (cursor == tape.length)
            cursor = 0;
    }

    @Override
    public void prev() {
        if (cursor == 0)
            cursor = tape.length;
        --cursor;
    }
}

tl; dr: writing interpreters in Java is tedious. Interestingly enough, I find the object-oriented expression of the Semantics over the different types of Memory very natural, more so even than what modular programming allows. The downsides I find, at least for Java, are two:

  1. The sheer amount of boilerplate necessary to express the problem. Even allowing for the lack of closures, algebraic data types and pattern matching, it lacks an automatic delegation mechanism. This is actually a shortcoming of every mainstream object-oriented language (and no, metaprogramming is not a substitute for a language construct that can be checked and verified statically for a number of properties that run-time reflection would not)
  2. The need to name everything. Nominal type disciplines not only suck on principle, they actually encourage naming trivial program constructs (classes, interfaces, methods) that therefore take an artificial existence of their own, bloating (module) interfaces and opening new ports for coupling

Still with me? Let me thank you and express my admiration for your fortitude.

2011-05-17

And Yet They Complain

Compare and contrast. PHP:

<?php
$body = @file_get_contents("php://input");
header('Content-type: text/plain');
print $body;
flush();
?>

Java:

import java.io.IOException;
import java.io.Reader;
import java.io.Writer;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/reflect")
public class ReflectorServlet extends HttpServlet {
  private static final long serialVersionUID = 1L;
       
  protected void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    dump(request, response);
  }

  protected void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    dump(request, response);
  }

  private void dump(HttpServletRequest request, HttpServletResponse response)
        throws IOException {
    response.setContentType("text/plain");
    response.setCharacterEncoding(request.getCharacterEncoding());
    final Reader reader = request.getReader();
    final Writer writer = response.getWriter();
    final StringBuilder builder = new StringBuilder();
    final char[] buffer = new char[1024];
    int nread;
    while ( (nread = reader.read(buffer, 0, buffer.length)) >= 0 )
      builder.append(buffer, 0, nread);
    final String contents = builder.toString();
    response.setContentLength(contents.length());
    writer.write(contents);
    response.flushBuffer();
    reader.close();
    writer.close();
  }
}

Granted, the Java version does one thing the PHP one doesn't (can you spot it?).

Sometimes the end does justify the means.

2009-05-26

Is Immutable Data Slow?

Is immutatble data always slower than mutable state? I was challenged in a discussion over at Reddit about this issue, and I decided to perform a little experiment to back up a rough estimate with some numbers. I was surprised and delighted to see that I could make my case very strong indeed by showing that no, immutable data can be twice as fast as mutable data in a modern functional language.

I concocted a trivial synthetic benchmark using simple records intended to emulate typical business entities:

module P0 = struct
  type person = { name: string; age: int; balance: float }
end

module P1 = struct
  type person = { name: string; mutable age: int; mutable balance: float }
end

let test0 =
  let module E = struct
    open P0
    let rec test p iters =
      if iters == 0 then p.balance else
      test { p with balance = p.balance +. 1. } (iters - 1)
  end in E.test { P0.name="John Doe"; P0.age=19; P0.balance=100.}

let test1 =
  let module E = struct
    open P1
    let test p iters =
      for i = 1 to iters do
        p.balance <- p.balance +. 1.
      done
  end in E.test { P1.name="John Doe"; P1.age=19; P1.balance=100.}

The module P0 encapsulates an immutable business record; test0 is the attendant test that uses functional record updating and recursion in a classicaly pure idiom. The module P1, on the other hand, with its corresponding test test1 show the typical imperative use of a mutable record. The test and timing harness for both functions is simple enough:

let test times f iters =
  let best = ref infinity in
  for i = 1 to times do
    let t = Sys.time () in
    let _ = f iters in
    let t = Sys.time () -. t in
    if !best > t then
      best := t
  done;
  float iters /. !best

let () =
  let iters = 1_000_000 in
  Printf.printf "Immutable record: %f updates/s\n"
    (test 5 test0 iters);
  Printf.printf "Mutable record:   %f updates/s\n"
    (test 5 test1 iters)

I tested this code with the OCaml bytecode compiler on a 1.6/2.0 GHz Intel Atom computer with Windows XP, and compiled with both the bytecode and native compilers, without optimization, on a 2.2 GHz Core2 Duo MacBook Pro computer with Mac OS X 10.5.7. The results are as follows:

SystemImmutable (upd/s)Mutable (upd/s)Speedup (Δ%)
1.6 GHz Atom/Win XP/Bytecode3,048,7803,558,71916.73
2.0 GHz Atom/Win XP/Bytecode4,000,0004,566,210 14.16
2.2 GHz Core2 Duo/Mac OS/Bytecode17,750,32420,418,58115.03
2.2 GHz Core2 Duo/Mac OS/Native128,882,58858,400,981-54.69

The speedup afforded by imperative mutation in bytecode is modest, in all cases around 15%. On the other hand, the penalty incurred by mutation under the native compiler is more than double.

Of course, my correspondent was right in that the situation with current object-oriented languages is very different. I translated the benchmark straightforwardly into Java, and the result is what "common sense" would let us expect: Java is heavily oriented to mutation, or rather, it penalizes immutability quite heavily. I tried both client and server VMs, under the Windows environment detailed above:

SystemImmutable (upd/s)Mutable (upd/s)Speedup (×)
1.6 GHz Atom/Win XP/Client22,831,050107,526,8824.71
1.6 GHz Atom/Win XP/Server37,735,849322,580,6458.55

The difference is dramatic: mutation is between 4.7 and 8.5 times faster than functional update in Java, and even twice as fast than native OCaml code on a faster machine. Moral of the story: test your assumptions with experiments. The benchmark code is:

public final class MutTest {
  private static final class Person0 {
    public final String name;
    public final int age;
    public final double balance;
    
    public Person0(String name, int age, double balance) {
      this.name = name;
      this.age = age;
      this.balance = balance;
    }
    
    public Person0 deposit(double amount) {
      return new Person0(this.name, this.age, this.balance + amount);
    }
  }
  
  private static final class Person1 {
    public String name;
    public int age;
    public double balance;
    
    public Person1(String name, int age, double balance) {
      this.name = name;
      this.age = age;
      this.balance = balance;
    }
    
    public void deposit(double amount) {
      this.balance += amount;
    }  
  }
  
  private interface Test {
    double test(int iters);
  }

  private static final Test TEST0 = new Test() {
    public double test(int iters) {
      Person0 person = new Person0("John Doe", 19, 100.0);
      for (int i = 0; i != iters; i++) {
        person = person.deposit(1.0);
      }
      return person.balance;
    }
  };
  
  private static final Test TEST1 = new Test() {
    public double test(int iters) {
      Person1 person = new Person1("John Doe", 19, 100.0);
      for (int i = 0; i != iters; i++) {
        person.deposit(1.0);
      }
      return person.balance;
    }
  };
  
  private static double test(int times, Test test, int iters) {
    long best = Long.MAX_VALUE;
    double balance;
    for (int i = 0; i != times; i++) {
      long now = System.currentTimeMillis();
      balance = test.test(iters);
      now = System.currentTimeMillis() - now;
      if (best > now)
        best = now;
    }
    return (double) iters / ((double) best / 1000.0);
  }

  public static void main(String[] args) {
    final int iters = 10000000;
    System.out.printf("Immutable record: %f updates/s\n", test(5, TEST0, iters));
    System.out.printf("Mutable record:  %f updates/s\n", test(5, TEST1, iters));
  }
}

2007-11-06

Plane Geometry in Java (III)

See also Part I and Part II.

Now that we have vectors and points, I can show how a line on the plane can be implemented:

final class Line {
  public final Pt p;
  public final Vec v;

  public Line(Pt p, Vec v) {
    if (p == null || v == null)
      throw new IllegalArgumentException("Arguments cannot be null");
    this.p = p;
    this.v = v;
  }

  public boolean equals(Object o) {
    if (o == null || !(o instanceof Line)) return false;
    else if (this == o) return true;
    final Line that = (Line) o;
    return this.p.equals(that.p) && this.v.equals(that.v);
  }

  public int hashCode() {
    return 127 * p.hashCode() + v.hashCode();
  }

  public String toString() {
    return String.format("%s-->%s", p, v);
  }

A difference with previous value classes is that we must make sure that a Line is properly constructed with actual values; other than that, the implementation is unsurprising. A basic property of a line is its slope:

  public double slope()            { return v.arg(); }

Given two lines, we might want to know whether they are parallel or perpendicular:

  private static final double EPSILON = 1e-11;

  public boolean isPerpendicular(Line l) {
    return Math.abs(v.dot(l.v)) < EPSILON;
  }

  public boolean isParallel(Line l) {
    return isPerpendicular(l.perp(l.p));
  }

This is necessarily an approximation, since it involves a subtraction. In any case, the angle between two lines is the angle between its respective direction vectors:

  public double angle(Line l)      { return v.angle(l.v); }

Our first construction on lines gives the perpendicular through a given point:

  public Line perp(Pt q)           { return new Line(q, v.perp()); }

In particular, the median between to points is the perpendicular to the line comprising both and passing through their midpoint:

  public static Line median(Pt p, Pt q) {
    return p.through(q).perp(p.mid(q));
  }

Note how the definition formalizes the English description. The second, fundamental construction is the intersection point between two lines:

  public Pt meet(Line l) {
    final Vec u = l.v.perp();
    return p.at(v.scale(u.dot(p.to(l.p)) / u.dot(v)));
  }

This is a direct translation of Property 20. If the lines are parallel, u.dot(v) is zero and the division gives the point at infinity. Another usual construction is to find the foot of a point on a given line; that is, the nearest point to it on the line:

  public Pt foot(Pt q) {
    final Vec u = v.unit();
    return p.at(u.scale(u.dot(p.to(q))));
  }

To test whether two segments (that is, the subset of the line comprised between the base point and its translate by the direction vector) intersect, check if the quadrilateral formed by said points is convex or not:

  public boolean meets(Line l) {
    final Vec u = l.v.perp();
    final Vec w = p.to(l.p);
    final double r = u.dot(w);
    final double s = v.perp().dot(w);
    final double t = u.dot(v);
    return 0 <= r && r <= t && 0 <= s && s <= t;
  }

Sometimes is useful to specify a line in implicit form, as a⋅x + b⋅y + c = 0. This constructor does so:

  public static Line implicit(double a, double b, double c) {
    final Pt p = b != 0 ? new Pt(0, c / b) : new Pt(c / a, 0);
    final Vec v = b > 0 ? new Vec(b, -a) : new Vec(-b, a);
    return new Line(p, v);
  }

Conversely, the implicit coefficients of a line can be retrieved with:

  public double[] coeffs() {
    final Vec u = v.perp();
    return new double[] { u.i, u.j, -u.dot(p.to(Pt.ORIGIN)) };
  }
}

Now we have everything in place to program simple Plane Geometry constructions. For instance, we can check that the altitudes of a triangle meet at a point. First, it is convenient to have a way to produce triangles that checks for us that we passed sensible values:

public class Geom {
  static Pt[] triangle(double a, double b, double c) {
    double t;
    if (a < b) { t = a; a = b; b = t; }
    if (b < c) { t = b; b = c; c = t; }
    if (a < b) { t = a; a = b; b = t; }
    // Now a >= b >= c
    if (a >= b + c)
      throw new IllegalArgumentException("Unsatisfied triangle inequality");

Our triangle will have the origin as its first vertex, its second vertex on the positive x-axis, and the third on the first quadrant. To find the latter, a simple system of equations involving the Pythagorean Theorem suffices:

    final double x = 0.5 * (a * a + (b + c) * (b - c))/a;
    final double y = Math.sqrt(b * b - x * x);
    return new Pt[] { Pt.ORIGIN, new Pt(a, 0), new Pt(x, y) };
  }

Since we have to find the three altitudes, another utility function will save repetition. This one-liner reads exactly as a mathematical description:

  static Line altitude(Pt a, Pt b, Pt c) {
    return a.through(b).foot(c).through(c);
  }

(albeit backwards!) Maybe this justifies writing a Tri class? Finally, the test:

  public static void main(String[] args) {
    final Pt[] tri = triangle(3, 6, 8);
    final Line u = altitude(tri[0], tri[1], tri[2]);
    final Line v = altitude(tri[1], tri[2], tri[0]);
    final Line w = altitude(tri[2], tri[0], tri[1]);
    final Pt r = u.meet(v);
    final Pt s = v.meet(w);
    System.out.printf("r = %s, s = %s\nDistance between points: %f\n", r, s, r.dist(s));
  }

The result shows, as expected, the coincidence of both points of intersection:

r = (5.68750 , 6.88204), s = (5.68750 , 6.88204)
Distance between points: 0.000000

2007-11-05

Plane Geometry in Java (II)

See also Part I and Part III.

We have our vectors ready. Now, points are entirely analogous, insofar they are value objects:

final class Pt {
  public final double x;
  public final double y;

  public Pt(double x, double y)    { this.x = x; this.y = y; }

  public static final Pt ORIGIN = new Pt(0, 0);

  public boolean equals(Object o) {
    if (o == null || !(o instanceof Pt)) return false;
    else if (this == o) return true;
    final Pt that = (Pt) o;
    return this.x == that.x && this.y == that.y;
  }

  public int hashCode() {
    return (int) ((Double.doubleToLongBits(x) >> 32) & 0xffffffffL)
         ^ (int) ((Double.doubleToLongBits(y) >> 32) & 0xffffffffL);
  }

  public String toString() {
    return String.format("(%g , %g)", x, y);
  }

There is a distinguished point, the origin.

It is important to understand the need to duplicate code that is essentially the same as in Vec; in other words, it is not appropriate to refactor common code in classes Vec and Pt, for two reasons:

  1. First, a vector is not a point, nor vice-versa. There is not even a meaningful common supertype between them. The whole point of using the typed algebra is to manipulate formulas with the added security afforded by the typing rules
  2. Second, even if a private base class could abstract some code, the bulk of the code needed to correctly implement a base type is in equals. This method needs to cast to the static class of the object in order for the comparison to be meaningful (else it would be comparing a derived class to the base class), so the duplicate equals are essential anyway

The Algebra has two "constructors" linking points and vectors: the point constructor and the vector constructor. Both operate on points, so naturally they are members of the Pt class. Also, as Axiom 1 states, both operations are some kind of additive inverses one of the other:

  public Pt at(Vec v)              { return new  Pt(x + v.i, y + v.j); }
  public Vec to(Pt p)              { return new Vec(p.x - x, p.y - y); }

A natural operation on points is to find the distance between them. It is, quite simply, p.to(q).norm(). However for convenience I include it directly in Pt:

  public double dist(Pt p)         { return to(p).norm(); }

Linear interpolation, or lerp mixes two points to give a third:

  public Pt lerp(Pt p, double k)   { return at(to(p).scale(k)); }

In particular, the midpoint between two given points is:

  public Pt mid(Pt p)              { return lerp(p, 0.5); }

The set of all linear interpolants is obviously a line. The simplest way to determine one is however to give a point through which it passes and the direction it takes:

  public Line towards(Vec v)       { return new Line(this, v); }
  public Line through(Pt p)        { return new Line(this, to(p)); }
}

I will show next how to use lines.

2007-11-02

Plane Geometry in Java (I)

See also Part II and Part III.

Algebras have computational content, and the Plane Geometry Algebra I presented is no exception. It's time to put it to test by implementing a DSL embodying it. I'll use value objects to represent geometric objects in the plane. The reason for this decision, if it is not obvious enough, is that points, vectors and lines, as geometric entities, have no meaningful state.

As pointed out in C2, value objects should be immutable; this implies that there is no point in hiding the instance variables behind setters, as the values are determined at the moment of construction. On the other hand, it is necessary to ensure proper value semantics by correctly implementing equals and hashCode.

I find it easiest to start with the class Vec, as vectors have a very well-known, rich structure that you will probably find familiar. But first, the basic Object contract:

final class Vec {
  public final double i;
  public final double j;

  public Vec(double i, double j)   { this.i = i; this.j = j; }

  public static final Vec ZERO = new Vec(0, 0);

  public boolean equals(Object o) {
    if (o == null || !(o instanceof Vec)) return false;
    else if (this == o) return true;
    final Vec that = (Vec) o;
    return this.i == that.i && this.j == that.j;
  }

  public int hashCode() {
    return (int) ((Double.doubleToLongBits(i) >> 32) & 0xffffffffL)
         ^ (int) ((Double.doubleToLongBits(j) >> 32) & 0xffffffffL);
  }

  public String toString() {
    return String.format("[%g , %g]", i, j);
  }

There is a distinguished vector, the zero vector.

In order for equals to be an equivalence relation, it must be closed on its domain (that is, it must compare meaningfully only Vecs, line 1), reflexive (line 2), symmetric and transitive. The equality operator in Java fulfills these properties, and so (line 4), using it to compare by value the coordinates ensures that the overall result conforms.

With respect to hashCode, there are many proposed methods to hash IEEE 754 doubles, but most aim at "chunking" buckets of nearby values by chopping off the least significant bits of the mantissa. To avoid clustering more in one coordinate than over the other, I mix symmetrically bits from both values using an exclusive-or.

Now, let's flesh out Vec's structure, not forgetting the perp operation in the Algebra:

  public Vec add(Vec v)            { return new Vec(i + v.i, j + v.j); }
  public Vec neg()                 { return new Vec(-i, -j); }
  public Vec scale(double k)       { return new Vec(k * i, k * j); }
  public Vec perp()                { return new Vec(-j, i); }

and endow it with a norm and a scalar product:

  public double dot(Vec v)         { return i * v.i + j * v.j; }
  public double norm()             { return Math.hypot(i, j); }
  public double arg()              { return Math.atan2(j, i); }
  public Vec unit()                { return scale(1/norm()); }

A natural operation on vectors is to find the enclosed (convex) angle between them. The dual operation is to rotate a vector by a given angle. It is well-known that the dot product between two plane vectors is proportional to the cosine of the comprised angle. By Theorem 16, the perp-dot product is proportional to the sine of the same angle. The cross product captures both proportionalities in vectorial form:

  public Vec cross(Vec v)          { return new Vec(dot(v), perp().dot(v)); }

This operation satisfies the following properties:

(0.0)  u × (v + w) = u × v + u × w
(0.1)  (u + v) × w = u × w + v × w
(0.2)  (k ⋅ u) × v = k ⋅ (u × v)
(0.3)  u × (k ⋅ v) = k ⋅ (u × v)
(0.4)  (-u) × v = u × (-v) = -(u × v)
(0.5)  (u × v)⊥ = u × v⊥
(0.6)  u × v = u⊥ × v⊥
(0.7)  u × v⊥ = -u⊥ × v

Properties (0.0) to (0.3) show that cross is linear on both arguments. This is a consequence of both the linearity of dot product and that of perp. From this, Property (0.4) is an easy consequence. Properties (0.4) to (0.7) capture the rotational invariance of the cross product, at least for quarter rotations and reflections. With this, we can define:

  public static Vec rotor(double a) {
    return new Vec(Math.cos(a), Math.sin(a));
  }

  public double angle(Vec v)       { return cross(v).arg(); }
  public Vec rotate(double a)      { return rotor(-a).cross(this); }
}

That angle correctly captures the intended functionality is clear from the definitions:

   u.angle(v)
= { Definition }
   u.cross(v).arg()
= { Definition }
   (new Vec(u.dot(v), u.perp().dot(v))).arg()
= { Properties of dot, perp-dot }
   (new Vec(|u|⋅|v|⋅cos.(θ.u.v), |u|⋅|v|⋅sin.(θ.u.v)).arg()
= { Definition arg, atan2 }
   atan.((|u|⋅|v|⋅sin.(θ.u.v)) / (|u|⋅|v|⋅cos.(θ.u.v)))
= { Algebra, definition tan }
   θ.u.v

Other properties of angle are:

(1.0)  θ.u.v = -θ.v.u
(1.1)  θ.u.v = θ.(k⋅u).v = θ.u.(k⋅v)
(1.2)  |v|⋅u.rotate(θ.u.v) = |u|⋅v
(1.3)  u × (u.rotate(a)) = |u|²⋅rotor(a)
(1.4)  θ.u.(u.rotate(a)) = a

Next, I will present points.

2007-10-05

The Ghost of Types Past

This is the second part of (Re)Visiting Expressions.

Is there a way to avoid having to wait until runtime to verify that our expressions are well-typed? Indeed, a simple application of Phantom types can make the compiler to work to our advantage. There is nothing in the application of phantom types that is specific to functional programming, except for the use of parametric polymorphism. We can use, like here, phantom types to make our Java programs type-safe, or to enforce statically (that is, in compile-time) various desirable properties of our program.

The idea is to constrain the construction of values by encoding the properties in type parameters. These constraints can go from typing ADT trees to enforcing access restrictions and static bounds-checking. As a technique, it is simplicity itself: a module exports a parametric type —which is kept abstract— but whose implementation does not depend on the type parameter. Smart constructor functions (the functional counterpart of static factories) are restricted in the module interface to various instantiations of the type parameter; the type-checker ensures that all applications are correctly typed by means of unification.

Our phantom type will wrap expressions, assigning to each a type tag T:

final class E<T> {
  private final Exp e;
  private E(Exp e) { this.e = e; }

However, values of this class will only be created by the smart constructors. For instance, an integer constant is tagged with Integer:

  public static E<Integer> con(int value) {
    return new E<Integer>(Exp.con(value));
  }

Similarly for addition and comparison, with respective tags Integer and Boolean:

  public static E<Integer> add(E<Integer> left, E<Integer> right) {
    return new E<Integer>(Exp.add(left.e, right.e));
  }
  public static E<Boolean> le(E<Integer> left, E<Integer> right) {
    return new E<Boolean>(Exp.leq(left.e, right.e));
  }

Note that the arguments are themselves tagged to codify the requirement that addition operates on two integer values and returns an integer. In this light, the constructor for a conditional:

  public static <T> E<T> cond(E<Boolean> test, E<T> ifTrue, E<T> ifFalse) {
    return new E<T>(Exp.cond(test.e, ifTrue.e, ifFalse.e));
  }

makes clear that the condition must be a boolean expression, and both the true and the false expressions must evaluate to the same type T (which has nothing to do with the class parameter, as this is a static method), which is then the type of the result.

For convenience, instances of this class know how to evaluate and print themselves out:

  private static final EvalExp evaluator = new EvalExp();
  private static final ShowExp printer   = new ShowExp();

  public Val eval() {
    return e.accept(evaluator);
  }
  public void print() {
    e.accept(printer);
  }
}

This avoids the need to expose the contents of the wrapper class; an alternative is to define a method that projects the phantom type to the type of the wrapped expression (i.e., a simple accessor).

We can now test our expressions. Our test harness becomes much simpler now that the phantom type dispatches the Visitors:

public final class PhantomTest {
  public static void main(String[] args) {
    E<Integer> e1;
    e1 = E.cond(E.le(E.con(3), E.con(5)), E.add(E.con(1), E.con(2)), E.con(0));
    e1.print();
    System.out.print(" = ");
    e1.eval().accept(new ShowVal());
    System.out.println();

    // E<?> e2 = E.cond(E.con(1), E.con(1), E.con(1));
  }
}

Running it produces the same output as before:

Cond(Leq(ConI(3),ConI(5)),Add(ConI(1),ConI(2)),ConI(0)) = 3 : int

(This is exactly the same ouput as before, which is unsurprising since the phantom type delegates blindly to the original, type-unsafe code). If you try to compile the test with the second, ill-typed expression uncommented, the compiler will complain, and will refuse to proceed:

PhantomTest.java:233: <T>cond(E<java.lang.Boolean>,E<T>,E<T>) in E cannot be
  applied to (E<java.lang.Integer>,E<java.lang.Integer>,E<java.lang.Integer>)
    E<?> e2 = E.cond(E.con(1), E.con(1), E.con(1));
               ^
1 error

As you can see, the type-checking rules of Java are being applied to detect the invalid construction of a conditional with a non-Boolean test. What is also important to remark is that it is not necessary to manually tag constructors; expressions are built out of method calls much as we've seen in the untyped case.

(Re)Visiting Expressions

Functional languages in the ML family (y compris Haskell) lend themselves naturally to interpreting the abstract syntax tree of a domain-specific language, since the former is quite naturally represented with an algebraic data type. You will see this phenomenon everywhere; to the point that I think that Greenspun's Tenth is not really an axiom but a corollary to the rather plain fact that destructuring an ADT amounts to interpreting it.

The analogous way to do this in an object-oriented language is to use the Interpreter and Visitor patterns in conjunction. I'll develop here a mini-language in Java, and I'll abstract out the different traversal strategies over both the expression and value trees by using Visitors, which will be generic on the type of the result generated.

Every language is contingent. Instead of inventing one I'll simply take Lennart Augustsson's domain-specific language of expressions:

E ::= n ∈ Z | E + E | E ≤ E | E → E : E

that is, an expression can be an integer constant, an addition, a comparison or a conditional. The result of evaluating such an expression is a value, either integer or Boolean:

V ::= n ∈ Z | b ∈ B

Visitors are used to parameterize traversals by decoupling of the traversal logic from the structure of the tree. That is, instead of adding methods to each class in a composite hierarchy, we plug in different strategies to a single interface.

Note: in traditional Object-Oriented languages the Visitor pattern calls for the accumulation of intermediate results in an instance variable; here, we'll take advantage of parametric polymorphism in Java to apply stateless Visitors whenever possible.

In our little language, a value is an abstract type that accepts a value Visitor:

abstract class Val {
  public abstract <T> T accept(ValVisitor<T> visitor);

This Visitor will produce a result of a generic type, hence the method must be generic on the type parameterizing it. The possible concrete values are integer and Boolean values:

  public static final class Int extends Val {
    public final int value;
    private Int(int value) { this.value = value; }
    public <T> T accept(ValVisitor<T> visitor) {
      return visitor.visitInt(this);
    }
  }

  public static final class Bool extends Val {
    public final boolean value;
    private Bool(boolean value) { this.value = value; }
    public <T> T accept(ValVisitor<T> visitor) {
      return visitor.visitBool(this);
    }
  }

Both are inner to Val and neither can be extended or instantiated directly. They both accept the Visitor by dispatching to the appropriate method, and forcing it to recur into their structure.

These are all the possibilities for Val, so we seal it against extension; also, we have to provide the static factories to allow our code to create values:

  private Val() { }

  public static Val ofInt(int value) { return new Int(value); }
  public static Val ofBoolean(boolean value) { return new Bool(value); }
}

This finishes the encoding of values. Now, a value Visitor must in turn discriminate between value types:

interface ValVisitor<T> {
  T visitInt(Val.Int value);
  T visitBool(Val.Bool value);
}

As a concrete example, this is a simple value printer implemented as a Visitor:

final class ShowVal implements ValVisitor<Void> {
  public Void visitInt(Val.Int value) {
    System.out.printf("%d : int", value.value);
    return null;
  }
  public Void visitBool(Val.Bool value) {
    System.out.printf("%b : bool", value.value);
    return null;
  }
}

Since there isn't really a meaningful return value from the act of printing (other than the side-effect of showing the text to the output), we use the java.lang.Void type. We are forced to return null since Void has no instances; we could have created instead a singleton type Unit, paralleling what Haskell or ML do.

An expression in our DSL is, analogously to values, an abstract type that accepts an expression Visitor:

abstract class Exp {
  public abstract <T> T accept(ExpVisitor<T> visitor);

This Visitor is also generic on the return type. For each expression kind we have a concrete type. Constant expressions are simple:

  public static final class ConI extends Exp {
    public final int value;
    private ConI(int value) { this.value = value; }
    public <T> T accept(ExpVisitor<T> visitor) {
      return visitor.visitConI(this);
    }
  }

(Again, the classes corresponding to each type constructor are sealed.) Both additions and comparisons are binary operations on expressions:

  public static final class Add extends Exp {
    public final Exp left, right;
    private Add(Exp left, Exp right) { this.left = left; this.right = right; }
    public <T> T accept(ExpVisitor<T> visitor) {
      return visitor.visitAdd(this);
    }
  }

  public static final class Leq extends Exp {
    public final Exp left, right;
    private Leq(Exp left, Exp right) { this.left = left; this.right = right; }
    public <T> T accept(ExpVisitor<T> visitor) {
      return visitor.visitLeq(this);
    }
  }

A conditional has three sub-expressions: one for the expression being tested, one for the expression to be evaluated if the test is true, and another if it is false:

  public static final class Cond extends Exp {
    public final Exp test, ifTrue, ifFalse;
    private Cond(Exp test, Exp ifTrue, Exp ifFalse) {
      this.test = test;
      this.ifTrue = ifTrue;
      this.ifFalse = ifFalse;
    }
    public <T> T accept(ExpVisitor<T> visitor) {
      return visitor.visitCond(this);
    }
  }

The definitions mirror exactly the abstract syntax outlined before. Finally, we seal the abstract Exp class and provide static factories:

  public static Exp con(int value) { return new ConI(value); }
  public static Exp add(Exp left, Exp right) { return new Add(left, right); }
  public static Exp leq(Exp left, Exp right) { return new Leq(left, right); }
  public static Exp cond(Exp test, Exp ifTrue, Exp ifFalse) { return new Cond(test, ifTrue, ifFalse); }
}

We now need to define the type of the expression Visitor:

interface ExpVisitor<T> {
  T visitConI(Exp.ConI value);
  T visitAdd(Exp.Add value);
  T visitLeq(Exp.Leq value);
  T visitCond(Exp.Cond value);
}

Again, a simple application of the Visitor is an expression printer:

final class ShowExp implements ExpVisitor<Void> {
  public Void visitConI(Exp.ConI value) {
    System.out.printf("ConI(%d)", value.value);
    return null;
  }
  public Void visitAdd(Exp.Add value) {
    System.out.print("Add(");
    value.left.accept(this);
    System.out.print(",");
    value.right.accept(this);
    System.out.print(")");
    return null;
  }
  public Void visitLeq(Exp.Leq value) {
    System.out.print("Leq(");
    value.left.accept(this);
    System.out.print(",");
    value.right.accept(this);
    System.out.print(")");
    return null;
  }
  public Void visitCond(Exp.Cond value) {
    System.out.print("Cond(");
    value.test.accept(this);
    System.out.print(",");
    value.ifTrue.accept(this);
    System.out.print(",");
    value.ifFalse.accept(this);
    System.out.print(")");
    return null;
  }
}

It now remains to write the code that will evaluate expressions down to a value. I'll present the evaluation Visitor in parts. First, since it is obvious that it will return Vals, it will be parameterized by that interface:

final class EvalExp implements ExpVisitor<Val> {

Evaluating a constant is simply a matter of extracting the value of the expression and wrapping it into an integer value:

  public Val visitConI(Exp.ConI value) {
    return Val.ofInt(value.value);
  }

Evaluating compound expressions is complicated by the fact that not all combination of types are meaningful. For instance, to evaluate an addition we must check that the addends evaluate to integer values before adding them. We begin by evaluating both sides of the sum; as noted in the comment, this corresponds to call-by-value. We then apply a value Visitor to the evaluated left-hand, which will in turn apply another value Visitor to the right-hand, which will finally return the sum:

  public Val visitAdd(Exp.Add value) {
    // Call-by-value semantics
    final Val left = value.left.accept(this);
    final Val right = value.right.accept(this);
    return left.accept(new ValVisitor<Val>() {
      public Val visitInt(final Val.Int left) {
        return right.accept(new ValVisitor<Val>() {
          public Val visitInt(final Val.Int right) {
            return Val.ofInt(left.value + right.value);
          }

This works if both operands evaluate to integers. If, however, any value does not, it is a type error:

          public Val visitBool(Val.Bool _) {
            throw new IllegalArgumentException("Bad right argument to Add");
          }
        });
      }
      public Val visitBool(Val.Bool _) {
        throw new IllegalArgumentException("Bad left argument to Add");
      }
    });
  }

(The name of the arguments are unimportant). The evaluation of a comparison is exactly analogous to that for the sum, except that, in the end, the result of the comparison is a boolean value:

  public Val visitLeq(Exp.Leq value) {
    final Val left = value.left.accept(this);
    final Val right = value.right.accept(this);
    return left.accept(new ValVisitor<Val>() {
      public Val visitInt(final Val.Int left) {
        return right.accept(new ValVisitor<Val>() {
          public Val visitInt(final Val.Int right) {
            return Val.ofBoolean(left.value <= right.value);
          }
          public Val visitBool(Val.Bool _) {
            throw new IllegalArgumentException("Bad right argument to Leq");
          }
        });
      }
      public Val visitBool(Val.Bool _) {
        throw new IllegalArgumentException("Bad left argument to Leq");
      }
    });
  }

Again, we use call-by-value by evaluating first both sides and then chaining visitors on the resulting values. Evaluating a conditional expression is simpler, fortunately. In contrast to the previous calls, a condition must lazily evaluate the correct branch depending on the result of evaluating the test. After doing that, it must visit the value and type-check that it is Boolean:

  public Val visitCond(final Exp.Cond value) {
    final Val test = value.test.accept(this);
    return test.accept(new ValVisitor<Val>() {
      public Val visitInt(Val.Int _) {
        throw new IllegalArgumentException("Bad test argument to Cond");
      }
      public Val visitBool(Val.Bool test) {
        return test.value
          ? value.ifTrue.accept(EvalExp.this)
          : value.ifFalse.accept(EvalExp.this);
      }
    });
  }
}

Note: the evaluator has a type hole, in that a conditional can evaluate to different types depending on the condition. The interpreter which inspired this one had exactly the same type unsoundess. We will see how phantom types can help us to avoid these (and other) kinds of type errors.

As it is, we can use this code to evaluate some simple expressions. We will use a test class to do this from the main entry point. But first, we show a helper method to print the expression, evaluate it and print the result. Since the evaluation can fail for an ill-typed expression, the method handles the exception and informs the programmer:

public final class PhantomTest {
  private static void eval(Exp e) {
    try {
      e.accept(new ShowExp());
      System.out.print(" = ");
      e.accept(new EvalExp()).accept(new ShowVal());
      System.out.println();
    } catch (IllegalArgumentException ex) {
      System.out.println();
      System.out.println(ex.getMessage());
    }
  }

Now we create some expressions in the main entry point and evaluate them:

  public static void main(String[] args) {
    Exp e;
    e = Exp.cond(Exp.leq(Exp.con(3), Exp.con(5)), Exp.add(Exp.con(1), Exp.con(2)), Exp.con(0));
    eval(e);
    e = Exp.cond(Exp.con(1), Exp.con(1), Exp.con(1));
    eval(e);
  }
}

The first expression is 3 ≤ 5 → 1 + 2 : 0, which obviously evaluates to 3:

Cond(Leq(ConI(3),ConI(5)),Add(ConI(1),ConI(2)),ConI(0)) = 3 : int

The second expression is 1 → 1 : 1, which is obviously ill-typed as the condition is an integer:

Cond(ConI(1),ConI(1),ConI(1)) =
Bad test argument to Cond

Next we'll see how we can add safety to our interpreter using phantom types.

2007-10-04

Algebraic Data Types and Java Generics (III)

See also Part I and Part II.

As remarked in many a monad introduction, monads are especially suited to containing and managing side-effects. This is because in general monads structure semantics: little packages of special functionality neatly tucked away and generalized under a unit, bind interface.

One typical gripe of imperative programming is resource mana'gement: how to structure the code to make sure that every resource consumed is accounted for. In the days of yore, we C programmers had to ensure that our code didn't leak memory: bytes allocated dynamically had to be freed exactly once no matter what the code path executed.

Of course, most modern languages incorporate a garbage collector that makes most if not all issues of dynamic memory allocation automatically solvable. There are other kinds of resources, however, that must still be manually managed. Typically, files and streams must be correctly opened and closed even in the face of exceptions, lest some data be corrupted and/or lost.

Also, in the absence of some sort of arbitration mechanism, concurrent file reading or writing by various actors is sure to lead to race conditions, where the data accessed depends on the scheduling order among the actors. If the operations they execute depend on the data read, the execution of the overall program is not deterministic.

Both problems could be solved if we had a way to ensure that:

  1. all files are closed after we're done with them
  2. nobody retains a reference to a closed file
  3. at most one user has access to a particular file

All three conditions can be met if we somehow make plain file handles (or streams) inaccessible. A monad is ideal for this: it guarantees that its type statically enforces (i.e., in compiler time) that these properties are upheld:

public class Input<X> implements Monad<X, Input<X>> {

The idea is to encapsulate operations on input files as a function from the stream to the result of type X of the processing:

  private final Function<BufferedReader, X> source;

  private Input(Function<BufferedReader, X> source) {
    this.source = source;
  }

The construction of Input monads will be managed by bind. It takes a function f which turns values read into another Input, and threads the input stream among them, in order:

  public <Y> Input<Y> bind(final Function<X, ? extends Monad<Y, ?>> f) {
    return new Input<Y>(new Function<BufferedReader, Y>() {
      public Y apply(BufferedReader in) {
        return ((Input<Y>) f.apply(source.apply(in))).source.apply(in);
      }
    });
  }

Unfortunately, covariance of the parameter type means that the bound function returns a type that is too general, and a down-cast is required to force the result into a Input. This code is not type-safe as it is. Note that the result of f is destructured in order to supply to it the same input stream; once this is done, it is repackaged as an Input monad of the correct (return) type.

The unit converts a delayed value into the Input monad that discards the stream and instead of its contents always returns this value:

  public static <X> Input<X> unit(final Function<Void, X> source) {
    return new Input<X>(new Function<BufferedReader, X>() {
      public X apply(BufferedReader _) { return source.apply(null); }
    });
  }

The reason why the encapsulated value is delayed is that it usually is the final result, or summary, of processing all the data read. Lastly, we need a way to actually make all this work on a file opened for input. This is as simple as opening the file, passing it to the processing function and returning the result, making sure that the code cleans after itself:

  public X run(String name) throws IOException {
    BufferedReader in = null;
    try {
      in = new BufferedReader(new FileReader(name));
      return source.apply(in);
    } catch (UncheckedException e) {
      throw (IOException) e.getCause();
    } finally {
      if (in != null)
        in.close();
    }
  }

The problem with this is that performing input might throw an exception, but the Function interface is pure. We need to encapsulate the exception in an unchecked exception, then unwrap it and pass it along.

  private static final class UncheckedException extends RuntimeException {
    public UncheckedException(Throwable cause) {
      super(cause);
    }
  }

Unfortunately, there is not much that we can do with Input, as the constructor is private and the only way to bind to an input is by having one in the first place. The simplest Input we can think of is the one that reads characters from the file and returns them, one by one, unchanged:

  public static final Input<Integer> read =
    new Input<Integer>(new Function<BufferedReader, Integer>() {
      public Integer apply(BufferedReader in) {
        try { return in.read(); }
        catch (IOException e) { throw new UncheckedException(e); }
      }
    });

Another common way of reading text files is line by line. In this case, the result of the Input operation is a String with the text of the line:

  public static final Input<String> readLine =
    new Input<String>(new Function<BufferedReader, String>() {
      public String apply(BufferedReader in) {
        try { return in.readLine(); }
        catch (IOException e) { throw new UncheckedException(e); }
      }
    });

The simplest example that I can think of is a char counter. Or a line counter. Thanks to the type wizardry, I can use the same code to do both, or indeed, to count any number of items of type X:

public class InputCounter<X> {
  private int count = 0;

At the end of the stream of items, we need to return the count:

  private final Input<Integer> finalCount =
    Input.unit(new Function<Void, Integer>() {
      public Integer apply(Void _) { return count; }
    });

This Input processor will delay looking at it until the last moment. We also need to get the next item and update the running count:

  private Input<Integer> partialCount;

We still didn't say how we'll count these mythical items: we need a way to parameterize the Input reader, and we also need a sentinel for the last item read (in other words ageneric end-of-file predicate):

  public InputCounter(Input<X> reader, final Function<X, Boolean> sentinel) {

With this, we bind the reader to a function that checks if there are any more items or not:

    this.partialCount = reader.bind(new Function<X, Input<Integer>>() {
      public Input<Integer> apply(X item) {

If not (that is, if we're at end-of-file), it returns the final count:

        if (sentinel.apply(item))
          return finalCount;

Otherwise, we increment and return the partial count.

        else {
          count++;
          return partialCount;
        }
      }
    });
  }

With this, it can run the Input on the supplied file:

  public int count(String file) throws IOException {
    count = 0;
    return partialCount.run(file);
  }
}

Let's use this in a test. We count both characters and lines by constructing the InputCounter with appropriate parameters:

public class InputTest {
  private static final Function<Integer, Boolean> isLastChar =
    new Function<Integer, Boolean>() {
      public Boolean apply(Integer ch) { return ch == -1; }
    };

  private static final Function<String, Boolean> isLastLine =
    new Function<String, Boolean>() {
      public Boolean apply(String l) { return l == null; }
    };

  public static void main(String[] args) {
    if (args.length != 1) {
      System.err.println("usage - java InputTest <file>");
      System.exit(2);
    }

    try {
      final int nchars = new InputCounter<Integer>(Input.read, isLastChar).count(args[0]);
      final int nlines = new InputCounter<String>(Input.readLine, isLastLine).count(args[0]);
      System.out.printf("File \"%s\": %d chars, %d lines\n", args[0], nchars, nlines);
      System.exit(0);
    } catch (IOException e) {
      System.err.println(e.getMessage());
      System.exit(1);
    }
  }
}

The monad ensures that no file remains open, even in the event of an exception.