import math

def unit(values):
    if not values or not all(math.isfinite(x) for x in values):
        raise ValueError('nonempty finite real vector required')
    scale = max(abs(x) for x in values)
    if scale == 0:
        raise ValueError('cosine is undefined for a zero vector here')
    scaled = [x/scale for x in values]
    length = math.sqrt(math.fsum(x*x for x in scaled))
    return [x/length for x in scaled]

def cosine(a, b):
    if len(a) != len(b):
        raise ValueError('vector dimensions differ')
    ua, ub = unit(a), unit(b)
    return max(-1.0, min(1.0, math.fsum(x*y for x,y in zip(ua, ub))))

a = [1.0, 2.0]
for b in ([2.0, 4.0], [-1.0, -2.0], [2.0, -1.0]):
    print(b, round(cosine(a, b), 12))
assert abs(cosine(a, [2,4])-1) < 1e-12
assert abs(cosine(a, [-1,-2])+1) < 1e-12
assert abs(cosine(a, [2,-1])) < 1e-12
assert abs(cosine([1e308,1e308], [1e308,1e308])-1) < 1e-12
try:
    cosine(a,[0,0])
except ValueError:
    print('zero vector rejected')
else:
    raise AssertionError('zero vector must be rejected')
