-- Test program that tickles suspected bug in nhc98's Integer div/mod code. -- Should output all the decimal places of sqrt(2): 1414.. -- Martin Guy, Newcastle, October 2004. module Main where import IO -- for hSetBeffering & friends main :: IO () main = hSetBuffering stdout NoBuffering >> putStr (concat (map show (m_sqrt [0,2]))) base :: Int base = 10 -- Square root by Mr C. Woo's abacus algorithm -- See http://freaknet.org/martin/tape -> "Algorithms" -> "Square root" -- for details of the algorithm. m_sqrt :: [Int] -> [Int] m_sqrt [] = [] -- sqrt(0) m_sqrt m = m_sqrt' (0, (toInteger a,x)) where (a:x) = m_sqrbase m -- prime sqrt engine with first digit -- Convert mantissa in base n to mantissa in base n^2. m_sqrbase :: [Int] -> [Int] m_sqrbase (a:b:m) = (a * base + b) : m_sqrbase m m_sqrbase [a] = [a * base] m_sqrbase [] = [] m_sqrt' :: (Integer,(Integer,[Int])) -> [Int] m_sqrt' (r1,(hd_o1,tl_o1)) | (hd_o1 == 0 && m_is_zero tl_o1) = [] | otherwise = ( fromInteger (r2 `mod` ibase)) : m_sqrt' (r2 * ibase, m_sqrt_shiftin (hd_o2,tl_o1)) where (r2,hd_o2) = m_sqrt_loop (r1,hd_o1) ibase = toInteger base -- Is the value of a mantissa equal to zero m_is_zero [] = True m_is_zero (a:x) = if a /= 0 then False else m_is_zero x -- Shift another term of the operand into the calculation. m_sqrt_shiftin :: (Integer, [Int]) -> (Integer, [Int]) m_sqrt_shiftin (a,b:x) = (a * sqr_base + toInteger b, x) m_sqrt_shiftin (a,[]) = (a * sqr_base, []) sqr_base = toInteger (base * base) m_sqrt_loop :: (Integer,Integer) -> (Integer,Integer) m_sqrt_loop ro = until sqrt_loop_done sqrt_loop_body ro where sqrt_loop_done (r, o) = 2*r >= o -- was: 2*r+1 > o sqrt_loop_body (r, o) = (r+1, o - (2*r+1))