MODULE OGGUtilities;
IMPORT
SYSTEM, Strings, Files, KernelLog, Machine, SoundDevices, BIT;
CONST
Trace = 1;
Error = 2;
Debug = {Error};
MaxCodewordLength* = 33;
MaxBlocksize* = 8192;
NoHuffmanLeaf = -1;
GoLeft = 0; GoRight = 1;
BaseVectorSize = 256;
Nx* = 20;
VAR
f: Files.File;
w*: Files.Writer;
Ny: LONGINT;
ScaleFactor: HUGEINT;
TYPE
PCMBuffer* = OBJECT
VAR data*: ARRAY MaxBlocksize OF HUGEINT;
PROCEDURE Print*(name: ARRAY OF CHAR; len: LONGINT);
BEGIN
ArrayHugeLen(name, data, len)
END Print;
PROCEDURE PrintShort(name: ARRAY OF CHAR; len: LONGINT);
VAR
tmp: POINTER TO ARRAY OF LONGINT;
i: LONGINT;
BEGIN
NEW(tmp,len);
FOR i := 0 TO len - 1 DO
tmp[i] := SHORT(data[i])
END;
ArrayLen(name, tmp^, len);
END PrintShort;
PROCEDURE ZeroBuffer*;
VAR i: LONGINT;
BEGIN
IF (Trace IN Debug) THEN String("@VorbisCodec::PCMBuffer::ZeroBuffer()") END;
FOR i := 0 TO LEN(data) - 1 DO
data[i] := 0
END
END ZeroBuffer;
END PCMBuffer;
HuffmanTree* = OBJECT
VAR start-: HuffmanNode;
PROCEDURE &Init*;
BEGIN
NEW(start, NoHuffmanLeaf, FALSE, FALSE)
END Init;
PROCEDURE AddNode(value, length, codeword: LONGINT);
BEGIN
IF (Trace IN Debug) THEN
String("@MyUtilities::HuffmanTree::AddNode()")
END;
start.AddNode(value, length, codeword)
END AddNode;
PROCEDURE IsValidLengthList*(VAR list: IntList; unused: LONGINT): BOOLEAN;
VAR limit, sum: HUGEINT;
BEGIN
IF (Trace IN Debug) THEN
String("@MyUtilities::HuffmanTree::IsValidLengthList()")
END;
GetSumAndLimit(list, sum, limit, unused);
RETURN (sum = limit)
END IsValidLengthList;
PROCEDURE IsOverspecified*(VAR list: IntList; unused: LONGINT): BOOLEAN;
VAR limit, sum: HUGEINT;
BEGIN
GetSumAndLimit(list, sum, limit, unused);
RETURN (sum > limit)
END IsOverspecified;
PROCEDURE IsUnderspecified*(VAR list: IntList; unused: LONGINT): BOOLEAN;
VAR limit, sum: HUGEINT;
BEGIN
GetSumAndLimit(list, sum, limit, unused);
RETURN (sum > limit)
END IsUnderspecified;
PROCEDURE GetSumAndLimit(VAR list: IntList; VAR sum, limit: HUGEINT; unused: LONGINT);
VAR
i: HUGEINT;
cur: ListElement;
BEGIN
limit := PowerH(2, MaxCodewordLength);
sum := 0;
cur := list.start;
FOR i := 0 TO list.length - 1 DO
IF (cur(IntElement).long # unused) THEN
sum := sum + PowerH(2, MaxCodewordLength - cur(IntElement).long);
END;
cur := cur.next
END
END GetSumAndLimit;
PROCEDURE HasUsedEntries*(VAR list: IntList; unused: LONGINT): BOOLEAN;
VAR
i: HUGEINT;
cur: ListElement;
BEGIN
cur := list.start;
FOR i := 0 TO list.length - 1 DO
IF (cur(IntElement).long # unused) THEN RETURN TRUE END
END;
RETURN FALSE
END HasUsedEntries;
PROCEDURE BuildTree*(VAR lengths: IntList; VAR codes: IntList; unused: LONGINT);
VAR
value: LONGINT;
curLen, curCode: IntElement;
BEGIN
IF (Trace IN Debug) THEN String("@MyUtilities::HuffmanTree::BuildTree()") END;
curLen := lengths.start(IntElement);
curCode := codes.start(IntElement);
value := 0;
WHILE (curLen # NIL) DO
IF (curLen.long # unused) THEN
AddNode(value, curLen.long, curCode.long);
IF (curCode.next # NIL) THEN curCode := curCode.next(IntElement) END
END;
INC(value);
IF (curLen.next # NIL) THEN curLen := curLen.next(IntElement) ELSE curLen := NIL END
END
END BuildTree;
PROCEDURE GoLeftOrRight*(VAR node: HuffmanNode; bit: LONGINT);
BEGIN
IF ((bit # 0) & (bit # 1)) THEN
KernelLog.String("ASSERTION failed - bit is not 0 or 1"); KernelLog.Ln
END;
ASSERT((bit = 0) OR (bit = 1));
IF (bit = GoLeft) THEN
node := node.left
ELSIF (bit = GoRight) THEN
node := node.right
END
END GoLeftOrRight;
PROCEDURE Print;
BEGIN
String("(inorder, *: isFull)");
IF ~(start = NIL) THEN start.Print() END;
String("")
END Print;
END HuffmanTree;
HuffmanNode* = OBJECT
VAR
left, right: HuffmanNode;
value: LONGINT;
isLeaf, isFull: BOOLEAN;
PROCEDURE &Init*(value: LONGINT; isLeaf, isFull: BOOLEAN);
BEGIN
left := NIL; right := NIL;
SELF.value := value;
SELF.isFull := isFull;
SELF.isLeaf := isLeaf
END Init;
PROCEDURE GetValue*(): LONGINT;
BEGIN
RETURN value
END GetValue;
PROCEDURE IsLeaf*(): BOOLEAN;
BEGIN
RETURN isLeaf
END IsLeaf;
PROCEDURE Print;
BEGIN
IF (left # NIL) THEN left.Print() END;
w.String("[");
IF isLeaf THEN w.Int(value, 1) ELSE w.String(".") END;
IF isFull THEN w.String("*") END;
w.String("]");
IF (right # NIL) THEN right.Print() END
END Print;
PROCEDURE AddNode(value, length, restCodeword: LONGINT);
VAR
digit: LONGINT;
BEGIN
IF (Trace IN Debug) THEN
String("@MyUtilities::HuffmanNode::AddNode()")
END;
digit := SYSTEM.LSH(restCodeword, -(length - 1));
restCodeword := restCodeword MOD Power(2, length - 1);
IF (length = 1) THEN
IF (digit = GoLeft) THEN
NEW(left, value, TRUE, TRUE)
ELSIF (digit = GoRight) THEN
NEW(right, value, TRUE, TRUE)
END
ELSE
IF (digit = GoLeft) THEN
IF (left = NIL) THEN NEW(left, NoHuffmanLeaf, FALSE, FALSE) END;
left.AddNode(value, length - 1, restCodeword)
ELSIF (digit = GoRight) THEN
IF (right = NIL) THEN NEW(right, NoHuffmanLeaf, FALSE, FALSE) END;
right.AddNode(value, length - 1, restCodeword)
END
END
END AddNode;
END HuffmanNode;
Vector* = OBJECT
VAR
capacity, len: LONGINT;
data: ARRAY BaseVectorSize OF HUGEINT;
PROCEDURE &Init*;
BEGIN
len := 0;
capacity := BaseVectorSize
END Init;
PROCEDURE Print*;
BEGIN
ArrayHugeLen("vector", data, len);
END Print;
PROCEDURE Add*(value: HUGEINT);
BEGIN
IF (len >= capacity) THEN
KernelLog.String("ASSERTION failed - vector exceeds size"); KernelLog.Ln
END;
ASSERT(len < capacity);
data[len] := value;
INC(len)
END Add;
PROCEDURE Increase(inc: HUGEINT);
VAR i: LONGINT;
BEGIN
FOR i := 0 TO len - 1 DO
INC(data[i], inc)
END
END Increase;
PROCEDURE GetLen(): LONGINT;
BEGIN
RETURN len
END GetLen;
PROCEDURE GetLast(): HUGEINT;
BEGIN
RETURN data[len]
END GetLast;
PROCEDURE GetValueAt*(idx: LONGINT): HUGEINT;
BEGIN
IF (idx >= len) THEN
KernelLog.String("ASSERTION failed - access to invalid vector element"); KernelLog.Ln
END;
ASSERT(idx < len);
RETURN data[idx]
END GetValueAt;
PROCEDURE IncValueAt(inc: HUGEINT; idx: LONGINT);
BEGIN
SetValueAt(inc + GetValueAt(idx), idx)
END IncValueAt;
PROCEDURE SetValueAt(val: HUGEINT; idx: LONGINT);
BEGIN
IF (idx >= len) THEN
KernelLog.String("ASSERTION failed - access to invalid vector element"); KernelLog.Ln
END;
ASSERT(idx < len);
data[idx] := val
END SetValueAt;
PROCEDURE Concatenate(VAR v: Vector);
VAR i: LONGINT;
BEGIN
FOR i := 0 TO v.GetLen() - 1 DO
SELF.Add(v.data[i])
END
END Concatenate;
END Vector;
List* = OBJECT
VAR
length*: HUGEINT;
start-, last-: ListElement;
PROCEDURE &Init*(first: ListElement);
VAR
BEGIN
IF (first = NIL) THEN length := 0 ELSE length := 1 END;
SELF.start := first;
SELF.last := first
END Init;
PROCEDURE Append*(node: ListElement);
BEGIN
IF (last = NIL) THEN
start := node; last := node
ELSE
last.next := node;
last := node
END;
INC(length);
node.next := NIL
END Append;
PROCEDURE Print*;
VAR
i, split: LONGINT;
cur: ListElement;
BEGIN
i := 0; split := 16;
cur := SELF.start;
String("-> List <-");
Var("list-length", SYSTEM.VAL(LONGINT,length));
WHILE (cur # NIL) DO
IF (~(i = 0) & (i MOD split = 0)) THEN w.Ln END;
cur.Print;
cur := cur.next;
INC(i)
END;
w.Ln; String("-> END (List) <-")
END Print;
END List;
IntList* = OBJECT(List)
END IntList;
ListElement* = OBJECT
VAR
next-: ListElement;
PROCEDURE &Init*;
BEGIN
SELF.next := NIL
END Init;
PROCEDURE Print;
END Print;
END ListElement;
IntElement* = OBJECT(ListElement)
VAR
long-: LONGINT;
PROCEDURE &InitInt*(long: LONGINT);
BEGIN
SELF.long := long;
SELF.next := NIL
END InitInt;
PROCEDURE Print;
BEGIN
w.Int(long, 3)
END Print;
END IntElement;
BufferPool* = OBJECT
VAR head, num: LONGINT; buffer: POINTER TO ARRAY OF SoundDevices.Buffer;
PROCEDURE Append*(x: SoundDevices.Buffer);
BEGIN {EXCLUSIVE}
AWAIT(num # LEN(buffer));
buffer[(head+num) MOD LEN(buffer)] := x;
INC(num)
END Append;
PROCEDURE Remove*(): SoundDevices.Buffer;
VAR x: SoundDevices.Buffer;
BEGIN {EXCLUSIVE}
AWAIT(num # 0);
x := buffer[head];
head := (head+1) MOD LEN(buffer);
DEC(num);
RETURN x
END Remove;
PROCEDURE &Init*(n: LONGINT);
BEGIN
head := 0; num := 0; NEW(buffer, n)
END Init;
END BufferPool;
PROCEDURE ILog*(x: LONGINT): LONGINT;
VAR ret: LONGINT;
BEGIN
ret := 0;
LOOP
IF (x > 0) THEN
INC(ret);
x := SYSTEM.LSH(x, -1)
ELSE
EXIT
END
END;
RETURN ret
END ILog;
PROCEDURE Float32Unpack*(val: LONGINT): HUGEINT;
VAR
mantissa, sign, exponent, one: LONGINT;
res: REAL;
BEGIN
mantissa := BIT.LAND(val, 1FFFFFH);
sign := BIT.LAND(val, LONGINT(80000000H));
exponent := BIT.LAND(val, 7FE00000H) DIV 1FFFFFH;
IF (sign # 0) THEN
mantissa := -1 * mantissa
END;
one := 1;
res := mantissa / SYSTEM.LSH(one, -1*(exponent - 788));
RETURN ScaleUpHuge(res)
END Float32Unpack;
PROCEDURE Lookup1Values*(cbEntries, cbDimensions: LONGINT): LONGINT;
VAR res: LONGINT;
BEGIN
res := 0;
WHILE (Power(res, cbDimensions) <= cbEntries) DO
INC(res);
END;
DEC(res);
RETURN res
END Lookup1Values;
PROCEDURE LowNeighbor*(v: ARRAY OF LONGINT; x: LONGINT): LONGINT;
VAR i, n: LONGINT;
BEGIN
n := 0;
FOR i := 1 TO x - 1 DO
IF (v[i] < v[x]) THEN
IF ((v[i] > v[n]) OR (n = 0)) THEN
n := i
END
END
END;
RETURN n
END LowNeighbor;
PROCEDURE HighNeighbor*(v: ARRAY OF LONGINT; x: LONGINT): LONGINT;
VAR i, n: LONGINT;
BEGIN
n := 0;
FOR i := 0 TO x - 1 DO
IF (v[i] > v[x]) THEN
IF ((v[i] < v[n]) OR (n = 0)) THEN
n := i
END
END
END;
RETURN n
END HighNeighbor;
PROCEDURE RenderPoint*(x0,y0,x1,y1,x: LONGINT): LONGINT;
VAR
dy, adx, ady, err, off: LONGINT;
BEGIN
dy := y1 - y0;
adx := x1 - x0;
ady := ABS(dy);
err := ady * (x - x0);
off := err DIV adx;
IF dy < 0 THEN
RETURN (y0 - off)
ELSE
RETURN (y0 + off)
END
END RenderPoint;
PROCEDURE RenderLine*(x0, y0, x1, y1: LONGINT; VAR v: ARRAY OF HUGEINT);
VAR dy, adx, ady, x, y, err, base, sy: LONGINT;
BEGIN
dy := y1 - y0;
adx := x1 - x0;
ady := ABS(dy);
IF (dy < 0) THEN
base := -1 * ABS(dy) DIV adx
ELSE
base := dy DIV adx
END;
x := x0;
y := y0;
err := 0;
IF (dy < 0) THEN
sy := base - 1
ELSE
sy := base + 1
END;
ady := ady - ABS(base) * adx;
v[x] := y;
FOR x := x0 + 1 TO x1 - 1 DO
INC(err, ady);
IF (err >= adx) THEN
DEC(err, adx);
INC(y, sy)
ELSE
INC(y, base)
END;
v[x] := y
END
END RenderLine;
PROCEDURE EasySortRemember*(VAR data, sortptr: ARRAY OF LONGINT; n: LONGINT);
VAR tmp, j, k: LONGINT;
BEGIN
IF ((n > LEN(data)) OR (n > LEN(sortptr))) THEN
KernelLog.String("ASSERTION failed - array too short to sort")
END;
ASSERT((n <= LEN(data)) & (n <= LEN(sortptr)));
FOR j := 0 TO n - 1 DO sortptr[j] := j END;
FOR j := 0 TO n - 2 DO
FOR k := j TO n - 1 DO
IF (data[sortptr[j]] > data[sortptr[k]]) THEN
tmp := sortptr[k];
sortptr[k] := sortptr[j];
sortptr[j] := tmp
END
END
END;
END EasySortRemember;
PROCEDURE Power*(x,n: LONGINT): LONGINT;
VAR res: LONGINT;
BEGIN
IF (n < 0) THEN
KernelLog.String("ASSERTION failed - power of negative numbers are not allowed"); KernelLog.Ln
END;
ASSERT(n >= 0);
IF (n = 0) THEN
RETURN 1
ELSE
res := x;
WHILE (n > 1) DO
res := x * res;
DEC(n)
END
END;
RETURN res;
END Power;
PROCEDURE PowerH(x: HUGEINT; n: LONGINT): HUGEINT;
VAR res: HUGEINT;
BEGIN
IF (n < 0) THEN
KernelLog.String("ASSERTION failed - power of negative numbers are not allowed"); KernelLog.Ln
END;
ASSERT(n >= 0);
IF (n = 0) THEN
RETURN 1
ELSE
res := x;
WHILE (n > 1) DO
res := x * res;
DEC(n)
END
END;
RETURN res;
END PowerH;
PROCEDURE PowerR*(x: REAL; n: LONGINT): REAL;
VAR res: REAL;
BEGIN
IF (n < 0) THEN
KernelLog.String("ASSERTION failed - power of negative numbers are not allowed"); KernelLog.Ln
END;
ASSERT(n >= 0);
IF (n = 0) THEN
RETURN 1
ELSE
res := x;
WHILE (n > 1) DO
res := res * x;
DEC(n)
END
END;
RETURN res;
END PowerR;
PROCEDURE Log2n*(n: LONGINT): LONGINT;
VAR res: LONGINT;
BEGIN
ASSERT(n > 0);
res := 0;
WHILE (n # 1) DO
n := n DIV 2;
INC(res);
END;
RETURN res
END Log2n;
PROCEDURE MultHugeFP*(a, b: HUGEINT): HUGEINT;
VAR sign, res: HUGEINT;
BEGIN
IF ((a = 0) OR (b = 0)) THEN
RETURN 0
ELSE
res := a * b;
IF res < 0 THEN
sign := -1;
res := sign * res;
ELSE
sign := 1
END;
res := SYSTEM.LSH(res, -Ny);
res := sign * res;
RETURN res
END
END MultHugeFP;
PROCEDURE MultDotProductFP*(residue, floor: HUGEINT): HUGEINT;
VAR sign: HUGEINT;
BEGIN
IF (residue = 0) OR (floor = 0) THEN
RETURN 0
ELSE
IF residue < 0 THEN
sign := -1;
residue := sign * residue
ELSE
sign := 1
END;
residue := ScaleDownHuge(residue);
residue := sign * residue;
RETURN residue * floor
END
END MultDotProductFP;
PROCEDURE MultFP*(a, b: HUGEINT): HUGEINT;
VAR divident, n: LONGINT;
BEGIN
IF (a = 0) OR (b = 0) THEN
RETURN 0
ELSE
n := Ny DIV 2;
divident := SYSTEM.LSH(LONG(LONG(1)), n);
a := Machine.DivH(a, divident);
b := Machine.DivH(b, divident);
RETURN a * b
END
END MultFP;
PROCEDURE DivFP*(a, b: LONGINT): LONGINT;
BEGIN
RETURN ScaleUpInt(a) DIV b;
END DivFP;
PROCEDURE ScaleUpHuge*(r: REAL): HUGEINT;
VAR tmp: HUGEINT;
BEGIN
tmp := ENTIERH(0.5 + r * ScaleFactor);
RETURN tmp
END ScaleUpHuge;
PROCEDURE ScaleUp*(r: LONGREAL): LONGINT;
VAR tmp: LONGINT;
BEGIN
tmp := ENTIER(0.5 + r * ScaleFactor);
RETURN tmp
END ScaleUp;
PROCEDURE ScaleUpRealToHuge*(r: LONGREAL): HUGEINT;
VAR tmp: HUGEINT;
BEGIN
tmp := ENTIERH(0.5 + r * ScaleFactor);
RETURN tmp
END ScaleUpRealToHuge;
PROCEDURE ScaleUpInt*(i: LONGINT): LONGINT;
VAR tmp: LONGINT;
BEGIN
tmp := i * SHORT(ScaleFactor);
RETURN tmp
END ScaleUpInt;
PROCEDURE ScaleUpHugeInt*(i: HUGEINT): HUGEINT;
VAR tmp: HUGEINT;
BEGIN
tmp := i * ScaleFactor;
RETURN tmp
END ScaleUpHugeInt;
PROCEDURE ScaleDownRoundedHuge*(i: HUGEINT): LONGINT;
BEGIN
RETURN SHORT(Machine.DivH(i + Machine.DivH(ScaleFactor , 2), ScaleFactor))
END ScaleDownRoundedHuge;
PROCEDURE ScaleDownHuge(i: HUGEINT): HUGEINT;
BEGIN
RETURN Machine.DivH(i, ScaleFactor)
END ScaleDownHuge;
PROCEDURE GetFilename*(VAR name: ARRAY OF CHAR);
BEGIN
f.GetName(name)
END GetFilename;
PROCEDURE Array2D*(name: ARRAY OF CHAR; VAR a: ARRAY OF ARRAY OF LONGINT);
VAR i: LONGINT;
BEGIN
w.String("[ "); w.String(name); w.String(" ]"); w.Ln;
FOR i := 0 TO LEN(a) - 1 DO
Array("---", a[i]);
w.Ln;
END;
w.Ln; w.String("[ END ("); w.String(name); w.String(") ]"); w.Ln;
w.Update
END Array2D;
PROCEDURE ArrayBool*(name: ARRAY OF CHAR; VAR a: ARRAY OF BOOLEAN);
VAR i: LONGINT;
BEGIN
w.String("[ "); w.String(name); w.String(" ]"); w.Ln;
FOR i := 0 TO LEN(a) - 1 DO
IF (~(i = 0) & (i MOD 16 = 0)) THEN
w.Ln; w.String(" ")
END;
IF (a[i]) THEN
w.String("1")
ELSE
w.String("0")
END;
IF (i # LEN(a)-1) THEN w.String(", ") END
END;
w.Ln; w.String("[ END ("); w.String(name); w.String(") ]"); w.Ln;
w.Update
END ArrayBool;
PROCEDURE Array*(name: ARRAY OF CHAR; VAR a: ARRAY OF LONGINT);
BEGIN
ArrayLen(name, a, LEN(a))
END Array;
PROCEDURE ArrayHuge*(name: ARRAY OF CHAR; VAR a: ARRAY OF HUGEINT);
BEGIN
ArrayHugeLen(name, a, LEN(a))
END ArrayHuge;
PROCEDURE ArrayHugeLen*(name: ARRAY OF CHAR; VAR a: ARRAY OF HUGEINT; n: LONGINT);
VAR i: LONGINT;
BEGIN
IF (n > LEN(a)) THEN
KernelLog.String("ASSERTION failed - array too short")
END;
ASSERT(n <= LEN(a));
w.String("[ "); w.String(name); w.String(" ] "); w.Ln;
FOR i := 0 TO n - 1 DO
w.Int(i, 0); w.String(";");
w.Int(SHORT(a[i]), 0);
w.Ln;
END;
w.Ln; w.String("[ END ("); w.String(name); w.String(") ]"); w.Ln;
w.Update
END ArrayHugeLen;
PROCEDURE ArrayLen*(name: ARRAY OF CHAR; VAR a: ARRAY OF LONGINT; n: LONGINT);
VAR i: LONGINT;
BEGIN
IF (n > LEN(a)) THEN
KernelLog.String("ASSERTION failed - array too short")
END;
ASSERT(n <= LEN(a));
w.String("[ "); w.String(name); w.String(" ]"); w.Ln;
FOR i := 0 TO n - 1 DO
w.Int(i, 0); w.String(";"); w.Int(a[i], 0); w.Ln;
END;
w.Ln; w.String("[ END ("); w.String(name); w.String(") ]"); w.Ln;
w.Update
END ArrayLen;
PROCEDURE String*(str: ARRAY OF CHAR);
BEGIN
w.String(str); w.Ln; w.Update
END String;
PROCEDURE Buffer*(VAR buf: ARRAY OF CHAR; ofs, len: LONGINT);
VAR i, line: LONGINT;
hex: ARRAY 3 OF CHAR;
BEGIN
line := 16;
FOR i := 0 TO len - 1 DO
IF ((i # 0) & (i MOD line = 0)) THEN w.Ln END;
CharToHex(buf[ofs + i], hex);
w.String(hex); w.String(" ")
END;
w.Ln; w.Update
END Buffer;
PROCEDURE CharToHex(ch: CHAR; VAR hex: ARRAY OF CHAR);
VAR ord, low, high: LONGINT;
BEGIN
ord := ORD(ch);
low := ord MOD 16;
high := ord DIV 16;
hex[0] := GetHexDigit(high);
hex[1] := GetHexDigit(low);
END CharToHex;
PROCEDURE GetHexDigit(val: LONGINT): CHAR;
BEGIN
IF (val <= 9) THEN
RETURN CHR(48 + val)
ELSE
RETURN CHR(65 + val - 10)
END
END GetHexDigit;
PROCEDURE Var*(name: ARRAY OF CHAR; value: LONGINT);
BEGIN
w.String(name); w.String(": "); w.Int(value,5); w.Ln; w.Update
END Var;
PROCEDURE VarH*(name: ARRAY OF CHAR; value: HUGEINT);
BEGIN
w.String(name); w.String(": ");
VarH2(value);
w.Ln; w.Update
END VarH;
PROCEDURE VarH2*(value: HUGEINT);
VAR sign: LONGINT;
BEGIN
IF (value < 0) THEN sign := -1; value := -1 * value ELSE sign := 1 END;
IF (sign = -1) THEN w.String("-") ELSE w.String(" ") END;
PrintHex(SHORT (Machine.ASHH(value, -32)));
PrintHex(SHORT (value));
w.Update
END VarH2;
PROCEDURE PrintHex(x: LONGINT);
VAR i, j: LONGINT;
buf: ARRAY 10 OF CHAR;
BEGIN
j := 8;
FOR i := j-1 TO 0 BY -1 DO
buf[i] := CHR(x MOD 10H + 48);
IF buf[i] > "9" THEN
buf[i] := CHR(ORD(buf[i]) - 48 + 65 - 10)
END;
x := x DIV 10H
END;
buf[j] := 0X;
w.String(buf)
END PrintHex;
PROCEDURE VarReal*(name: ARRAY OF CHAR; value: LONGREAL);
VAR tmpStr: ARRAY 32 OF CHAR;
BEGIN
Strings.FloatToStr(value, 5, 4, 0, tmpStr);
w.String(name); w.String(": "); w.String(tmpStr); w.Ln; w.Update
END VarReal;
PROCEDURE InitLogger*;
BEGIN
f := Files.New("LogFile.csv");
Files.Register(f);
Files.OpenWriter(w, f, 0);
END InitLogger;
BEGIN
Ny := Nx;
ScaleFactor := SYSTEM.LSH(LONG(LONG(1)), Ny DIV 2);
ScaleFactor := ScaleFactor * ScaleFactor;
END OGGUtilities.