I wrote a function for the Haar wavelet transformation given that the input is a List with a power of 2. I was trying to error check by making sure that the length of the List is a power of 2 before preforming the transformation. I am comparing the log base 2 of the length of the list to see if it comes out evenly (nothing to the right of the decimal point). I think there is something going on with the if statement in haskell that I am not used to in other languages. It works perfectly if I don't error check and just call haar with the proper argument.
haar :: (Fractional a) => [a] -> [a]
haar xs = if logBase 2 (fromIntegral (length xs)) /= truncate (logBase 2 (fromIntegral (length xs)))
then error "The List must be a power of 2"
else haarHelper xs (logBase 2 (fromIntegral (length xs)))
haarHelper xs 1 = haarAvgs xs ++ haarDiffs xs
haarHelper xs level = haarHelper (haarAvgs xs ++ haarDiffs xs) (level - 1)
haarAvgs [] = []
haarAvgs (x:y:xs) = ((x + y) / 2.0) : haarAvgs xs
haarDiffs [] = []
haarDiffs (x:y:xs) = ((x - y) / 2.0) : haarDiffs xs
I am getting the following error message:
functions.hs:52:13:
Ambiguous type variable `t' in the constraints:
`Floating t'
arising from a use of `logBase' at functions.hs:52:13-48
`Integral t'
arising from a use of `truncate' at functions.hs:52:53-99
Probable fix: add a type signature that fixes these type variable(s)
Failed, modules loaded: none.
There's a much simpler and faster implementation to check that a positive integer is a power of two:
import Data.Bits
powerOfTwo' n = n .&. (n-1) == 0
(Note: this omits the check that n is positive, assuming we can rely on it coming from length.)
Explanation, for the curious:
This algorithm relies on the unique property that only powers of 2 have a single 1 bit (by definition), and decrementing them inverts all the lower bits:
2^n = 100000...
2^n - 1 = 011111...
This leaves no bits in common, making their bitwise-and zero.
For all non-powers-of-two, the decrement will leave at least the highest 1 bit unchanged, keeping the bitwise-and result non-zero.
(Wikipedia: Fast algorithm to check if a positive number is a power of two)
haar :: (Fractional a) => [a] -> [a]
haar xs | r /= (truncate r) = error "The List must be a power of 2"
| otherwise = haarHelper xs (logBase 2 (fromIntegral (length xs)))
where r = logBase 2 (fromIntegral (length xs))
Yea, seems like its something with truncate. Easier way to write if then statements with haskell is shown above. Might help with the debugging a bit.
I think i may know. I think truncate is returning an int where the other number is a float.
Try this
haar :: (Fractional a) => [a] -> [a]
haar xs | r /= w = error "The List must be a power of 2"
| otherwise = haarHelper xs (logBase 2 (fromIntegral (length xs)))
where
r = logBase 2 (fromIntegral (length xs))
w = intToFloat (truncate r)
haarHelper xs 1 = haarAvgs xs ++ haarDiffs xs
haarHelper xs level = haarHelper (haarAvgs xs ++ haarDiffs xs) (level - 1)
haarAvgs [] = []
haarAvgs (x:y:xs) = ((x + y) / 2.0) : haarAvgs xs
haarDiffs [] = []
haarDiffs (x:y:xs) = ((x - y) / 2.0) : haarDiffs xs
intToFloat :: Int -> Float
intToFloat n = fromInteger (toInteger n)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With