To illustrate that Modified Gram-Schmidt works, consider a \(2\times 2\) matrix as in your example. I'll use sympy to make the algebra less tedious. You can make it a \(4\times 3\) simply by adjusting the parameters.
import sympy as sp
import sympy.matrices
from sympy import init_printing
init_printing()
num_rows = 2
num_cols = 2
a = sp.Matrix([[
# Uncomment this row for symbolic math, as shown below:
"a%d%d" % (row, col)
# Uncomment this row for numerical math, as shown below:
row+col
for col in xrange(num_cols)]
for row in xrange(num_rows)])
a
a[:,0]
from sympy.matrices import zeros
r = zeros(num_rows, num_cols)
q = zeros(num_rows, num_cols)
r
What follows is just Algorithm 3.3 from the book, typed up:
a_mod = a.copy()
for k in range(num_cols):
ak = a_mod[:,k]
r[k,k] = ak.norm()
q[:,k ] = ak/ak.norm()
for j in range(k+1, num_cols):
r[k,j] = q[:,k].dot(a[:,j])
a_mod[:,j] = a_mod[:,j] - r[k,j] * q[:,k]
print sp.simplify(q[:,0].norm())
print sp.simplify(q[:,1].norm())
q
r
sp.simplify(q * r - a)