public static BigRational[] solve(final BigRational[][] a, final BigRational[] b)
	{
		int n = b.length;

		for(int p = 0; p < n; p++)
		{
			// find pivot row and swap
			int max = p;
			for(int i = p + 1; i < n; i++)
			{
				if(a[i][p].abs().compareTo(a[max][p].abs()) > 0)
				{
					max = i;
				}
			}

			BigRational[] temp = a[p];
			a[p] = a[max];
			a[max] = temp;
			
			BigRational t = b[p];
			b[p] = b[max];
			b[max] = t;

			if(a[p][p].equals(BigRational.ZERO))
			{
				// singular matrix... Given that we are solving finite
				// difference system, this should probably never happen.
				throw new IllegalArgumentException("a is singular");
			}

			// pivot within a and b
			for(int i = p + 1; i < n; i++)
			{
				BigRational alpha = a[i][p].divide(a[p][p]);
				b[i] = b[i].subtract(alpha.multiply(b[p]));
								
				for(int j = p; j < n; j++)
				{
					a[i][j] = a[i][j].subtract(alpha.multiply(a[p][j]));
				}
			}
		}

		// perform back substitution to solve the system.
		BigRational[] x = new BigRational[n];
		for(int i = n - 1; i >= 0; i--)
		{
			BigRational sum = BigRational.ZERO;
			
			for(int j = i + 1; j < n; j++)
			{
				sum = sum.add(a[i][j].multiply(x[j]));
			}
			
			x[i] = (b[i].subtract(sum)).divide(a[i][i]);
		}
		
		return x;
	}