public static void solve
		(double[] d,
		 double[] e,
		 double[] f,
		 double[] b,
		 double[] x)
		{
		// Verify preconditions.
		int N = d.length;
		if (N < 2)
			{
			throw new IllegalArgumentException
				("Tridiagonal.solve(): d.length = " + d.length + " illegal");
			}
		if (e.length != N-1)
			{
			throw new IllegalArgumentException
				("Tridiagonal.solve(): e.length = " + e.length + " illegal");
			}
		if (f.length != N-1)
			{
			throw new IllegalArgumentException
				("Tridiagonal.solve(): f.length = " + f.length + " illegal");
			}
		if (b.length != N)
			{
			throw new IllegalArgumentException
				("Tridiagonal.solve(): b.length = " + b.length + " illegal");
			}
		if (x.length != N)
			{
			throw new IllegalArgumentException
				("Tridiagonal.solve(): x.length = " + x.length + " illegal");
			}

		// Working storage.
		double[] alpha = new double [N];
		double[] z = new double [N];

		// Elimination of sub-diagonal. alpha = new diagonal, z = new right hand
		// side.
		alpha[0] = d[0];
		z[0] = b[0];
		if (alpha[0] == 0.0)
			{
			throw new DomainException
				("Tridiagonal.solve(): Zero on diagonal");
			}
		for (int i = 1; i < N; ++ i)
			{
			double t = f[i-1] / alpha[i-1];
			alpha[i] = d[i] - t * e[i-1];
			z[i] = b[i] - t * z[i-1];
			if (alpha[i] == 0.0)
				{
				throw new DomainException
					("Tridiagonal.solve(): Zero on diagonal");
				}
			}

		// Back substitution.
		int Nminus1 = N - 1;
		x[Nminus1] = z[Nminus1] / alpha[Nminus1];
		for (int i = N-2; i >= 0; -- i)
			{
			x[i] = (z[i] - e[i] * x[i+1]) / alpha[i];
			}
		}