{- - Encode Mk 2, using a prefix table for the codes - - Paul Sanders, Systems Research, British Telecom Laboratories 1992 -} module Encode (encode) where import Defaults import PTTrees -- for convenience we make the code table type explicit type CodeTable = PrefixTree Char Int -- encode sets up the arguments for the real function. encode :: String -> [Int] encode input = encode' input first_code initial_table {- - encode' loops through the input string assembling the codes produced - by code_string. The first character is treated specially in that it - is not added to the table; its code is simply its ascii value. -} encode' [] _ _ = [] encode' input v t = case (code_string input 0 v t) of { (input', n, t') -> n : encode' input' (v + 1) t' } {- - code_string parses enough of the input string to produce one code and - returns the remaining input, the code and a new code table. - - The first character is taken and its place found in the code table. The - extension code table found for this character is then used as the lookup - table for the next character. - - If a character is not found in the current table then output the code - of the character associated with the current table and add the current - character to the current table and assign it the next new code value. -} code_string input@(c : input2) old_code next_code (PT p@(PTE k v t) l r) | c < k = (f1 r1 p r) | c > k = (f2 r2 p l) | otherwise = (f3 r3 k v l r) where r1 = code_string input old_code next_code l r2 = code_string input old_code next_code r r3 = code_string input2 v next_code t f1 (input_l,nl,l2) p r = (input_l,nl,PT p l2 r) f2 (input_r,nr,r2) p l = (input_r,nr,PT p l r2) f3 (input2,n,t2) k v l r = (input2, n, PT (PTE k v t2) l r) code_string input@(c : input_file2) old_code next_code PTNil | next_code >= 4096 = (input, old_code, PTNil) | otherwise = (input, old_code, PT (PTE c next_code PTNil) PTNil PTNil) code_string [] old_code next_code code_table = ([], old_code, PTNil) {- - We want the inital table to be balanced, but this is expensive to compute - as a rebalance is needed evert two inserts (yuk!). So we do the ordinary - infix-order binary tree insert but give the keys in such an order as to - give a balanced tree. - - (I would have defined the tree by hand but the constant was too big - for hc-0.41) -} initial_table :: CodeTable initial_table = foldr tab_insert PTNil balanced_list tab_insert n = insert (toEnum n) n balanced_list = [128,64,32,16,8,4,2,1,0,3,6,5,7,12,10,9,11,14,13,15,24,20,18,17,19,22, 21,23,28,26,25,27,30,29,31,48,40,36,34,33,35,38,37,39,44,42,41,43,46, 45,47,56,52,50,49,51,54,53,55,60,58,57,59,62,61,63,96,80,72,68,66,65] ++ bal_list2 ++ bal_list3 ++ bal_list4 ++ bal_list5 bal_list2 = [67,70,69,71,76,74,73,75,78,77,79,88,84,82,81,83,86,85,87,92,90,89,91, 94,93,95,112,104,100,98,97,99,102,101,103,108,106,105,107,110,109,111, 120,116,114,113,115,118,117,119,124,122,121,123,126,125,127,192,160] bal_list3 = [144,136,132,130,129,131,134,133,135,140,138,137,139,142,141,143,152, 148,146,145,147,150,149,151,156,154,153,155,158,157,159,176,168,164, 162,161,163,166,165,167,172,170,169,171,174,173,175,184,180,178,177] bal_list4 = [179,182,181,183,188,186,185,187,190,189,191,224,208,200,196,194,193, 195,198,197,199,204,202,201,203,206,205,207,216,212,210,209,211,214, 213,215,220,218,217,219,222,221,223,240,232,228,226,225,227,230,229, 231,236,234,233,235,238,237,239,248,244,242,241,243,246,245,247,252] bal_list5 = [250,249,251,254,253,255]