author  unc0rr 
Wed, 18 Mar 2009 15:48:43 +0000  
changeset 1899  5763f46d7486 
parent 1753  2ccba26f1aa4 
child 1915  c357f5b55320 
permissions  rwrr 
351  1 
(* 
1066  2 
* Hedgewars, a free turn based strategy game 
883  3 
* Copyright (c) 2007, 2008 Andrey Korotaev <unC0Rr@gmail.com> 
351  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 021111307, USA 

17 
*) 

18 

19 
unit uFloat; 

20 
interface 

21 

1629  22 
{$INCLUDE options.inc} 
23 

351  24 
{$IFDEF FPC} 
25 
{$ifdef FPC_LITTLE_ENDIAN} 

26 
type hwFloat = record 

27 
isNegative: boolean; 

28 
case byte of 

29 
0: (Frac, Round: Longword); 

30 
1: (QWordValue : QWord); 

31 
end; 

32 
{$else FPC_LITTLE_ENDIAN} 

33 
type hwFloat = record 

34 
isNegative: boolean; 

35 
case byte of 

36 
0: (Round, Frac: Longword); 

37 
1: (QWordValue : QWord); 

38 
end; 

39 
{$endif FPC_LITTLE_ENDIAN} 

40 

515  41 
function int2hwFloat (const i: LongInt) : hwFloat; 
351  42 

515  43 
operator + (const z1, z2: hwFloat) z : hwFloat; 
44 
operator  (const z1, z2: hwFloat) z : hwFloat; 

45 
operator  (const z1: hwFloat) z : hwFloat; 

351  46 

515  47 
operator * (const z1, z2: hwFloat) z : hwFloat; 
48 
operator * (const z1: hwFloat; const z2: LongInt) z : hwFloat; 

49 
operator / (const z1: hwFloat; z2: hwFloat) z : hwFloat; 

50 
operator / (const z1: hwFloat; const z2: LongInt) z : hwFloat; 

351  51 

515  52 
operator < (const z1, z2: hwFloat) b : boolean; 
53 
operator > (const z1, z2: hwFloat) b : boolean; 

351  54 

515  55 
function cstr(const z: hwFloat): string; 
56 
function hwRound(const t: hwFloat): LongInt; 

57 
function hwAbs(const t: hwFloat): hwFloat; 

58 
function hwSqr(const t: hwFloat): hwFloat; 

59 
function hwSqrt(const t: hwFloat): hwFloat; 

60 
function Distance(const dx, dy: hwFloat): hwFloat; 

61 
function DistanceI(const dx, dy: LongInt): hwFloat; 

62 
function AngleSin(const Angle: Longword): hwFloat; 

63 
function AngleCos(const Angle: Longword): hwFloat; 

64 
function SignAs(const num, signum: hwFloat): hwFloat; 

351  65 

538  66 
{$J} 
611  67 
{$WARNINGS OFF} 
351  68 
const _1div1024: hwFloat = (isNegative: false; QWordValue: 4194304); 
69 
_1div10000: hwFloat = (isNegative: false; QWordValue: 429496); 

70 
_1div50000: hwFloat = (isNegative: false; QWordValue: 85899); 

71 
_1div100000: hwFloat = (isNegative: false; QWordValue: 42950); 

72 
_1div3: hwFloat = (isNegative: false; QWordValue: 1431655766); 

73 
hwPi: hwFloat = (isNegative: false; QWordValue: 13493037704); 

74 
_0_000004: hwFloat = (isNegative: false; QWordValue: 17179); 

75 
_0_0002: hwFloat = (isNegative: false; QWordValue: 858993); 

1586  76 
_0_0005: hwFloat = (isNegative: false; QWordValue: 2147484); 
351  77 
_0_001: hwFloat = (isNegative: false; QWordValue: 4294967); 
78 
_0_003: hwFloat = (isNegative: false; QWordValue: 12884902); 

79 
_0_004: hwFloat = (isNegative: false; QWordValue: 17179869); 

80 
_0_005: hwFloat = (isNegative: false; QWordValue: 21474836); 

81 
_0_01: hwFloat = (isNegative: false; QWordValue: 42949673); 

82 
_0_02: hwFloat = (isNegative: false; QWordValue: 85899345); 

83 
_0_03: hwFloat = (isNegative: false; QWordValue: 128849018); 

84 
_0_08: hwFloat = (isNegative: false; QWordValue: 343597383); 

365  85 
_0_1: hwFloat = (isNegative: false; QWordValue: 429496730); 
351  86 
_0_15: hwFloat = (isNegative: false; QWordValue: 644245094); 
87 
_0_2: hwFloat = (isNegative: false; QWordValue: 858993459); 

88 
_0_25: hwFloat = (isNegative: false; QWordValue: 1073741824); 

89 
_0_3: hwFloat = (isNegative: false; QWordValue: 1288490189); 

90 
_0_35: hwFloat = (isNegative: false; QWordValue: 1503238553); 

835
6f567934cc44
Automatically use parachute when vertical speed is high enough
unc0rr
parents:
745
diff
changeset

91 
_0_39: hwFloat = (isNegative: false; QWordValue: 1675037245); 
351  92 
_0_4: hwFloat = (isNegative: false; QWordValue: 1717986918); 
93 
_0_45: hwFloat = (isNegative: false; QWordValue: 1932735283); 

94 
_0_5: hwFloat = (isNegative: false; QWordValue: 2147483648); 

95 
_0_55: hwFloat = (isNegative: false; QWordValue: 2362232012); 

96 
_0_6: hwFloat = (isNegative: false; QWordValue: 2576980377); 

358  97 
_0_7: hwFloat = (isNegative: false; QWordValue: 3006477107); 
351  98 
_0_8: hwFloat = (isNegative: false; QWordValue: 3435973837); 
99 
_0_84: hwFloat = (isNegative: false; QWordValue: 3607772528); 

100 
_0_87: hwFloat = (isNegative: false; QWordValue: 3736621547); 

101 
_0_9: hwFloat = (isNegative: false; QWordValue: 3865470566); 

102 
_0_93: hwFloat = (isNegative: false; QWordValue: 3994319585); 

103 
_0_96: hwFloat = (isNegative: false; QWordValue: 4123168604); 

104 
_0_995: hwFloat = (isNegative: false; QWordValue: 4273492459); 

1433  105 
_0_998: hwFloat = (isNegative: false; QWordValue: 4294967296); 
351  106 
_0_999: hwFloat = (isNegative: false; QWordValue: 4290672328); 
107 
_1_9: hwFloat = (isNegative: false; QWordValue: 8160437862); 

498  108 
_0: hwFloat = (isNegative: false; QWordValue: 0); 
109 
_1: hwFloat = (isNegative: false; QWordValue: 4294967296); 

513
69e06d710d46
Moving hedgehog could get another hedgehog moving forward
unc0rr
parents:
498
diff
changeset

110 
_1_5: hwFloat = (isNegative: false; QWordValue: 4294967296 * 3 div 2); 
498  111 
_2: hwFloat = (isNegative: false; QWordValue: 4294967296 * 2); 
112 
_3: hwFloat = (isNegative: false; QWordValue: 4294967296 * 3); 

113 
_4: hwFloat = (isNegative: false; QWordValue: 4294967296 * 4); 

114 
_5: hwFloat = (isNegative: false; QWordValue: 4294967296 * 5); 

115 
_6: hwFloat = (isNegative: false; QWordValue: 4294967296 * 6); 

116 
_10: hwFloat = (isNegative: false; QWordValue: 4294967296 * 10); 

117 
_16: hwFloat = (isNegative: false; QWordValue: 4294967296 * 16); 

118 
_19: hwFloat = (isNegative: false; QWordValue: 4294967296 * 19); 

119 
_20: hwFloat = (isNegative: false; QWordValue: 4294967296 * 20); 

1652  120 
_0_3x70: hwFloat = (isNegative: false; QWordValue: 1288490189 * 70); 
498  121 
_25: hwFloat = (isNegative: false; QWordValue: 4294967296 * 25); 
122 
_30: hwFloat = (isNegative: false; QWordValue: 4294967296 * 30); 

123 
_128: hwFloat = (isNegative: false; QWordValue: 4294967296 * 128); 

1124  124 
_300: hwFloat = (isNegative: false; QWordValue: 4294967296 * 300); 
498  125 
_450: hwFloat = (isNegative: false; QWordValue: 4294967296 * 450); 
611  126 
_1024: hwFloat = (isNegative: false; QWordValue: 4294967296 * 1024); 
127 
_2048: hwFloat = (isNegative: false; QWordValue: 4294967296 * 2048); 

1753  128 
_4096: hwFloat = (isNegative: false; QWordValue: 4294967296 * 4096); 
498  129 
_10000: hwFloat = (isNegative: false; QWordValue: 4294967296 * 10000); 
351  130 

131 
cLittle: hwFloat = (isNegative: false; QWordValue: 1); 

967  132 
cHHKick: hwFloat = (isNegative: false; QWordValue: 42949673); // _0_01 
611  133 
{$WARNINGS ON} 
351  134 
{$ENDIF} 
135 

136 
{$IFNDEF FPC} 

137 
type hwFloat = Extended; 

138 
{$ENDIF} 

139 

140 
implementation 

744  141 
uses uConsts, uMisc; 
351  142 

143 
{$IFDEF FPC} 

144 

515  145 
function int2hwFloat (const i: LongInt) : hwFloat; 
351  146 
begin 
498  147 
int2hwFloat.isNegative:= i < 0; 
148 
int2hwFloat.Round:= abs(i); 

149 
int2hwFloat.Frac:= 0 

351  150 
end; 
151 

515  152 
operator + (const z1, z2: hwFloat) z : hwFloat; 
351  153 
begin 
154 
if z1.isNegative = z2.isNegative then 

155 
begin 

156 
z.isNegative:= z1.isNegative; 

157 
z.QWordValue:= z1.QWordValue + z2.QWordValue 

158 
end 

159 
else 

160 
if z1.QWordValue > z2.QWordValue then 

161 
begin 

162 
z.isNegative:= z1.isNegative; 

163 
z.QWordValue:= z1.QWordValue  z2.QWordValue 

164 
end else 

165 
begin 

166 
z.isNegative:= z2.isNegative; 

167 
z.QWordValue:= z2.QWordValue  z1.QWordValue 

168 
end 

169 
end; 

170 

515  171 
operator  (const z1, z2: hwFloat) z : hwFloat; 
351  172 
begin 
173 
if z1.isNegative = z2.isNegative then 

174 
if z1.QWordValue > z2.QWordValue then 

175 
begin 

176 
z.isNegative:= z1.isNegative; 

177 
z.QWordValue:= z1.QWordValue  z2.QWordValue 

178 
end else 

179 
begin 

180 
z.isNegative:= not z2.isNegative; 

181 
z.QWordValue:= z2.QWordValue  z1.QWordValue 

182 
end 

183 
else begin 

184 
z.isNegative:= z1.isNegative; 

185 
z.QWordValue:= z1.QWordValue + z2.QWordValue 

186 
end 

187 
end; 

188 

515  189 
operator  (const z1: hwFloat) z : hwFloat; 
351  190 
begin 
191 
z:= z1; 

192 
z.isNegative:= not z.isNegative 

193 
end; 

194 

195 

515  196 
operator * (const z1, z2: hwFloat) z : hwFloat; 
351  197 
begin 
198 
z.isNegative:= z1.isNegative xor z2.isNegative; 

199 
z.QWordValue:= QWord(z1.Round) * z2.Frac + 

200 
QWord(z1.Frac) * z2.Round + 

201 
((QWord(z1.Frac) * z2.Frac) shr 32); 

202 
z.Round:= z.Round + QWord(z1.Round) * z2.Round; 

203 
end; 

204 

515  205 
operator * (const z1: hwFloat; const z2: LongInt) z : hwFloat; 
351  206 
begin 
207 
z.isNegative:= z1.isNegative xor (z2 < 0); 

515  208 
z.QWordValue:= z1.QWordValue * abs(z2) 
351  209 
end; 
210 

515  211 
operator / (const z1: hwFloat; z2: hwFloat) z : hwFloat; 
351  212 
var t: hwFloat; 
213 
begin 

214 
z.isNegative:= z1.isNegative xor z2.isNegative; 

215 
z.Round:= z1.QWordValue div z2.QWordValue; 

216 
t:= z1  z2 * z.Round; 

217 
if t.QWordValue = 0 then 

218 
z.Frac:= 0 

219 
else 

220 
begin 

221 
while ((t.QWordValue and $8000000000000000) = 0) and 

222 
((z2.QWordValue and $8000000000000000) = 0) do 

223 
begin 

224 
t.QWordValue:= t.QWordValue shl 1; 

225 
z2.QWordValue:= z2.QWordValue shl 1 

226 
end; 

543
465e2ec8f05f
 Better randomness of placing hedgehogs on the land
unc0rr
parents:
538
diff
changeset

227 
if z2.Round > 0 then z.Frac:= (t.QWordValue) div (z2.Round) 
465e2ec8f05f
 Better randomness of placing hedgehogs on the land
unc0rr
parents:
538
diff
changeset

228 
else z.Frac:= 0 
351  229 
end 
230 
end; 

231 

515  232 
operator / (const z1: hwFloat; const z2: LongInt) z : hwFloat; 
498  233 
begin 
234 
z.isNegative:= z1.isNegative xor (z2 < 0); 

515  235 
z.QWordValue:= z1.QWordValue div abs(z2) 
498  236 
end; 
237 

515  238 
operator < (const z1, z2: hwFloat) b : boolean; 
351  239 
begin 
916  240 
if z1.isNegative xor z2.isNegative then 
351  241 
b:= z1.isNegative 
242 
else 

243 
if z1.QWordValue = z2.QWordValue then 

244 
b:= false 

245 
else 

246 
b:= (z1.QWordValue < z2.QWordValue) xor z1.isNegative 

247 
end; 

248 

515  249 
operator > (const z1, z2: hwFloat) b : boolean; 
351  250 
begin 
916  251 
if z1.isNegative xor z2.isNegative then 
351  252 
b:= z2.isNegative 
253 
else 

254 
if z1.QWordValue = z2.QWordValue then 

255 
b:= false 

256 
else 

257 
b:= (z1.QWordValue > z2.QWordValue) xor z2.isNegative 

258 
end; 

259 

515  260 
function cstr(const z: hwFloat): string; 
351  261 
var tmpstr: string; 
262 
begin 

263 
str(z.Round, cstr); 

264 
if z.Frac <> 0 then 

265 
begin 

266 
str(z.Frac / $100000000:1:15, tmpstr); 

267 
delete(tmpstr, 1, 2); 

268 
cstr:= cstr + '.' + tmpstr 

269 
end; 

270 
if z.isNegative then cstr:= '' + cstr 

271 
end; 

272 

515  273 
function hwRound(const t: hwFloat): LongInt; 
351  274 
begin 
275 
if t.isNegative then hwRound:= t.Round 

276 
else hwRound:= t.Round 

277 
end; 

278 

515  279 
function hwAbs(const t: hwFloat): hwFloat; 
351  280 
begin 
281 
hwAbs:= t; 

282 
hwAbs.isNegative:= false 

283 
end; 

284 

515  285 
function hwSqr(const t: hwFloat): hwFloat; 
351  286 
begin 
1433  287 
hwSqr.isNegative:= false; 
288 
hwSqr.QWordValue:= 

289 
((QWord(t.Round) * t.Round) shl 32) 

290 
+ QWord(t.Round) * t.Frac * 2 

291 
+ ((QWord(t.Frac) * t.Frac) shr 32); 

351  292 
end; 
293 

515  294 
function hwSqrt(const t: hwFloat): hwFloat; 
738  295 
var l, r: QWord; 
296 
c: hwFloat; 

357  297 
begin 
298 
hwSqrt.isNegative:= false; 

744  299 

300 
if t.Round = 0 then 

301 
begin 

302 
l:= t.QWordValue; 

303 
r:= $100000000 

304 
end else 

305 
begin 

306 
l:= $100000000; 

953
237fc147950c
Fix bug in hwSqrt when calculating square root of number >= 65536
unc0rr
parents:
916
diff
changeset

307 
r:= t.QWordValue div 2 + $80000000; // r:= t / 2 + 0.5 
237fc147950c
Fix bug in hwSqrt when calculating square root of number >= 65536
unc0rr
parents:
916
diff
changeset

308 
if r > $FFFFFFFFFFFF then r:= $FFFFFFFFFFFF 
744  309 
end; 
310 

738  311 
repeat 
312 
c.QWordValue:= (l + r) div 2; 

313 
if hwSqr(c).QWordValue > t.QWordValue then r:= c.QWordValue else l:= c.QWordValue 

314 
until r  l <= 1; 

744  315 

738  316 
hwSqrt.QWordValue:= l 
357  317 
end; 
318 

515  319 
function Distance(const dx, dy: hwFloat): hwFloat; 
351  320 
begin 
738  321 
Distance:= hwSqrt(hwSqr(dx) + hwSqr(dy)) 
351  322 
end; 
323 

515  324 
function DistanceI(const dx, dy: LongInt): hwFloat; 
498  325 
begin 
856  326 
DistanceI:= hwSqrt(int2hwFloat(sqr(dx) + sqr(dy))) 
498  327 
end; 
328 

515  329 
function SignAs(const num, signum: hwFloat): hwFloat; 
498  330 
begin 
856  331 
SignAs.QWordValue:= num.QWordValue; 
498  332 
SignAs.isNegative:= signum.isNegative 
333 
end; 

334 

357  335 
{$INCLUDE SinTable.inc} 
336 

515  337 
function AngleSin(const Angle: Longword): hwFloat; 
351  338 
begin 
1629  339 
{$IFDEF DEBUGFILE} 
1640  340 
TryDo((Angle >= 0) and (Angle <= 2048), 'Sin param exceeds limits', true); 
1629  341 
{$ENDIF} 
351  342 
AngleSin.isNegative:= false; 
357  343 
if Angle < 1024 then AngleSin.QWordValue:= SinTable[Angle] 
344 
else AngleSin.QWordValue:= SinTable[2048  Angle] 

351  345 
end; 
346 

515  347 
function AngleCos(const Angle: Longword): hwFloat; 
351  348 
begin 
1629  349 
{$IFDEF DEBUGFILE} 
1640  350 
TryDo((Angle >= 0) and (Angle <= 2048), 'Cos param exceeds limits', true); 
1629  351 
{$ENDIF} 
357  352 
AngleCos.isNegative:= Angle > 1024; 
353 
if Angle < 1024 then AngleCos.QWordValue:= SinTable[1024  Angle] 

354 
else AngleCos.QWordValue:= SinTable[Angle  1024] 

351  355 
end; 
356 

357 
{$ENDIF} 

358 

359 
end. 