-
Notifications
You must be signed in to change notification settings - Fork 2
/
ufixed.pas
160 lines (128 loc) · 4.38 KB
/
ufixed.pas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
(******************************************************************************)
(* *)
(* Author : Uwe Schächterle (Corpsman) *)
(* *)
(* This file is part of Fixed comma *)
(* *)
(* See the file license.md, located under: *)
(* https://github.com/PascalCorpsman/Software_Licenses/blob/main/license.md *)
(* for details about the license. *)
(* *)
(* It is not allowed to change or remove this text from any *)
(* source file of the project. *)
(* *)
(******************************************************************************)
Unit ufixed;
{$MODE objfpc}{$H+}
Interface
Uses
Classes, SysUtils;
(*
* If you get a compiler error with missing file
* just create a file namend "ufixed.inc" in your project folder and
* insert the following content:
*
* ---------- Content of file ----------
{.$DEFINE AllowAccesToInternalData} // Zugriff auf die interne Datenstructur
---------- End content of file ----------
*)
{$I ufixed.inc}
Type
{ TFixedComma }
TFixedComma = Class
private
fone: uint64;
fvalue: uint64;
fn: integer;
fp: integer;
fsigned: Boolean;
Function getValue: Double;
Procedure setValue(AValue: Double);
public
{$IFDEF AllowAccesToInternalData}
Property RaWValue: uint64 read fvalue write fvalue;
{$ENDIF}
Property Value: Double read getValue write setValue;
Constructor Create(N, P: integer; Signed: Boolean); virtual;
Destructor Destroy; override;
End;
Operator + (a, b: TFixedComma): TFixedComma;
Operator - (a, b: TFixedComma): TFixedComma;
Operator * (a, b: TFixedComma): TFixedComma;
Operator / (a, b: TFixedComma): TFixedComma;
Implementation
Procedure Check(a, b: TFixedComma);
Begin
If (a.fp <> b.fp) Then Raise exception.create('Oparand with different comma position');
If (a.fn <> b.fn) Then Raise exception.create('Oparand with different bit width');
If (a.fsigned <> b.fsigned) Then Raise exception.create('Oparand with different signing');
End;
Operator + (a, b: TFixedComma): TFixedComma;
Begin
Check(a, b);
result := TFixedComma.Create(a.fn, a.fp, a.fsigned);
result.fvalue := a.fvalue + b.fvalue;
// Todo: Overflow detection => Clamt to Upper Border
If result.fvalue >= (1 Shl result.fp) Then Begin
result.fvalue := (1 Shl result.fp) - 1;
End;
End;
Operator - (a, b: TFixedComma): TFixedComma;
Begin
Check(a, b);
result := TFixedComma.Create(a.fn, a.fp, a.fsigned);
result.fvalue := a.fvalue - b.fvalue;
// Todo: Underflow detection => Clamt to Upper Border
End;
Operator * (a, b: TFixedComma): TFixedComma;
Begin
Check(a, b);
result := TFixedComma.Create(a.fn, a.fp, a.fsigned);
result.fvalue := a.fvalue * b.fvalue;
result.fvalue := result.fvalue Shr (a.fp);
End;
Operator / (a, b: TFixedComma): TFixedComma;
Begin
Check(a, b);
result := TFixedComma.Create(a.fn, a.fp, a.fsigned);
result.fvalue := a.fvalue Div b.fvalue;
// Todo: Overflow detection => Clamt to Upper Border
End;
{ TFixedComma }
Function TFixedComma.getValue: Double;
Begin
If fsigned Then Begin
result := int64(fvalue) / fone;
End
Else Begin
result := fvalue / fone;
End;
End;
Procedure TFixedComma.setValue(AValue: Double);
Begin
fvalue := trunc(AValue * fone);
End;
Constructor TFixedComma.Create(N, P: integer; Signed: Boolean);
Begin
Inherited create;
If (n Mod 8 <> 0) Or (n <= 0) Or (n > 32) Then Begin
Raise Exception.Create('Invalid Bitnumber.');
End;
If (p + 1 > n) Then Begin
Raise Exception.Create('Invalid comma position.');
End;
fn := n;
If Signed Then Begin
fp := p;
End
Else Begin
fp := p + 1;
End;
fone := 1 Shl fp;
fsigned := Signed;
fvalue := 0;
End;
Destructor TFixedComma.Destroy;
Begin
End;
End.