def bits.in.character = 8, number.of.characters= 1 << bits.in.character, number.of.codes = number.of.characters + 1, character.mask = not ((not 0) << bits.in.character): def root = 0, size.of.tree = (2* number.of.codes)-1, not.a.node = size.of.tree: var escape, weight[size.of.tree], children[size.of.tree], parent[size.of.tree], character[size.of.tree], representative[number.of.characters] : proc construct.tree = -- Create a tree for the encoding in which every character is escaped seq escape := root weight[escape] := 1 children[escape] := root -- it is a leaf seq ch= [0 for number.of.characters] representative[ch] := not.a.node : proc create.leaf(var new.leaf, value ch) = -- Extend the tree by fision of the escape leaf into two new leaves var new.escape: seq new.leaf := escape + 1 new.escape := escape + 2 children[escape] := new.leaf -- escape is the new parent weight[new.leaf] := 0 children[new.leaf] := root parent[new.leaf] := escape character[new.leaf] := ch representative[ch /\ character.mask] := new.leaf weight[new.escape] := 1 children[new.escape]:= root parent[new.escape] := escape escape := new.escape : proc swap.trees(value i, j) = -- Exchange disjoint sub-trees routed at i and j proc swap.words(var p,q) = -- Exchange values stored in p and q var t: seq t := p p := q q := t : proc adjust.offspring(value i) = -- Restore downstream pointers to node i if children[i] = root representative[character[i] /\ character.mask] := i children[i] <> root seq child=[children[i] for 2] parent[child] := i : seq swap.words(children[i], children[j]) swap.words(character[i], character[j]) adjust.offspring(i) adjust.offspring(j) : proc increment.frequency(value ch) = -- Adjust the weights of all relevant nodes to account for one more occurence -- of the character ch, and adjust the shape of the tree if necessary var node: seq if representative[ch /\ character.mask] <> not.a.node node := representative[ch /\ character.mask] representative[ch /\ character.mask] = not.a.node create.leaf(node, ch) while node <> root if weight[node-1] > weight[node] seq weight[node] := weight[node] + 1 node := parent[node] weight[node-1] = weight[node] if i= [1 for (node-root)-1] weight[(node-i)-1] > weight[node] seq swap.trees(node, node-i) node := node-i weight[root] := weight[root] + 1 : proc encode.character(chan output, value ch) = -- Transmit the encoding of ch along output def size.of.encoding = bits.in.character + (number.of.codes - 1) : var encoding[size.of.encoding], length, node: seq if representative[ch /\ character.mask] <> not.a.node seq length := 0 node := representative[ch /\ character.mask] representative[ch /\ character.mask] = not.a.node seq seq i=[0 for bits.in.character] encoding[i] := (ch >> i) /\ 1 -- i'th bit of unencoded ch length := bits.in.character node := escape while node <> root seq encoding[length] := node - children[parent[node]] length := length + 1 node := parent[node] seq i= [1 for length] output ! encoding[length-i] : proc decode.character(chan input, var ch) = -- Receive an encoding along input and store the corresponding character in ch var node: seq node := root while children[node] <> root var bit: seq input ? bit node := children[node] + bit if node < escape ch := character[node] node = escape var bit: seq input ? bit ch := -bit seq i= [2 for bits.in.character - 1] seq input ? bit ch := (ch << 1) \/ bit : def end.of.message = -1: proc copy.encoding(chan source, sink) = -- Read a stream of characters from source, until signalled on end.of.source, -- and transmit their encodings in sequence along sink, followed by that of -- end.of.message, maintaining throughout the encoding tree for the encoding -- determined by the cumulative frequencies of the characters transmitted var more.characters.expected: seq construct.tree more.characters.expected := true while more.characters.expected var ch: seq source ? ch if ch <> end.of.message seq encode.character(sink, ch) increment.frequency(ch) ch = end.of.message more.characters.expected := false encode.character(sink, end.of.message) : proc copy.decoding(chan source, sink) = -- Read the encodings of a stream of characters, up to and including the -- encoding of end.of.message, from source and transmit the corresponding -- characters along sink, maintaining the encoding tree for encoding -- determined by the cumulative frequencies of the characters received var more.characters.expected: seq construct.tree more.characters.expected := true while more.characters.expected var ch: seq decode.character(source, ch) if ch <> end.of.message seq sink ! ch increment.frequency(ch) ch = end.of.message more.characters.expected:=false : var choose: seq input ? choose if choose='e' copy.encoding(input, output) choose='d' copy.decoding(input, output)