def directional_variance_gradient_i(r_i, w):
    """ computes the gradient of the directioanl variance for row_i in
        data """
    return [2 * Ch4.dot_product(r_i, direction(w)) * r_ij for r_ij in r_i]
def directional_variance_i(r_i, w):
    """" computes for row r_i the projection of r_i onto w """
    # we square this because we later sum to get a resultant vector
    return Ch4.dot_product(r_i, direction(w))**2
def project(v, w):
    """ projects vector v onto w """
    projection_length = Ch4.dot_product(v, w)
    return Ch4.scalar_multiply(projection_length, w)
def directional_variance_gradient_i(r_i, w):
    """ computes the gradient of the directioanl variance for row_i in
        data """
    return [2 * Ch4.dot_product(r_i, direction(w)) * r_ij for r_ij in r_i]
def directional_variance_i(r_i, w):
    """" computes for row r_i the projection of r_i onto w """
    # we square this because we later sum to get a resultant vector
    return Ch4.dot_product(r_i, direction(w))**2
def project(v,w):
    """ projects vector v onto w """
    projection_length = Ch4.dot_product(v,w)
    return Ch4.scalar_multiply(projection_length,w)