import config, image
import global math

float h0, h1, h2, h3
float g0, g1, g2, g3

def transform_row_to_column(V *v, int w, b, V *out):
    int w2 = b * (w / 2)
    int i2 = 0
    for int i = 0; i < w - 3; i += 2:
        out[i2]      = v[i] * h0 + v[i + 1] * h1 + v[i + 2] * h2 + v[i + 3] * h3
        out[w2 + i2] = v[i] * g0 + v[i + 1] * g1 + v[i + 2] * g2 + v[i + 3] * g3
        i2 += b
    # What to do at the right edge where v[i + 2] and v[i + 3] do not exist?
    # We assume the last value just goes on.
    V bv = v[w - 1]
    out[i2]      = v[w - 2] * h0 + bv * h1 + bv * h2 + bv * h3
    out[w2 + i2] = v[w - 2] * g0 + bv * g1 + bv * g2 + bv * g3

V *def daubechies(V *image, int w, h):
    float r3 = sqrt(3)
    float r32 = sqrt(32)

    h0 = (1 + r3) / r32
    h1 = (3 + r3) / r32
    h2 = (3 - r3) / r32
    h3 = (1 - r3) / r32

    g0 = h3
    g1 = -h2
    g2 = h1
    g3 = -h0

    V *result = ALLOCATE(w * h * sizeof *image)
    V *temp = ALLOCATE(w * h * sizeof *image)
    V *previous = image
    for int k= 0; k < 4; k++:
        int s = 1 << k
        # horizontal (to vertical)
        for int j = 0; j < h / s; j++:
            transform_row_to_column(previous + j * w, w / s, h, temp + j)
        # vertical (back to horizontal)
        for int i = 0; i < w / s; i++:
            transform_row_to_column(temp + i * h, h / s, w, result + i)
        previous = result
    FREE(temp)
    return result

Image *def apply_2d_daubechies(Image const *source):
    Image *image = BtoV(source)
    V *data = daubechies(image->data.v, image->w, image->h)
    FREE(image->data.v)
    image->data.v = data
    Image *result = VtoB(image)
    image_del(image)
    return result
