Arithmetic coding/As a generalized change of radix: Difference between revisions

m
 
(17 intermediate revisions by 9 users not shown)
Line 14:
Verify the implementation by decoding the results back into strings and checking for equality with the given strings.
 
=={{header|C#|C sharp11l}}==
{{trans|Python}}
 
<syntaxhighlight lang="11l">F cumulative_freq(freq)
[Int = Int] cf
V total = 0
L(b) 256
I b C freq
cf[b] = total
total += freq[b]
R cf
 
F arithmethic_coding(bytes, radix)
 
DefaultDict[Int, Int] freq
L(b) bytes
freq[b.code]++
 
V cf = cumulative_freq(freq)
 
BigInt base = bytes.len
 
BigInt lower = 0
 
BigInt pf = 1
 
L(b) bytes
lower = lower * base + cf[b.code] * pf
pf *= freq[b.code]
 
V upper = lower + pf
 
BigInt power = 0
L
pf I/= radix
I pf == 0
L.break
power++
 
V enc = (upper - 1) I/ BigInt(radix) ^ power
R (enc, power, freq)
 
F arithmethic_decoding(=enc, radix, =power, freq)
 
enc *= radix ^ power
 
V base = sum(freq.values())
 
V cf = cumulative_freq(freq)
 
[Int = Int] dict
L(k, v) cf
dict[v] = k
 
Int? lchar
L(i) 0 .< base
I i C dict
lchar = dict[i]
E I lchar != N
dict[i] = lchar
 
V decoded = ‘’
L(i) (base - 1 .< -1).step(-1)
power = BigInt(base) ^ i
V div = enc I/ power
 
V c = dict[Int(div)]
V fv = freq[c]
V cv = cf[c]
 
V rem = (enc - power * cv) I/ fv
 
enc = rem
decoded ‘’= Char(code' c)
 
R decoded
 
V radix = 10
 
L(str) ‘DABDDB DABDDBBDDBA ABRACADABRA TOBEORNOTTOBEORTOBEORNOT’.split(‘ ’)
V (enc, power, freq) = arithmethic_coding(str, radix)
V dec = arithmethic_decoding(enc, radix, power, freq)
 
print(‘#<25=> #19 * #.^#.’.format(str, enc, radix, power))
 
I str != dec
X.throw RuntimeError("\tHowever that is incorrect!")</syntaxhighlight>
 
{{out}}
<pre>
DABDDB => 251 * 10^2
DABDDBBDDBA => 167351 * 10^6
ABRACADABRA => 7954170 * 10^4
TOBEORNOTTOBEORTOBEORNOT => 1150764267498783364 * 10^15
</pre>
 
=={{header|C sharp|C#}}==
{{trans|Java}}
<langsyntaxhighlight lang="csharp">using System;
using System.Collections.Generic;
using System.Linq;
Line 144 ⟶ 240:
}
}
}</langsyntaxhighlight>
{{out}}
<pre>DABDDB => 251 * 10^2
Line 153 ⟶ 249:
=={{header|D}}==
{{trans|Go}}
<langsyntaxhighlight Dlang="d">import std.array;
import std.bigint;
import std.stdio;
Line 304 ⟶ 400:
}
}
}</langsyntaxhighlight>
{{out}}
<pre>DABDDB => 251 * 10^2
Line 312 ⟶ 408:
 
=={{header|Go}}==
<langsyntaxhighlight lang="go">package main
 
import (
Line 474 ⟶ 570:
}
}
}</langsyntaxhighlight>
{{out}}
<pre>
Line 482 ⟶ 578:
TOBEORNOTTOBEORTOBEORNOT => 1150764267498783364 * 10^15
</pre>
 
=={{header|Groovy}}==
{{trans|Java}}
<syntaxhighlight lang="groovy">class ArithmeticCoding {
private static class Triple<A, B, C> {
A a
B b
C c
 
Triple(A a, B b, C c) {
this.a = a
this.b = b
this.c = c
}
}
 
private static class Freq extends HashMap<Character, Long> {
// type alias
}
 
private static Freq cumulativeFreq(Freq freq) {
long total = 0
Freq cf = new Freq()
for (int i = 0; i < 256; ++i) {
char c = i
Long v = freq.get(c)
if (null != v) {
cf.put(c, total)
total += v
}
}
return cf
}
 
private static Triple<BigInteger, Integer, Freq> arithmeticCoding(String str, Long radix) {
// Convert the string into a char array
char[] chars = str.toCharArray()
 
// The frequency characters
Freq freq = new Freq()
for (char c : chars) {
if (freq.containsKey(c)) {
freq.put(c, freq[c] + 1)
} else {
freq.put(c, 1)
}
}
 
// The cumulative frequency
Freq cf = cumulativeFreq(freq)
 
// Base
BigInteger base = chars.length
 
// LowerBound
BigInteger lower = BigInteger.ZERO
 
// Product of all frequencies
BigInteger pf = BigInteger.ONE
 
// Each term is multiplied by the product of the
// frequencies of all previously occurring symbols
for (char c : chars) {
BigInteger x = cf[c]
lower = lower * base + x * pf
pf = pf * freq[c]
}
 
// Upper bound
BigInteger upper = lower + pf
 
int powr = 0
BigInteger bigRadix = radix
 
while (true) {
pf = pf.divide(bigRadix)
if (BigInteger.ZERO == pf) {
break
}
powr++
}
 
BigInteger diff = (upper - BigInteger.ONE).divide(bigRadix.pow(powr))
return new Triple<BigInteger, Integer, Freq>(diff, powr, freq)
}
 
private static String arithmeticDecoding(BigInteger num, long radix, int pwr, Freq freq) {
BigInteger powr = radix
BigInteger enc = num * powr.pow(pwr)
long base = 0
for (Long v : freq.values()) base += v
 
// Create the cumulative frequency table
Freq cf = cumulativeFreq(freq)
 
// Create the dictionary
Map<Long, Character> dict = new HashMap<>()
for (Map.Entry<Character, Long> entry : cf.entrySet()) dict[entry.value] = entry.key
 
// Fill the gaps in the dictionary
long lchar = -1
for (long i = 0; i < base; ++i) {
Character v = dict[i]
if (null != v) {
lchar = v
} else if (lchar != -1) {
dict[i] = lchar as Character
}
}
 
// Decode the input number
StringBuilder decoded = new StringBuilder((int) base)
BigInteger bigBase = base
for (long i = base - 1; i >= 0; --i) {
BigInteger pow = bigBase.pow((int) i)
BigInteger div = enc.divide(pow)
Character c = dict[div.longValue()]
BigInteger fv = freq[c]
BigInteger cv = cf[c]
BigInteger diff = enc - pow * cv
enc = diff.divide(fv)
decoded.append(c)
}
// Return the decoded output
return decoded.toString()
}
 
static void main(String[] args) {
long radix = 10
String[] strings = ["DABDDB", "DABDDBBDDBA", "ABRACADABRA", "TOBEORNOTTOBEORTOBEORNOT"]
String fmt = "%-25s=> %19s * %d^%s\n"
for (String str : strings) {
Triple<BigInteger, Integer, Freq> encoded = arithmeticCoding(str, radix)
String dec = arithmeticDecoding(encoded.a, radix, encoded.b, encoded.c)
System.out.printf(fmt, str, encoded.a, radix, encoded.b)
if (!Objects.equals(str, dec)) throw new RuntimeException("\tHowever that is incorrect!")
}
}
}</syntaxhighlight>
{{out}}
<pre>DABDDB => 251 * 10^2
DABDDBBDDBA => 167351 * 10^6
ABRACADABRA => 7954170 * 10^4
TOBEORNOTTOBEORTOBEORNOT => 1150764267498783364 * 10^15</pre>
 
=={{header|J}}==
Line 487 ⟶ 727:
Implementation:
 
<langsyntaxhighlight Jlang="j">NB. generate a frequency dictionary from a reference string
aekDict=:verb define
d=. ~.y NB. dictionary lists unique characters
Line 538 ⟶ 778:
echo 'Decoded:'
echo ' ',":dict (#y) aekDec aekEnc y
)</langsyntaxhighlight>
 
Example use:
 
<langsyntaxhighlight Jlang="j"> aek 'DABDDB'
Dictionary:
A 1r6
Line 593 ⟶ 833:
1150764267498783364 15
Decoded:
TOBEORNOTTOBEORTOBEORNOT</langsyntaxhighlight>
 
Note that for this task we use our plaintext to generate our dictionary for decoding. Also note that we use rational numbers, rather than floating point, for our dictionary, because floating point tends to be inexact.
Line 599 ⟶ 839:
=={{header|Java}}==
{{trans|Kotlin}}
<langsyntaxhighlight Javalang="java">import java.math.BigInteger;
import java.util.HashMap;
import java.util.Map;
Line 736 ⟶ 976:
}
}
}</langsyntaxhighlight>
{{out}}
<pre>DABDDB => 251 * 10^2
Line 742 ⟶ 982:
ABRACADABRA => 7954170 * 10^4
TOBEORNOTTOBEORTOBEORNOT => 1150764267498783364 * 10^15</pre>
 
=={{header|JavaScript}}==
{{trans|C#}}
<syntaxhighlight lang="javascript">
function CumulativeFreq(freq) {
let total = 0;
const cf = new Map();
for (let i = 0; i < 256; i++) {
const c = String.fromCharCode(i);
if (freq.has(c)) {
const v = freq.get(c);
cf.set(c, total);
total += v;
}
}
return cf;
}
 
function ArithmeticCoding(str, radix) {
const freq = new Map();
for (let i = 0; i < str.length; i++) {
const c = str[i].toString();
if (freq.has(c)) freq.set(c, freq.get(c) + 1);
else freq.set(c, 1);
}
const cf = CumulativeFreq(freq);
const base = BigInt(str.length);
let lower = BigInt(0);
let pf = BigInt(1);
for (let i = 0; i < str.length; i++) {
const c = str[i].toString();
const x = BigInt(cf.get(c));
lower = lower * base + x * pf;
pf = pf * BigInt(freq.get(c));
}
let upper = lower + pf;
let powr = 0n;
const bigRadix = BigInt(radix);
while (true) {
pf = pf / bigRadix;
if (pf === 0n) break;
powr++;
}
const diff = (upper - 1n) / (bigRadix ** powr)
return { Item1: diff, Item2: powr, Item3: freq };
}
 
function ArithmeticDecoding(num, radix, pwr, freq) {
const powr = BigInt(radix);
let enc = BigInt(num) * powr ** BigInt(pwr);
let sum = 0;
freq.forEach(value => sum += value);
const base = sum;
 
const cf = CumulativeFreq(freq);
const dict = new Map();
cf.forEach((value, key) => dict.set(value, key));
 
let lchar = -1;
for (let i = 0; i < base; i++) {
if (dict.has(i)) lchar = dict.get(i).charCodeAt(0);
else if (lchar !== -1) dict.set(i, String.fromCharCode(lchar));
}
const decoded = new Array(base);
const bigBase = BigInt(base);
for (let i = base - 1; i >= 0; --i) {
const pow = bigBase ** BigInt(i);
const div = enc / pow;
const c = dict.get(Number(div));
const fv = BigInt(freq.get(c));
const cv = BigInt(cf.get(c));
const diff = BigInt(enc - pow * cv);
enc = diff / fv;
decoded[base - 1 - i] = c;
}
return decoded.join("");
}
 
function Main() {
const radix = 10;
const strings = ["DABDDB", "DABDDBBDDBA", "ABRACADABRA", "TOBEORNOTTOBEORTOBEORNOT"];
for (const str of strings) {
const encoded = ArithmeticCoding(str, radix);
const dec = ArithmeticDecoding(encoded.Item1, radix, encoded.Item2, encoded.Item3);
console.log(`${str.padEnd(25, " ")}=> ${encoded.Item1.toString(10).padStart(19, " ")} * ${radix}^${encoded.Item2}`);
if (str !== dec) {
throw new Error("\tHowever that is incorrect!");
}
}
}
</syntaxhighlight>
{{out}}
<pre>DABDDB => 251 * 10^2
DABDDBBDDBA => 167351 * 10^6
ABRACADABRA => 7954170 * 10^4
TOBEORNOTTOBEORTOBEORNOT => 1150764267498783364 * 10^15</pre>
 
=={{header|Julia}}==
Taken from the wikipedia example.
<syntaxhighlight lang="julia">function charfreq(s)
d = Dict()
for c in s
if haskey(d, c)
d[c] += 1
else
d[c] = 1
end
end
d
end
 
function charcumfreq(dfreq)
lastval = 0
d = Dict()
for c in sort!(collect(keys(dfreq)))
d[c] = lastval
lastval += dfreq[c]
end
d
end
 
function L(s, dfreq, dcumfreq)
nbase = BigInt(length(s))
lsum, cumprod = BigInt(0), 1
for (i, c) in enumerate(s)
lsum += nbase^(nbase - i) * dcumfreq[c] * cumprod
cumprod *= dfreq[c]
end
lsum
end
 
U(l, s, dfreq) = l + prod(c -> dfreq[c], s)
 
function mostzeros(low, high)
z = Int(floor(log10(high - low)))
if z == 0
return string(low), 0
end
if low <= parse(BigInt, string(high)[1:end- z - 1] * "0"^(z + 1)) <= high
z += 1
end
return string(high)[1:end-z], z
end
 
function msgnum(s)
dfreq = charfreq(s)
dcumfreq = charcumfreq(dfreq)
low = L(s, dfreq, dcumfreq)
high = U(low, s, dfreq)
return mostzeros(low, high), dfreq
end
 
function decode(encoded, fdict)
cdict, bas = charcumfreq(fdict), sum(values(fdict))
kys = sort!(collect(keys(cdict)))
revdict = Dict([(cdict[k], k) for k in kys])
lastkey = revdict[0]
for i in 0:bas
if !haskey(revdict, i)
revdict[i] = lastkey
else
lastkey = revdict[i]
end
end
rem = parse(BigInt, encoded)
s = ""
for i in 1:bas
basepow = BigInt(bas)^(bas -i)
c = revdict[div(rem, basepow)]
s *= c
rem = div(rem - basepow * cdict[c], fdict[c])
end
s
end
 
for s in ["DABDDB", "DABDDBBDDBA", "ABRACADABRA", "TOBEORNOTTOBEORTOBEORNOT"]
(encoded, z), dfreq = msgnum(s)
println(lpad(s, 30), " ", rpad(encoded, 19), " * 10^", rpad(z, 4), " ",
decode(encoded * "0"^z, dfreq))
end
</syntaxhighlight>{{out}}
<pre>
DABDDB 251 * 10^2 DABDDB
DABDDBBDDBA 16735 * 10^7 DABDDBBDDBA
ABRACADABRA 795417 * 10^5 ABRACADABRA
TOBEORNOTTOBEORTOBEORNOT 1150764267498783364 * 10^15 TOBEORNOTTOBEORTOBEORNOT
</pre>
 
=={{header|Kotlin}}==
{{trans|Go}}
<langsyntaxhighlight lang="scala">// version 1.2.10
 
import java.math.BigInteger
Line 871 ⟶ 1,298:
if (str != dec) throw Exception("\tHowever that is incorrect!")
}
}</langsyntaxhighlight>
 
{{out}}
Line 880 ⟶ 1,307:
TOBEORNOTTOBEORTOBEORNOT => 1150764267498783364 * 10^15
</pre>
 
=={{header|Nim}}==
{{trans|Kotlin}}
{{libheader|bignum}}
<syntaxhighlight lang="nim">import strformat, sugar, tables
import bignum
 
type Freq = CountTable[char]
 
 
proc cumulativeFreq(freq: Freq): Freq =
var total = 0
for c in '\0'..'\255':
result.inc c, total
inc total, freq[c]
 
 
func arithmeticCoding(str: string; radix: int): (Int, int, Freq) =
 
let freq = str.toCountTable() # The frequency characters.
let cf = cumulativeFreq(freq) # The cumulative frequency.
let base = newInt(str.len) # Base.
var lower = newInt(0) # Lower bound.
var pf = newInt(1) # Product of all frequencies.
 
# Each term is multiplied by the product of the
# frequencies of all previously occurring symbols.
for c in str:
lower = lower * base + cf[c] * pf
pf *= freq[c]
 
let upper = lower + pf # Upper bound.
var powr = 0
 
while true:
pf = pf div radix
if pf.isZero: break
inc powr
 
let diff = (upper - 1) div radix.pow(powr.culong)
result = (diff, powr, freq)
 
 
func arithmeticDecoding(num: Int; radix, pwr: int; freq: Freq): string =
var enc = num * radix.pow(pwr.culong)
var base = 0
for v in freq.values: base += v
 
# Create the cumulative frequency table.
let cf = cumulativeFreq(freq)
 
# Create the dictionary.
let dict = collect(newTable, for k in '\0'..'\255': {cf[k]: k})
 
# Fill the gaps in the dictionary.
var lchar = -1
for i in 0..<base:
if i in dict:
lchar = ord(dict[i])
elif lchar >= 0:
dict[i] = chr(lchar)
 
# Decode the input number.
for i in countdown(base - 1, 0):
let p = base.pow(i.culong)
let d = enc div p
let c = dict[d.toInt]
let diff = enc - p * cf[c]
enc = diff div freq[c]
result.add c
 
 
const Radix = 10
const Strings = ["DABDDB", "DABDDBBDDBA", "ABRACADABRA", "TOBEORNOTTOBEORTOBEORNOT"]
for str in Strings:
let (enc, pow, freq) = arithmeticCoding(str, Radix)
let dec = arithmeticDecoding(enc, Radix, pow, freq)
echo &"{str:<25}→ {enc:>19} * {Radix}^{pow}"
doAssert str == dec, "\tHowever that is incorrect!"</syntaxhighlight>
 
{{out}}
<pre>DABDDB → 251 * 10^2
DABDDBBDDBA → 167351 * 10^6
ABRACADABRA → 7954170 * 10^4
TOBEORNOTTOBEORTOBEORNOT → 1150764267498783364 * 10^15</pre>
 
=={{header|Perl}}==
<langsyntaxhighlight lang="perl">use Math::BigInt (try => 'GMP');
 
sub cumulative_freq {
Line 991 ⟶ 1,503:
die "\tHowever that is incorrect!";
}
}</langsyntaxhighlight>
{{out}}
<pre>
DABDDB => 251 * 10^2
DABDDBBDDBA => 167351 * 10^6
ABRACADABRA => 7954170 * 10^4
TOBEORNOTTOBEORTOBEORNOT => 1150764267498783364 * 10^15
</pre>
 
=={{header|Perl 6}}==
<lang perl6>sub cumulative_freq(%freq) {
my %cf;
my $total = 0;
for %freq.keys.sort -> $c {
%cf{$c} = $total;
$total += %freq{$c};
}
return %cf;
}
 
sub arithmethic_coding($str, $radix) {
my @chars = $str.comb;
 
# The frequency characters
my %freq;
%freq{$_}++ for @chars;
 
# The cumulative frequency table
my %cf = cumulative_freq(%freq);
 
# Base
my $base = @chars.elems;
 
# Lower bound
my $L = 0;
 
# Product of all frequencies
my $pf = 1;
 
# Each term is multiplied by the product of the
# frequencies of all previously occurring symbols
for @chars -> $c {
$L = $L*$base + %cf{$c}*$pf;
$pf *= %freq{$c};
}
 
# Upper bound
my $U = $L + $pf;
 
my $pow = 0;
loop {
$pf div= $radix;
last if $pf == 0;
++$pow;
}
 
my $enc = ($U - 1) div ($radix ** $pow);
($enc, $pow, %freq);
}
 
sub arithmethic_decoding($encoding, $radix, $pow, %freq) {
 
# Multiply encoding by radix^pow
my $enc = $encoding * $radix**$pow;
 
# Base
my $base = [+] %freq.values;
 
# Create the cumulative frequency table
my %cf = cumulative_freq(%freq);
 
# Create the dictionary
my %dict;
for %cf.kv -> $k,$v {
%dict{$v} = $k;
}
 
# Fill the gaps in the dictionary
my $lchar;
for ^$base -> $i {
if (%dict{$i}:exists) {
$lchar = %dict{$i};
}
elsif (defined $lchar) {
%dict{$i} = $lchar;
}
}
 
# Decode the input number
my $decoded = '';
for reverse(^$base) -> $i {
 
my $pow = $base**$i;
my $div = $enc div $pow;
 
my $c = %dict{$div};
my $fv = %freq{$c};
my $cv = %cf{$c};
 
my $rem = ($enc - $pow*$cv) div $fv;
 
$enc = $rem;
$decoded ~= $c;
}
 
# Return the decoded output
return $decoded;
}
 
my $radix = 10; # can be any integer greater or equal with 2
 
for <DABDDB DABDDBBDDBA ABRACADABRA TOBEORNOTTOBEORTOBEORNOT> -> $str {
my ($enc, $pow, %freq) = arithmethic_coding($str, $radix);
my $dec = arithmethic_decoding($enc, $radix, $pow, %freq);
 
printf("%-25s=> %19s * %d^%s\n", $str, $enc, $radix, $pow);
 
if ($str ne $dec) {
die "\tHowever that is incorrect!";
}
}</lang>
{{out}}
<pre>
Line 1,123 ⟶ 1,515:
{{trans|Go}}
{{trans|Kotlin}}
{{libheader|Phix/mpfr}}
<lang Phix>include bigatom.e
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
function cumulative_freq(sequence freq)
<span style="color: #008080;">include</span> <span style="color: #004080;">mpfr</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span>
integer total = 0,
l = length(freq)
<span style="color: #008080;">function</span> <span style="color: #000000;">cumulative_freq</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">freq</span><span style="color: #0000FF;">)</span>
sequence cf = repeat(-1,l)
<span style="color: #004080;">integer</span> <span style="color: #000000;">total</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span>
for c=1 to l do
<span style="color: #000000;">l</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">freq</span><span style="color: #0000FF;">)</span>
integer v = freq[c]
<span style="color: #004080;">sequence</span> <span style="color: #000000;">cf</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">l</span><span style="color: #0000FF;">)</span>
if v!=0 then
<span style="color: #008080;">for</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">l</span> <span style="color: #008080;">do</span>
cf[c] = total
<span style="color: #004080;">integer</span> <span style="color: #000000;">v</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">freq</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c</span><span style="color: #0000FF;">]</span>
total += v
<span style="color: #008080;">if</span> <span style="color: #000000;">v</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
end if
<span style="color: #000000;">cf</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">total</span>
end for
<span style="color: #000000;">total</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">v</span>
return cf
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end function
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">cf</span>
function arithmethic_coding(string str, integer radix)
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
sequence freq = repeat(0,256)
for i=1 to length(str) do
<span style="color: #008080;">function</span> <span style="color: #000000;">arithmethic_coding</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">str</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">radix</span><span style="color: #0000FF;">)</span>
freq[str[i]+1] += 1
<span style="color: #004080;">sequence</span> <span style="color: #000000;">freq</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">256</span><span style="color: #0000FF;">)</span>
end for
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">str</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
sequence cf = cumulative_freq(freq)
<span style="color: #000000;">freq</span><span style="color: #0000FF;">[</span><span style="color: #000000;">str</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
integer base = length(str)
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
bigatom lo = BA_ZERO, -- lower bound
<span style="color: #004080;">sequence</span> <span style="color: #000000;">cf</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">cumulative_freq</span><span style="color: #0000FF;">(</span><span style="color: #000000;">freq</span><span style="color: #0000FF;">)</span>
pf = BA_ONE -- product of all frequencies
<span style="color: #004080;">integer</span> <span style="color: #000000;">base</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">str</span><span style="color: #0000FF;">)</span>
-- Each term is multiplied by the product of the
<span style="color: #004080;">mpz</span> <span style="color: #000000;">lo</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_init</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">-- lower bound</span>
-- frequencies of all previously occurring symbols
<span style="color: #000000;">pf</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_init</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">-- product of all frequencies</span>
for i=1 to length(str) do
<span style="color: #000000;">t1</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_init</span><span style="color: #0000FF;">(),</span> <span style="color: #000080;font-style:italic;">-- temp</span>
integer c = str[i]+1
<span style="color: #000000;">t2</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_init</span><span style="color: #0000FF;">(),</span> <span style="color: #000080;font-style:italic;">-- temp</span>
integer x = cf[c]
<span style="color: #000000;">hi</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_init</span><span style="color: #0000FF;">(),</span> <span style="color: #000080;font-style:italic;">-- upper bound</span>
lo = ba_add(ba_mul(lo,base),ba_mul(x,pf))
<span style="color: #000000;">diff</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_init</span><span style="color: #0000FF;">()</span>
pf = ba_mul(pf,freq[c])
<span style="color: #000080;font-style:italic;">-- Each term is multiplied by the product of the
end for
-- frequencies of all previously occurring symbols</span>
bigatom hi = ba_add(lo,pf) -- upper bound
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">str</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
integer powr = 0
<span style="color: #004080;">integer</span> <span style="color: #000000;">c</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">str</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]+</span><span style="color: #000000;">1</span>
while true do
<span style="color: #004080;">integer</span> <span style="color: #000000;">x</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">cf</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c</span><span style="color: #0000FF;">]</span>
pf = ba_idiv(pf,radix)
<span style="color: #7060A8;">mpz_mul_si</span><span style="color: #0000FF;">(</span><span style="color: #000000;">t1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">lo</span><span style="color: #0000FF;">,</span><span style="color: #000000;">base</span><span style="color: #0000FF;">)</span>
if pf=BA_ZERO then exit end if
<span style="color: #7060A8;">mpz_mul_si</span><span style="color: #0000FF;">(</span><span style="color: #000000;">t2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pf</span><span style="color: #0000FF;">,</span><span style="color: #000000;">x</span><span style="color: #0000FF;">)</span>
powr += 1
<span style="color: #7060A8;">mpz_add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lo</span><span style="color: #0000FF;">,</span><span style="color: #000000;">t1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">t2</span><span style="color: #0000FF;">)</span>
end while
<span style="color: #7060A8;">mpz_mul_si</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pf</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pf</span><span style="color: #0000FF;">,</span><span style="color: #000000;">freq</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c</span><span style="color: #0000FF;">])</span>
bigatom diff = ba_idiv(ba_sub(hi,1),ba_power(radix,powr))
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
return {diff, powr, freq}
<span style="color: #7060A8;">mpz_add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">hi</span><span style="color: #0000FF;">,</span><span style="color: #000000;">lo</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pf</span><span style="color: #0000FF;">)</span>
end function
<span style="color: #004080;">integer</span> <span style="color: #000000;">powr</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #008080;">while</span> <span style="color: #004600;">true</span> <span style="color: #008080;">do</span>
function arithmethic_decoding(bigatom num, integer radix, pwr, sequence freq)
<span style="color: #0000FF;">{}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_fdiv_q_ui</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pf</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pf</span><span style="color: #0000FF;">,</span><span style="color: #000000;">radix</span><span style="color: #0000FF;">)</span>
bigatom enc = ba_mul(num,ba_power(radix,pwr))
<span style="color: #008080;">if</span> <span style="color: #7060A8;">mpz_cmp_si</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pf</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
integer base = sum(freq)
<span style="color: #000000;">powr</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
sequence cf = cumulative_freq(freq)
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
sequence dict = repeat(0,base+1)
<span style="color: #7060A8;">mpz_sub_ui</span><span style="color: #0000FF;">(</span><span style="color: #000000;">hi</span><span style="color: #0000FF;">,</span><span style="color: #000000;">hi</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
for i=1 to length(cf) do
<span style="color: #7060A8;">mpz_ui_pow_ui</span><span style="color: #0000FF;">(</span><span style="color: #000000;">t1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">radix</span><span style="color: #0000FF;">,</span><span style="color: #000000;">powr</span><span style="color: #0000FF;">)</span>
integer v = cf[i]
<span style="color: #7060A8;">mpz_fdiv_q</span><span style="color: #0000FF;">(</span><span style="color: #000000;">diff</span><span style="color: #0000FF;">,</span><span style="color: #000000;">hi</span><span style="color: #0000FF;">,</span><span style="color: #000000;">t1</span><span style="color: #0000FF;">)</span>
if v!=-1 then dict[v+1] = i-1 end if
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">diff</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">powr</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">freq</span><span style="color: #0000FF;">}</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
-- Fill the gaps in the dictionary
integer lchar = -1
<span style="color: #008080;">function</span> <span style="color: #000000;">arithmethic_decoding</span><span style="color: #0000FF;">(</span><span style="color: #004080;">mpz</span> <span style="color: #000000;">num</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">radix</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">pwr</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">freq</span><span style="color: #0000FF;">)</span>
for i=0 to base do
<span style="color: #004080;">mpz</span> <span style="color: #000000;">enc</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_init</span><span style="color: #0000FF;">(),</span>
integer v = dict[i+1]
<span style="color: #000000;">pow</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_init</span><span style="color: #0000FF;">(),</span>
if v!=0 then
<span style="color: #000000;">tmp</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_init</span><span style="color: #0000FF;">()</span>
lchar = v
<span style="color: #7060A8;">mpz_ui_pow_ui</span><span style="color: #0000FF;">(</span><span style="color: #000000;">enc</span><span style="color: #0000FF;">,</span><span style="color: #000000;">radix</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pwr</span><span style="color: #0000FF;">)</span>
elsif lchar!=-1 then
<span style="color: #7060A8;">mpz_mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">enc</span><span style="color: #0000FF;">,</span><span style="color: #000000;">num</span><span style="color: #0000FF;">,</span><span style="color: #000000;">enc</span><span style="color: #0000FF;">)</span>
dict[i+1] = lchar
<span style="color: #004080;">integer</span> <span style="color: #000000;">base</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sum</span><span style="color: #0000FF;">(</span><span style="color: #000000;">freq</span><span style="color: #0000FF;">)</span>
end if
<span style="color: #004080;">sequence</span> <span style="color: #000000;">cf</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">cumulative_freq</span><span style="color: #0000FF;">(</span><span style="color: #000000;">freq</span><span style="color: #0000FF;">)</span>
end for
<span style="color: #004080;">sequence</span> <span style="color: #000000;">dict</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">base</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
-- Decode the input number
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cf</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
string decoded = ""
<span style="color: #004080;">integer</span> <span style="color: #000000;">v</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">cf</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
for i=base-1 to 0 by -1 do
<span style="color: #008080;">if</span> <span style="color: #000000;">v</span><span style="color: #0000FF;">!=-</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span> <span style="color: #000000;">dict</span><span style="color: #0000FF;">[</span><span style="color: #000000;">v</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
bigatom pow = ba_power(base,i)
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
integer div = bigatom_to_atom(ba_idiv(enc,pow)),
<span style="color: #000080;font-style:italic;">-- Fill the gaps in the dictionary</span>
c = dict[div+1],
<span style="color: #004080;">integer</span> <span style="color: #000000;">lchar</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span>
fv = freq[c+1],
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">base</span> <span style="color: #008080;">do</span>
cv = cf[c+1]
<span style="color: #004080;">integer</span> <span style="color: #000000;">v</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">dict</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
bigatom diff = ba_sub(enc,ba_mul(pow,cv))
<span style="color: #008080;">if</span> <span style="color: #000000;">v</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
enc = ba_idiv(diff,fv)
<span style="color: #000000;">lchar</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">v</span>
decoded &= c
<span style="color: #008080;">elsif</span> <span style="color: #000000;">lchar</span><span style="color: #0000FF;">!=-</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
end for
<span style="color: #000000;">dict</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">lchar</span>
return decoded
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end function
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
 
<span style="color: #000080;font-style:italic;">-- Decode the input number</span>
constant tests = {"DABDDB", "DABDDBBDDBA", "ABRACADABRA", "TOBEORNOTTOBEORTOBEORNOT"},
<span style="color: #004080;">string</span> <span style="color: #000000;">decoded</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span>
radix = 10
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">base</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">0</span> <span style="color: #008080;">by</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
<span style="color: #7060A8;">mpz_ui_pow_ui</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pow</span><span style="color: #0000FF;">,</span><span style="color: #000000;">base</span><span style="color: #0000FF;">,</span><span style="color: #000000;">i</span><span style="color: #0000FF;">)</span>
for i=1 to length(tests) do
<span style="color: #7060A8;">mpz_fdiv_q</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tmp</span><span style="color: #0000FF;">,</span><span style="color: #000000;">enc</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pow</span><span style="color: #0000FF;">)</span>
string str = tests[i]
<span style="color: #004080;">integer</span> <span style="color: #000000;">div</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_get_integer</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tmp</span><span style="color: #0000FF;">),</span>
{bigatom enc, integer pow, sequence freq} = arithmethic_coding(str, radix)
<span style="color: #000000;">c</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">dict</span><span style="color: #0000FF;">[</span><span style="color: #000000;">div</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">],</span>
string dec = arithmethic_decoding(enc, radix, pow, freq),
<span style="color: #000000;">fv</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">freq</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">],</span>
ok = iff(str=dec?"(ok)":"***ERROR***"),
<span style="color: #000000;">cv</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">cf</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
encs = ba_sprint(enc)
<span style="color: #7060A8;">mpz_mul_si</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tmp</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pow</span><span style="color: #0000FF;">,</span><span style="color: #000000;">cv</span><span style="color: #0000FF;">)</span>
printf(1,"%-25s=> %19s * %d^%d %s\n",{str, encs, radix, pow, ok})
<span style="color: #7060A8;">mpz_sub</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tmp</span><span style="color: #0000FF;">,</span><span style="color: #000000;">enc</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tmp</span><span style="color: #0000FF;">)</span>
end for</lang>
<span style="color: #0000FF;">{}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_fdiv_q_ui</span><span style="color: #0000FF;">(</span><span style="color: #000000;">enc</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tmp</span><span style="color: #0000FF;">,</span><span style="color: #000000;">fv</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">decoded</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">c</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">decoded</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">tests</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"DABDDB"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"DABDDBBDDBA"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"ABRACADABRA"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"TOBEORNOTTOBEORTOBEORNOT"</span><span style="color: #0000FF;">},</span>
<span style="color: #000000;">radix</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">10</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tests</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">str</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tests</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
<span style="color: #0000FF;">{</span><span style="color: #004080;">mpz</span> <span style="color: #000000;">enc</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">pow</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">freq</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">arithmethic_coding</span><span style="color: #0000FF;">(</span><span style="color: #000000;">str</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">radix</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">dec</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">arithmethic_decoding</span><span style="color: #0000FF;">(</span><span style="color: #000000;">enc</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">radix</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">pow</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">freq</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">ok</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">str</span><span style="color: #0000FF;">=</span><span style="color: #000000;">dec</span><span style="color: #0000FF;">?</span><span style="color: #008000;">"(ok)"</span><span style="color: #0000FF;">:</span><span style="color: #008000;">"***ERROR***"</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">encs</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_get_str</span><span style="color: #0000FF;">(</span><span style="color: #000000;">enc</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%-25s=&gt; %19s * %d^%d %s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">str</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">encs</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">radix</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">pow</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ok</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
Line 1,222 ⟶ 1,632:
=={{header|Python}}==
{{works with|Python|3.1+}}
<langsyntaxhighlight lang="python">from collections import Counter
 
def cumulative_freq(freq):
Line 1,319 ⟶ 1,729:
 
if str != dec:
raise Exception("\tHowever that is incorrect!")</langsyntaxhighlight>
{{out}}
<pre>
DABDDB => 251 * 10^2
DABDDBBDDBA => 167351 * 10^6
ABRACADABRA => 7954170 * 10^4
TOBEORNOTTOBEORTOBEORNOT => 1150764267498783364 * 10^15
</pre>
 
=={{header|Raku}}==
(formerly Perl 6)
<syntaxhighlight lang="raku" line>sub cumulative_freq(%freq) {
my %cf;
my $total = 0;
for %freq.keys.sort -> $c {
%cf{$c} = $total;
$total += %freq{$c};
}
return %cf;
}
 
sub arithmethic_coding($str, $radix) {
my @chars = $str.comb;
 
# The frequency characters
my %freq;
%freq{$_}++ for @chars;
 
# The cumulative frequency table
my %cf = cumulative_freq(%freq);
 
# Base
my $base = @chars.elems;
 
# Lower bound
my $L = 0;
 
# Product of all frequencies
my $pf = 1;
 
# Each term is multiplied by the product of the
# frequencies of all previously occurring symbols
for @chars -> $c {
$L = $L*$base + %cf{$c}*$pf;
$pf *= %freq{$c};
}
 
# Upper bound
my $U = $L + $pf;
 
my $pow = 0;
loop {
$pf div= $radix;
last if $pf == 0;
++$pow;
}
 
my $enc = ($U - 1) div ($radix ** $pow);
($enc, $pow, %freq);
}
 
sub arithmethic_decoding($encoding, $radix, $pow, %freq) {
 
# Multiply encoding by radix^pow
my $enc = $encoding * $radix**$pow;
 
# Base
my $base = [+] %freq.values;
 
# Create the cumulative frequency table
my %cf = cumulative_freq(%freq);
 
# Create the dictionary
my %dict;
for %cf.kv -> $k,$v {
%dict{$v} = $k;
}
 
# Fill the gaps in the dictionary
my $lchar;
for ^$base -> $i {
if (%dict{$i}:exists) {
$lchar = %dict{$i};
}
elsif (defined $lchar) {
%dict{$i} = $lchar;
}
}
 
# Decode the input number
my $decoded = '';
for reverse(^$base) -> $i {
 
my $pow = $base**$i;
my $div = $enc div $pow;
 
my $c = %dict{$div};
my $fv = %freq{$c};
my $cv = %cf{$c};
 
my $rem = ($enc - $pow*$cv) div $fv;
 
$enc = $rem;
$decoded ~= $c;
}
 
# Return the decoded output
return $decoded;
}
 
my $radix = 10; # can be any integer greater or equal with 2
 
for <DABDDB DABDDBBDDBA ABRACADABRA TOBEORNOTTOBEORTOBEORNOT> -> $str {
my ($enc, $pow, %freq) = arithmethic_coding($str, $radix);
my $dec = arithmethic_decoding($enc, $radix, $pow, %freq);
 
printf("%-25s=> %19s * %d^%s\n", $str, $enc, $radix, $pow);
 
if ($str ne $dec) {
die "\tHowever that is incorrect!";
}
}</syntaxhighlight>
{{out}}
<pre>
Line 1,329 ⟶ 1,860:
 
=={{header|Ruby}}==
<langsyntaxhighlight lang="ruby">def cumulative_freq(freq)
cf = {}
total = 0
Line 1,437 ⟶ 1,968:
raise "\tHowever that is incorrect!"
end
end</langsyntaxhighlight>
{{out}}
<pre>
Line 1,445 ⟶ 1,976:
TOBEORNOTTOBEORTOBEORNOT => 1150764267498783364 * 10^15
</pre>
 
=={{header|Scala}}==
{{Out}}Best seen in running your browser either by [https://scalafiddle.io/sf/EUNJ0zp/0 ScalaFiddle (ES aka JavaScript, non JVM)] or [https://scastie.scala-lang.org/DVl840oDS2mFvFQ560fxJAScastie (remote JVM)].
<syntaxhighlight lang="scala">object ArithmeticCoding extends App {
val (radix, strings) = (10, Seq("DABDDB", "DABDDBBDDBA", "ABRACADABRA", "TOBEORNOTTOBEORTOBEORNOT"))
val fmt = "%-25s=> %19s * %d^%s"
 
def arithmeticDecoding( num: BigInt, radix: Int, pwr: Int, freq: Map[Char, Long]): String = {
var enc = num * BigInt(radix).pow(pwr)
val base: Long = freq.map { case (_: Char, v: Long) => v }.sum
 
// Create the cumulative frequency table
val cf = cumulativeFreq(freq)
// Create the dictionary
val dict0: Map[Long, Char] = cf.map { el: (Char, Long) => (el._2, el._1) }
 
var lchar = -1
val dict: Map[Long, Char] = (0L until base)
.map { i =>
val v: Option[Char] = dict0.get(i)
if (v.isDefined) {
lchar = v.get.toInt
(i, v.get)
} else if (lchar != -1) (i, lchar.toChar)
else (-1L, ' ')
}.filter(_ != (-1, ' ')).toMap
 
// Decode the input number
val (bigBase, decoded) = (BigInt(base), new StringBuilder(base.toInt))
for (i <- base - 1 to 0L by -1) {
val pow = bigBase.pow(i.toInt)
val div = enc / pow
val c = dict(div.longValue)
val diff = enc - (pow * cf(c))
enc = diff / freq(c)
decoded.append(c)
}
decoded.mkString
}
 
def cumulativeFreq(freq: Map[Char, Long]): Map[Char, Long] = {
var total = 0L
 
// freq.toSeq.scanLeft(('_', 0L)){ case ((_, acc), (x, y)) => (x, (acc + y))}.filter(_ !=('_', 0L) ).toMap
freq.toSeq.sortBy(_._1).map { case (k, v) => val temp = total; total += v; (k, temp) }.toMap
}
 
private def arithmeticCoding( str: String, radix: Int): (BigInt, Int, Map[Char, Long]) = {
val freq = str.toSeq.groupBy(c => c).map { el: (Char, Seq[Char]) =>
(el._1, el._2.length.toLong)
}
val cf = cumulativeFreq(freq)
var (lower, pf) = (BigInt(0), BigInt(1))
 
// Each term is multiplied by the product of the
// frequencies of all previously occurring symbols
for (c <- str) {
lower = (lower * str.length) + cf(c) * pf
pf = pf * freq(c)
}
// Upper bound
var powr = 0
val (bigRadix, upper) = (BigInt(radix.toLong), lower + pf)
do { pf = pf / bigRadix
if (pf != 0) powr += 1
} while (pf != 0)
((upper - 1) / bigRadix.pow(powr), powr, freq)
}
 
for (str <- strings) {
val encoded = arithmeticCoding(str, radix)
 
def dec =
arithmeticDecoding(num = encoded._1, radix = radix, pwr = encoded._2, freq = encoded._3)
 
println(fmt.format(str, encoded._1, radix, encoded._2))
if (str != dec) throw new RuntimeException("\tHowever that is incorrect!")
}
}</syntaxhighlight>
 
=={{header|Sidef}}==
<langsyntaxhighlight lang="ruby">func cumulative_freq(freq) {
var cf = Hash()
var total = 0
Line 1,554 ⟶ 2,164:
die "\tHowever that is incorrect!"
}
}</langsyntaxhighlight>
{{out}}
<pre>DABDDB => 251 * 10^2
DABDDBBDDBA => 167351 * 10^6
ABRACADABRA => 7954170 * 10^4
TOBEORNOTTOBEORTOBEORNOT => 1150764267498783364 * 10^15</pre>
 
=={{header|Visual Basic .NET}}==
{{trans|C#}}
<syntaxhighlight lang="vbnet">Imports System.Numerics
Imports System.Text
Imports Freq = System.Collections.Generic.Dictionary(Of Char, Long)
Imports Triple = System.Tuple(Of System.Numerics.BigInteger, Integer, System.Collections.Generic.Dictionary(Of Char, Long))
 
Module Module1
 
Function CumulativeFreq(freq As Freq) As Freq
Dim total As Long = 0
Dim cf As New Freq
For i = 0 To 255
Dim c = Chr(i)
If freq.ContainsKey(c) Then
Dim v = freq(c)
cf(c) = total
total += v
End If
Next
Return cf
End Function
 
Function ArithmeticCoding(str As String, radix As Long) As Triple
'The frequency of characters
Dim freq As New Freq
For Each c In str
If freq.ContainsKey(c) Then
freq(c) += 1
Else
freq(c) = 1
End If
Next
 
'The cumulative frequency
Dim cf = CumulativeFreq(freq)
 
' Base
Dim base As BigInteger = str.Length
 
' Lower bound
Dim lower As BigInteger = 0
 
' Product of all frequencies
Dim pf As BigInteger = 1
 
' Each term is multiplied by the product of the
' frequencies of all previously occuring symbols
For Each c In str
Dim x = cf(c)
lower = lower * base + x * pf
pf = pf * freq(c)
Next
 
' Upper bound
Dim upper = lower + pf
 
Dim powr = 0
Dim bigRadix As BigInteger = radix
 
While True
pf = pf / bigRadix
If pf = 0 Then
Exit While
End If
powr = powr + 1
End While
 
Dim diff = (upper - 1) / (BigInteger.Pow(bigRadix, powr))
Return New Triple(diff, powr, freq)
End Function
 
Function ArithmeticDecoding(num As BigInteger, radix As Long, pwr As Integer, freq As Freq) As String
Dim powr As BigInteger = radix
Dim enc = num * BigInteger.Pow(powr, pwr)
Dim base = freq.Values.Sum()
 
' Create the cumulative frequency table
Dim cf = CumulativeFreq(freq)
 
' Create the dictionary
Dim dict As New Dictionary(Of Long, Char)
For Each key In cf.Keys
Dim value = cf(key)
dict(value) = key
Next
 
' Fill the gaps in the dictionary
Dim lchar As Long = -1
For i As Long = 0 To base - 1
If dict.ContainsKey(i) Then
lchar = AscW(dict(i))
Else
dict(i) = ChrW(lchar)
End If
Next
 
' Decode the input number
Dim decoded As New StringBuilder
Dim bigBase As BigInteger = base
For i As Long = base - 1 To 0 Step -1
Dim pow = BigInteger.Pow(bigBase, i)
Dim div = enc / pow
Dim c = dict(div)
Dim fv = freq(c)
Dim cv = cf(c)
Dim diff = enc - pow * cv
enc = diff / fv
decoded.Append(c)
Next
 
' Return the decoded ouput
Return decoded.ToString()
End Function
 
Sub Main()
Dim radix As Long = 10
Dim strings = {"DABDDB", "DABDDBBDDBA", "ABRACADABRA", "TOBEORNOTTOBEORTOBEORNOT"}
For Each St In strings
Dim encoded = ArithmeticCoding(St, radix)
Dim dec = ArithmeticDecoding(encoded.Item1, radix, encoded.Item2, encoded.Item3)
Console.WriteLine("{0,-25}=> {1,19} * {2}^{3}", St, encoded.Item1, radix, encoded.Item2)
If St <> dec Then
Throw New Exception(vbTab + "However that is incorrect!")
End If
Next
End Sub
 
End Module</syntaxhighlight>
{{out}}
<pre>DABDDB => 251 * 10^2
DABDDBBDDBA => 167351 * 10^6
ABRACADABRA => 7954170 * 10^4
TOBEORNOTTOBEORTOBEORNOT => 1150764267498783364 * 10^15</pre>
 
=={{header|Wren}}==
{{trans|Kotlin}}
{{libheader|Wren-big}}
{{libheader|Wren-fmt}}
<syntaxhighlight lang="wren">import "./big" for BigInt
import "./fmt" for Fmt
 
var cumulativeFreq = Fn.new { |freq|
var total = 0
var cf = {}
for (i in 0..255) {
var c = i
var v = freq[c]
if (v) {
cf[c] = total
total = total + v
}
}
return cf
}
 
var arithmeticCoding = Fn.new { |str, radix|
// Convert the string into a character list
var chars = str.bytes.toList
 
// The frequency characters
var freq = {}
for (c in chars) {
if (!freq[c]) {
freq[c] = 1
} else {
freq[c] = freq[c] + 1
}
}
 
// The cumulative frequency
var cf = cumulativeFreq.call(freq)
 
// Base
var base = BigInt.new(chars.count)
 
// LowerBound
var lower = BigInt.zero
 
// Product of all frequencies
var pf = BigInt.one
 
// Each term is multiplied by the product of the
// frequencies of all previously occurring symbols
for (c in chars) {
var x = BigInt.new(cf[c])
lower = lower * base + x * pf
pf = pf * BigInt.new(freq[c])
}
 
// Upper bound
var upper = lower + pf
 
var powr = 0
var bigRadix = BigInt.new(radix)
 
while (true) {
pf = pf / bigRadix
if (pf == BigInt.zero) break
powr = powr + 1
}
 
var diff = (upper - BigInt.one) / bigRadix.pow(powr)
return [diff, powr, freq]
}
 
var arithmeticDecoding = Fn.new { |num, radix, pwr, freq|
var powr = BigInt.new(radix)
var enc = num * powr.pow(pwr)
var base = 0
for (v in freq.values) base = base + v
 
// Create the cumulative frequency table
var cf = cumulativeFreq.call(freq)
 
// Create the dictionary
var dict = {}
for (me in cf) dict[me.value] = me.key
 
// Fill the gaps in the dictionary
var lchar = -1
for (i in 0...base) {
var v = dict[i]
if (v) {
lchar = v
} else if (lchar != -1) {
dict[i] = lchar
}
}
 
// Decode the input number
var decoded = ""
var bigBase = BigInt.new(base)
for (i in base-1..0) {
var pow = bigBase.pow(i)
var div = enc / pow
var c = dict[div.toSmall]
var fv = BigInt.new(freq[c])
var cv = BigInt.new(cf[c])
var diff = enc - pow * cv
enc = diff / fv
decoded = decoded + String.fromByte(c)
}
// Return the decoded output
return decoded
}
 
var radix = 10
var strings = ["DABDDB", "DABDDBBDDBA", "ABRACADABRA", "TOBEORNOTTOBEORTOBEORNOT"]
var fmt = "$-25s=> $19s * $d^$s"
for (str in strings) {
var res = arithmeticCoding.call(str, radix)
var enc = res[0]
var pow = res[1]
var freq = res[2]
var dec = arithmeticDecoding.call(enc, radix, pow, freq)
Fmt.print(fmt, str, enc, radix, pow)
if (str != dec) Fiber.abort("\tHowever that is incorrect!")
}</syntaxhighlight>
 
{{out}}
<pre>
Line 1,565 ⟶ 2,441:
=={{header|zkl}}==
Uses libGMP (GNU MP Bignum Library)
<langsyntaxhighlight lang="zkl">var [const] BN=Import("zklBigNum"); // libGMP
 
fcn cumulativeFreq(freqHash){
Line 1,597 ⟶ 2,473:
 
return(enc,powr,freqHash);
}</langsyntaxhighlight>
<langsyntaxhighlight lang="zkl">fcn arithmethicDecoding(enc, radix, powr, freqHash){
enc*=radix.pow(powr);
base:=freqHash.values.sum(0);
Line 1,621 ⟶ 2,497:
}
decoded.text // Return the decoded output
}</langsyntaxhighlight>
<langsyntaxhighlight lang="zkl">radix:=10;
testStrings:=T(
"DABDDB",
Line 1,635 ⟶ 2,511:
if(str!=dec) println("\tHowever that is incorrect!");
}</langsyntaxhighlight>
{{out}}
<pre>
1,481

edits