language-Modula2-0.1: examples/Modula-2_Libraries/andrea-m2/lib/generic/base2.mod
IMPLEMENTATION MODULE Base2;
(* for 16 bit machines use max_power = 15 *)
(* for 32 bit machines use max_power = 31 *)
(* John Andrea, Nov.18/91 *)
(* This code may be freely used and distributed, it may not be sold. *)
FROM StringOperations IMPORT Length;
CONST
max_power = 31;
VAR
power2 :ARRAY [0..max_power] OF CARDINAL;
max_value, i :CARDINAL;
(* --------------------------------------------------------- *)
PROCEDURE Max10() :CARDINAL;
BEGIN
RETURN max_value;
END Max10;
(* --------------------------------------------------------- *)
PROCEDURE HowMany2( base10 :CARDINAL ) :CARDINAL;
(* return the number of base 2 digits needed to represent 'base10' *)
VAR n :CARDINAL;
BEGIN
IF base10 < 2 THEN
n := 1;
ELSE
(* find the largest position in the power list *)
n := 0;
WHILE base10 >= power2[n] DO
n := n + 1;
END;
END;
RETURN n;
END HowMany2;
(* --------------------------------------------------------- *)
PROCEDURE ToBase2( base10 :CARDINAL; VAR base2 :ARRAY OF CHAR; VAR ok :BOOLEAN );
VAR
n, i, j :CARDINAL;
high :CARDINAL;
BEGIN
high := HIGH( base2 );
IF base10 = 0 THEN
ok := TRUE;
base2[0] := '0';
IF high > 0 THEN base2[1] := 0C; END;
ELSE
IF base10 > max_value THEN
ok := FALSE;
base2[0] := 0C;
ELSE
n := HowMany2( base10 ) - 1;
IF n > high THEN
ok := FALSE;
base2[0] := 0C;
ELSE
(* for each of the powers of 2, count their numbers *)
FOR i := 0 TO n DO
j := n - i;
IF base10 >= power2[j] THEN
base10 := base10 - power2[j];
base2[i] := '1';
ELSE
base2[i] := '0';
END;
END;
IF high > n THEN base2[n+1] := 0C; END;
END;
END;
END;
END ToBase2;
(* --------------------------------------------------------- *)
PROCEDURE FromBase2( base2 :ARRAY OF CHAR; VAR base10 :CARDINAL; VAR ok :BOOLEAN );
VAR
i, n, d :CARDINAL;
c :CHAR;
BEGIN
ok := TRUE;
base10 := 0;
n := Length( base2 );
i := 0;
WHILE ( i < n ) & ok DO
c := base2[i];
IF c = '0' THEN
d := 0;
ELSIF c = '1' THEN
d := 1;
ELSE
ok := FALSE; d := 0;
END;
base10 := base10 * 2 + d;
i := i + 1;
END;
END FromBase2;
BEGIN
(* precompute the powers of 2 *)
power2[0] := 1;
FOR i := 1 TO max_power DO
power2[i] := 2 * power2[i-1];
END;
max_value := power2[max_power];
END Base2.