2009-05-14 16:46:10 -04:00
|
|
|
! Copyright (C) 2009 Marc Fauconneau.
|
|
|
|
! See http://factorcode.org/license.txt for BSD license.
|
2009-06-13 19:47:19 -04:00
|
|
|
USING: accessors arrays assocs fry
|
2009-05-14 16:46:10 -04:00
|
|
|
hashtables io kernel locals math math.order math.parser
|
|
|
|
math.ranges multiline sequences ;
|
|
|
|
IN: compression.huffman
|
|
|
|
|
2009-05-15 02:27:00 -04:00
|
|
|
QUALIFIED-WITH: bitstreams bs
|
2009-05-14 16:46:10 -04:00
|
|
|
|
|
|
|
<PRIVATE
|
|
|
|
|
|
|
|
! huffman codes
|
|
|
|
|
|
|
|
TUPLE: huffman-code
|
|
|
|
{ value }
|
|
|
|
{ size }
|
|
|
|
{ code } ;
|
|
|
|
|
|
|
|
: <huffman-code> ( -- code ) 0 0 0 huffman-code boa ;
|
2009-08-13 20:21:44 -04:00
|
|
|
: next-size ( code -- ) [ 1 + ] change-size [ 2 * ] change-code drop ;
|
|
|
|
: next-code ( code -- ) [ 1 + ] change-code drop ;
|
2009-05-14 16:46:10 -04:00
|
|
|
|
|
|
|
:: all-patterns ( huff n -- seq )
|
|
|
|
n log2 huff size>> - :> free-bits
|
|
|
|
free-bits 0 >
|
|
|
|
[ free-bits 2^ [0,b) [ huff code>> free-bits 2^ * + ] map ]
|
|
|
|
[ huff code>> free-bits neg 2^ /i 1array ] if ;
|
|
|
|
|
|
|
|
:: huffman-each ( tdesc quot: ( huff -- ) -- )
|
|
|
|
<huffman-code> :> code
|
|
|
|
tdesc
|
|
|
|
[
|
|
|
|
code next-size
|
|
|
|
[ code (>>value) code clone quot call code next-code ] each
|
|
|
|
] each ; inline
|
|
|
|
|
|
|
|
: update-reverse-table ( huff n table -- )
|
|
|
|
[ drop all-patterns ]
|
|
|
|
[ nip '[ _ swap _ set-at ] each ] 3bi ;
|
|
|
|
|
|
|
|
:: reverse-table ( tdesc n -- rtable )
|
|
|
|
n f <array> <enum> :> table
|
|
|
|
tdesc [ n table update-reverse-table ] huffman-each
|
|
|
|
table seq>> ;
|
|
|
|
|
|
|
|
:: huffman-table ( tdesc max -- table )
|
|
|
|
max f <array> :> table
|
|
|
|
tdesc [ [ ] [ value>> ] bi table set-nth ] huffman-each
|
|
|
|
table ;
|
|
|
|
|
|
|
|
PRIVATE>
|
|
|
|
|
|
|
|
! decoder
|
|
|
|
|
|
|
|
TUPLE: huffman-decoder
|
|
|
|
{ bs }
|
|
|
|
{ tdesc }
|
|
|
|
{ rtable }
|
|
|
|
{ bits/level } ;
|
|
|
|
|
2009-06-13 19:47:19 -04:00
|
|
|
: <huffman-decoder> ( bs tdesc -- decoder )
|
|
|
|
huffman-decoder new
|
|
|
|
swap >>tdesc
|
|
|
|
swap >>bs
|
2009-05-14 16:46:10 -04:00
|
|
|
16 >>bits/level
|
|
|
|
[ ] [ tdesc>> ] [ bits/level>> 2^ ] tri reverse-table >>rtable ;
|
|
|
|
|
|
|
|
: read1-huff ( decoder -- elt )
|
|
|
|
16 over [ bs>> bs:peek ] [ rtable>> nth ] bi ! first/last
|
|
|
|
[ size>> swap bs>> bs:seek ] [ value>> ] bi ;
|
|
|
|
|
|
|
|
! %remove
|
|
|
|
: reverse-bits ( value bits -- value' )
|
|
|
|
[ >bin ] [ CHAR: 0 pad-head <reversed> bin> ] bi* ;
|
|
|
|
|
|
|
|
: read1-huff2 ( decoder -- elt )
|
|
|
|
16 over [ bs>> bs:peek 16 reverse-bits ] [ rtable>> nth ] bi ! first/last
|
|
|
|
[ size>> swap bs>> bs:seek ] [ value>> ] bi ;
|
|
|
|
|
|
|
|
/*
|
|
|
|
: huff>string ( code -- str )
|
|
|
|
[ value>> number>string ]
|
|
|
|
[ [ code>> ] [ size>> bits>string ] bi ] bi
|
|
|
|
" = " glue ;
|
|
|
|
|
|
|
|
: huff. ( code -- ) huff>string print ;
|
|
|
|
|
|
|
|
:: rtable. ( rtable -- )
|
|
|
|
rtable length>> log2 :> n
|
|
|
|
rtable <enum> [ swap n bits. [ huff. ] each ] assoc-each ;
|
|
|
|
*/
|