|
1 (* |
|
2 * Hedgewars, a Worms style game |
|
3 * Copyright (c) 2007 Andrey Korotaev <unC0Rr@gmail.com> |
|
4 * |
|
5 * This program is free software; you can redistribute it and/or modify |
|
6 * it under the terms of the GNU General Public License as published by |
|
7 * the Free Software Foundation; version 2 of the License |
|
8 * |
|
9 * This program is distributed in the hope that it will be useful, |
|
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 * GNU General Public License for more details. |
|
13 * |
|
14 * You should have received a copy of the GNU General Public License |
|
15 * along with this program; if not, write to the Free Software |
|
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA |
|
17 *) |
|
18 |
|
19 unit uFloat; |
|
20 interface |
|
21 |
|
22 {$IFDEF FPC} |
|
23 {$ifdef FPC_LITTLE_ENDIAN} |
|
24 type hwFloat = record |
|
25 isNegative: boolean; |
|
26 case byte of |
|
27 0: (Frac, Round: Longword); |
|
28 1: (QWordValue : QWord); |
|
29 end; |
|
30 {$else FPC_LITTLE_ENDIAN} |
|
31 type hwFloat = record |
|
32 isNegative: boolean; |
|
33 case byte of |
|
34 0: (Round, Frac: Longword); |
|
35 1: (QWordValue : QWord); |
|
36 end; |
|
37 {$endif FPC_LITTLE_ENDIAN} |
|
38 |
|
39 operator := (i: LongInt) z : hwFloat; |
|
40 |
|
41 operator + (z1, z2: hwFloat) z : hwFloat; |
|
42 operator - (z1, z2: hwFloat) z : hwFloat; |
|
43 operator - (z1: hwFloat) z : hwFloat; |
|
44 |
|
45 operator * (z1, z2: hwFloat) z : hwFloat; |
|
46 operator * (z1: hwFloat; z2: LongInt) z : hwFloat; |
|
47 operator / (z1, z2: hwFloat) z : hwFloat; |
|
48 |
|
49 operator < (z1, z2: hwFloat) b : boolean; |
|
50 operator > (z1, z2: hwFloat) b : boolean; |
|
51 |
|
52 function cstr(z: hwFloat): string; |
|
53 function hwRound(t: hwFloat): integer; |
|
54 function hwAbs(t: hwFloat): hwFloat; |
|
55 function hwSqr(t: hwFloat): hwFloat; |
|
56 function Distance(dx, dy: hwFloat): hwFloat; |
|
57 function AngleSin(angle: Longword): hwFloat; |
|
58 function AngleCos(angle: Longword): hwFloat; |
|
59 |
|
60 const _1div1024: hwFloat = (isNegative: false; QWordValue: 4194304); |
|
61 _1div10000: hwFloat = (isNegative: false; QWordValue: 429496); |
|
62 _1div50000: hwFloat = (isNegative: false; QWordValue: 85899); |
|
63 _1div100000: hwFloat = (isNegative: false; QWordValue: 42950); |
|
64 _1div3: hwFloat = (isNegative: false; QWordValue: 1431655766); |
|
65 hwPi: hwFloat = (isNegative: false; QWordValue: 13493037704); |
|
66 _0_000004: hwFloat = (isNegative: false; QWordValue: 17179); |
|
67 _0_0002: hwFloat = (isNegative: false; QWordValue: 858993); |
|
68 _0_001: hwFloat = (isNegative: false; QWordValue: 4294967); |
|
69 _0_003: hwFloat = (isNegative: false; QWordValue: 12884902); |
|
70 _0_004: hwFloat = (isNegative: false; QWordValue: 17179869); |
|
71 _0_005: hwFloat = (isNegative: false; QWordValue: 21474836); |
|
72 _0_01: hwFloat = (isNegative: false; QWordValue: 42949673); |
|
73 _0_02: hwFloat = (isNegative: false; QWordValue: 85899345); |
|
74 _0_03: hwFloat = (isNegative: false; QWordValue: 128849018); |
|
75 _0_08: hwFloat = (isNegative: false; QWordValue: 343597383); |
|
76 _0_1: hwFloat = (isNegative: false; QWordValue: 429496729); |
|
77 _0_15: hwFloat = (isNegative: false; QWordValue: 644245094); |
|
78 _0_2: hwFloat = (isNegative: false; QWordValue: 858993459); |
|
79 _0_25: hwFloat = (isNegative: false; QWordValue: 1073741824); |
|
80 _0_3: hwFloat = (isNegative: false; QWordValue: 1288490189); |
|
81 _0_35: hwFloat = (isNegative: false; QWordValue: 1503238553); |
|
82 _0_4: hwFloat = (isNegative: false; QWordValue: 1717986918); |
|
83 _0_45: hwFloat = (isNegative: false; QWordValue: 1932735283); |
|
84 _0_5: hwFloat = (isNegative: false; QWordValue: 2147483648); |
|
85 _0_55: hwFloat = (isNegative: false; QWordValue: 2362232012); |
|
86 _0_6: hwFloat = (isNegative: false; QWordValue: 2576980377); |
|
87 _0_8: hwFloat = (isNegative: false; QWordValue: 3435973837); |
|
88 _0_84: hwFloat = (isNegative: false; QWordValue: 3607772528); |
|
89 _0_87: hwFloat = (isNegative: false; QWordValue: 3736621547); |
|
90 _0_9: hwFloat = (isNegative: false; QWordValue: 3865470566); |
|
91 _0_93: hwFloat = (isNegative: false; QWordValue: 3994319585); |
|
92 _0_96: hwFloat = (isNegative: false; QWordValue: 4123168604); |
|
93 _0_995: hwFloat = (isNegative: false; QWordValue: 4273492459); |
|
94 _0_999: hwFloat = (isNegative: false; QWordValue: 4290672328); |
|
95 _1_9: hwFloat = (isNegative: false; QWordValue: 8160437862); |
|
96 |
|
97 cLittle: hwFloat = (isNegative: false; QWordValue: 1); |
|
98 cHHKick: hwFloat = (isNegative: false; QWordValue: 128849018); |
|
99 {$ENDIF} |
|
100 |
|
101 {$IFNDEF FPC} |
|
102 type hwFloat = Extended; |
|
103 {$ENDIF} |
|
104 |
|
105 implementation |
|
106 uses uConsts; |
|
107 |
|
108 {$IFDEF FPC} |
|
109 |
|
110 operator := (i: LongInt) z : hwFloat; |
|
111 begin |
|
112 z.isNegative:= i < 0; |
|
113 z.Round:= abs(i); |
|
114 z.Frac:= 0 |
|
115 end; |
|
116 |
|
117 operator + (z1, z2: hwFloat) z : hwFloat; |
|
118 begin |
|
119 if z1.isNegative = z2.isNegative then |
|
120 begin |
|
121 z.isNegative:= z1.isNegative; |
|
122 z.QWordValue:= z1.QWordValue + z2.QWordValue |
|
123 end |
|
124 else |
|
125 if z1.QWordValue > z2.QWordValue then |
|
126 begin |
|
127 z.isNegative:= z1.isNegative; |
|
128 z.QWordValue:= z1.QWordValue - z2.QWordValue |
|
129 end else |
|
130 begin |
|
131 z.isNegative:= z2.isNegative; |
|
132 z.QWordValue:= z2.QWordValue - z1.QWordValue |
|
133 end |
|
134 end; |
|
135 |
|
136 operator - (z1, z2: hwFloat) z : hwFloat; |
|
137 begin |
|
138 if z1.isNegative = z2.isNegative then |
|
139 if z1.QWordValue > z2.QWordValue then |
|
140 begin |
|
141 z.isNegative:= z1.isNegative; |
|
142 z.QWordValue:= z1.QWordValue - z2.QWordValue |
|
143 end else |
|
144 begin |
|
145 z.isNegative:= not z2.isNegative; |
|
146 z.QWordValue:= z2.QWordValue - z1.QWordValue |
|
147 end |
|
148 else begin |
|
149 z.isNegative:= z1.isNegative; |
|
150 z.QWordValue:= z1.QWordValue + z2.QWordValue |
|
151 end |
|
152 end; |
|
153 |
|
154 operator - (z1: hwFloat) z : hwFloat; |
|
155 begin |
|
156 z:= z1; |
|
157 z.isNegative:= not z.isNegative |
|
158 end; |
|
159 |
|
160 |
|
161 operator * (z1, z2: hwFloat) z : hwFloat; |
|
162 begin |
|
163 z.isNegative:= z1.isNegative xor z2.isNegative; |
|
164 z.QWordValue:= QWord(z1.Round) * z2.Frac + |
|
165 QWord(z1.Frac) * z2.Round + |
|
166 ((QWord(z1.Frac) * z2.Frac) shr 32); |
|
167 z.Round:= z.Round + QWord(z1.Round) * z2.Round; |
|
168 end; |
|
169 |
|
170 operator * (z1: hwFloat; z2: LongInt) z : hwFloat; |
|
171 begin |
|
172 z.isNegative:= z1.isNegative xor (z2 < 0); |
|
173 z2:= abs(z2); |
|
174 z.QWordValue:= z.QWordValue * z2 |
|
175 end; |
|
176 |
|
177 operator / (z1, z2: hwFloat) z : hwFloat; |
|
178 var t: hwFloat; |
|
179 begin |
|
180 z.isNegative:= z1.isNegative xor z2.isNegative; |
|
181 z.Round:= z1.QWordValue div z2.QWordValue; |
|
182 t:= z1 - z2 * z.Round; |
|
183 if t.QWordValue = 0 then |
|
184 z.Frac:= 0 |
|
185 else |
|
186 begin |
|
187 while ((t.QWordValue and $8000000000000000) = 0) and |
|
188 ((z2.QWordValue and $8000000000000000) = 0) do |
|
189 begin |
|
190 t.QWordValue:= t.QWordValue shl 1; |
|
191 z2.QWordValue:= z2.QWordValue shl 1 |
|
192 end; |
|
193 z.Frac:= (t.QWordValue) div (z2.Round) |
|
194 end |
|
195 end; |
|
196 |
|
197 operator < (z1, z2: hwFloat) b : boolean; |
|
198 begin |
|
199 if z1.isNegative <> z2.isNegative then |
|
200 b:= z1.isNegative |
|
201 else |
|
202 if z1.QWordValue = z2.QWordValue then |
|
203 b:= false |
|
204 else |
|
205 b:= (z1.QWordValue < z2.QWordValue) xor z1.isNegative |
|
206 end; |
|
207 |
|
208 operator > (z1, z2: hwFloat) b : boolean; |
|
209 begin |
|
210 if z1.isNegative <> z2.isNegative then |
|
211 b:= z2.isNegative |
|
212 else |
|
213 if z1.QWordValue = z2.QWordValue then |
|
214 b:= false |
|
215 else |
|
216 b:= (z1.QWordValue > z2.QWordValue) xor z2.isNegative |
|
217 end; |
|
218 |
|
219 function cstr(z: hwFloat): string; |
|
220 var tmpstr: string; |
|
221 begin |
|
222 str(z.Round, cstr); |
|
223 if z.Frac <> 0 then |
|
224 begin |
|
225 str(z.Frac / $100000000:1:15, tmpstr); |
|
226 delete(tmpstr, 1, 2); |
|
227 cstr:= cstr + '.' + tmpstr |
|
228 end; |
|
229 if z.isNegative then cstr:= '-' + cstr |
|
230 end; |
|
231 |
|
232 function hwRound(t: hwFloat): integer; |
|
233 begin |
|
234 if t.isNegative then hwRound:= -t.Round |
|
235 else hwRound:= t.Round |
|
236 end; |
|
237 |
|
238 function hwAbs(t: hwFloat): hwFloat; |
|
239 begin |
|
240 hwAbs:= t; |
|
241 hwAbs.isNegative:= false |
|
242 end; |
|
243 |
|
244 function hwSqr(t: hwFloat): hwFloat; |
|
245 begin |
|
246 hwSqr:= t * t |
|
247 end; |
|
248 |
|
249 function Distance(dx, dy: hwFloat): hwFloat; |
|
250 var x, y: hwFloat; |
|
251 Result: hwFloat; |
|
252 begin |
|
253 x:= dx * dx; |
|
254 y:= dy * dy; |
|
255 Result:= x + y; |
|
256 Result.QWordValue:= Round(sqrt(1.0 / 4294967296 * (Result.QWordValue)) * 4294967296); |
|
257 Distance:= Result |
|
258 end; |
|
259 |
|
260 function AngleSin(angle: Longword): hwFloat; |
|
261 begin |
|
262 AngleSin.isNegative:= false; |
|
263 AngleSin:= Round(Sin(Angle * pi / cMaxAngle) * 4294967296) |
|
264 end; |
|
265 |
|
266 function AngleCos(angle: Longword): hwFloat; |
|
267 var CosVal: Extended; |
|
268 begin |
|
269 CosVal:= Cos(Angle * pi / cMaxAngle); |
|
270 AngleCos.isNegative:= CosVal < 0; |
|
271 AngleCos:= Round(Cosval * 4294967296) |
|
272 end; |
|
273 |
|
274 {$ENDIF} |
|
275 |
|
276 end. |