import config

def haar_transform(V const *indata, int n, instep,
    V *outlow, int lowstep, V *outhigh, int highstep):
    """
    Given a signal of n samples, return low and highband of the wavelet
    transform, downsampled by half.
    """
    V const *v = indata
    V *vl = outlow, *vh = outhigh
    int s1 = instep
    int s2 = instep * 2
    int ii = 0, li = 0, hi = 0
    # Note: includes also the sqrt(2) factor
    V const r2 = sqrt(2) * sqrt(2)
    V const h0 = 1 / r2
    V const h1 = 1 / r2
    V const g0 = 1 / r2
    V const g1 = -1 / r2
    for int i = 0; i < n; i += 2:
        vl[li] = v[ii] * h0 + v[ii + s1] * h1
        vh[hi] = v[ii] * g0 + v[ii + s1] * g1
        ii += s2
        li += lowstep
        hi += highstep

def haar_transform_no_key(V const *indata, int n, instep,
    V *outlow, int lowstep, V *outhigh, int highstep, char const *key):
    haar_transform(indata, n, instep, outlow, lowstep, outhigh, highstep)

V **def haar(V const *s, int n):
    """
    This expects a signal of n samples, and will return (full-length, not
    downsampled) low and high pass results for each subdivision level.
    """
    int l = ceil(log2(n));
    V **r = ALLOCATE(l * 2 * sizeof(V *))

    int step = 1
    V const *p = s
    for int i = 0; i < l; i++:
        V outlow[n / step / 2]
        V outhigh[n / step / 2]
        haar_transform(p, n / step, step, outlow, 1, outhigh, 1)

        step <<= 1

        # Hm, we upsample here again as that's the expected format
        # (by duplicating each value)
        # TODO: hm..
        r[i * 2] = ALLOCATE(n * sizeof(V))
        for int j = 0; j < n; j++:
            r[i * 2][j] = outlow[j / step]

        r[i * 2 + 1] = ALLOCATE(n * sizeof(V))
        for int j = 0; j < n; j++:
            r[i * 2 + 1][j] = outhigh[j / step]

        # In each step, re-use the low band. Also, ignore the artificial
        # upsampling..
        p = r[i * 2]

    return r