typ.pas 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579
  1. {
  2. This file is part of the Numlib package.
  3. Copyright (c) 1986-2000 by
  4. Kees van Ginneken, Wil Kortsmit and Loek van Reij of the
  5. Computational centre of the Eindhoven University of Technology
  6. FPC port Code by Marco van de Voort ([email protected])
  7. documentation by Michael van Canneyt ([email protected])
  8. This is the most basic unit from NumLib.
  9. The most important items this unit defines are matrix types and machine
  10. constants
  11. See the file COPYING.FPC, included in this distribution,
  12. for details about the copyright.
  13. This program is distributed in the hope that it will be useful,
  14. but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  16. **********************************************************************}
  17. {
  18. In the FPC revision, instead of picking a certain floating point type,
  19. a new type "ArbFloat" is defined, which is used as floating point type
  20. throughout the entire library. If you change the floating point type, you
  21. should only have to change ArbFloat, and the machineconstants belonging to
  22. the type you want.
  23. However for IEEE Double (64bit) and Extended(80bit) these constants are
  24. already defined, and autoselected by the library. (the library tests the
  25. size of the float type in bytes for 8 and 10 and picks the appropiate
  26. constants
  27. Also some stuff had to be added to get ipf running (vector object and
  28. complex.inp and scale methods)
  29. }
  30. {$mode objfpc}{$H+}
  31. {$modeswitch nestedprocvars}
  32. {$IFNDEF FPC_DOTTEDUNITS}
  33. unit typ;
  34. {$ENDIF FPC_DOTTEDUNITS}
  35. {$I DIRECT.INC} {Contains "global" compilerswitches which
  36. are imported into every unit of the library }
  37. interface
  38. {$IFDEF FPC_DOTTEDUNITS}
  39. uses
  40. System.Math;
  41. {$ELSE FPC_DOTTEDUNITS}
  42. uses
  43. Math;
  44. {$ENDIF FPC_DOTTEDUNITS}
  45. {$if sizeof(extended)=10}
  46. {$DEFINE ArbExtended}
  47. {$endif}
  48. CONST numlib_version=2; {used to detect version conflicts between
  49. header unit and dll}
  50. type {Definition of base types}
  51. {$IFDEF ArbExtended}
  52. ArbFloat = extended;
  53. {$ELSE}
  54. ArbFloat = double;
  55. {$ENDIF}
  56. ArbInt = LONGINT;
  57. ArbString = AnsiString;
  58. Float8Arb =ARRAY[0..7] OF BYTE;
  59. Float10Arb =ARRAY[0..9] OF BYTE;
  60. CONST {Some constants for the variables below, in binary formats.}
  61. {$IFNDEF ArbExtended}
  62. {First for REAL/Double}
  63. TC1 : Float8Arb = ($00,$00,$00,$00,$00,$00,$B0,$3C);
  64. TC2 : Float8Arb = ($FF,$FF,$FF,$FF,$FF,$FF,$EF,$7F);
  65. TC3 : Float8Arb = ($00,$00,$00,$00,$01,$00,$10,$00);
  66. TC5 : Float8Arb = ($EF,$39,$FA,$FE,$42,$2E,$86,$40);
  67. TC6 : Float8Arb = ($D6,$BC,$FA,$BC,$2B,$23,$86,$C0);
  68. {$ENDIF}
  69. {For Extended}
  70. {$IFDEF ArbExtended}
  71. TC1 : Float10Arb = (0,0,$00,$00,$00,$00,0,128,192,63); {Eps}
  72. TC2 : Float10Arb = ($FF,$FF,$FF,$FF,$FF,$FF,$FF,$D6,$FE,127); {9.99188560553925115E+4931}
  73. TC3 : Float10Arb = (1,0,0,0,0,0,0,0,0,0); {3.64519953188247460E-4951}
  74. TC5 : Float10Arb = (18,25,219,91,61,101,113,177,12,64); {1.13563488668777920E+0004}
  75. TC6 : Float10Arb = (108,115,3,170,182,56,27,178,12,192); {-1.13988053843083006E+0004}
  76. {$ENDIF}
  77. { numdig is the number of useful (safe) decimal places of an "ArbFloat"
  78. for display.
  79. minform is the number of decimal places shown by the rtls
  80. write(x:ArbFloat)
  81. maxform is the maximal number of decimal positions
  82. }
  83. numdig = 25;
  84. minform = 10;
  85. maxform = 26;
  86. var
  87. macheps : ArbFloat absolute TC1; { macheps = r - 1, with r
  88. the smallest ArbFloat > 1}
  89. giant : ArbFloat absolute TC2; { the largest ArbFloat}
  90. midget : ArbFloat absolute TC3; { the smallest positive ArbFloat}
  91. LnGiant : ArbFloat absolute TC5; {ln of giant}
  92. LnMidget : ArbFloat absolute TC6; {ln of midget}
  93. {Copied from Det. Needs ArbExtended conditional}
  94. const { og = 8^-maxexp, ogý>=midget,
  95. bg = 8^maxexp, bgý<=giant
  96. midget and giant are defined in typ.pas}
  97. {$IFDEF ArbExtended}
  98. ogx: Float10Arb = (51,158,223,249,51,243,4,181,224,31);
  99. bgx: Float10Arb = (108,119,117,92,70,38,155,234,254,95);
  100. maxexpx : ArbInt = 2740;
  101. {$ELSE}
  102. ogx: Float8Arb= (84, 254, 32, 128, 32, 0, 0, 32);
  103. bgx: Float8Arb= (149, 255, 255, 255, 255, 255, 239, 95);
  104. maxexpx : ArbInt = 170;
  105. {$ENDIF}
  106. var
  107. og : ArbFloat absolute ogx;
  108. bg : ArbFloat absolute bgx;
  109. MaxExp : ArbInt absolute maxexpx;
  110. {Like standard EXP(), but for very small values (near lowest possible
  111. ArbFloat this version returns 0}
  112. Function exp(x: ArbFloat): ArbFloat;
  113. type
  114. Complex = object
  115. { Crude complex record. For me an example of
  116. useless OOP, specially if you have operator overloading
  117. }
  118. xreal, imag : ArbFloat;
  119. procedure Init (r, i: ArbFloat);
  120. procedure Add (c: complex);
  121. procedure Sub (c: complex);
  122. function Inp(z:complex):ArbFloat;
  123. procedure Conjugate;
  124. procedure Scale(s: ArbFloat);
  125. Function Norm : ArbFloat;
  126. Function Size : ArbFloat;
  127. Function Re : ArbFloat;
  128. procedure Unary;
  129. Function Im : ArbFloat;
  130. Function Arg : ArbFloat;
  131. procedure MinC(c: complex);
  132. procedure MaxC(c: complex);
  133. Procedure TransF(var t: complex);
  134. end;
  135. vector = object
  136. i, j, k: ArbFloat;
  137. procedure Init (vii, vjj, vkk: ArbFloat);
  138. procedure Unary;
  139. procedure Add (c: vector);
  140. procedure Sub (c: vector);
  141. function Vi : ArbFloat;
  142. function Vj : ArbFloat;
  143. function Vk : ArbFloat;
  144. function Norm : ArbFloat;
  145. Function Norm8 : ArbFloat;
  146. function Size : ArbFloat;
  147. function InProd(c: vector): ArbFloat;
  148. procedure Uitprod(c: vector; var e: vector);
  149. procedure Scale(s: ArbFloat);
  150. procedure DScale(s: ArbFloat);
  151. procedure Normalize;
  152. procedure Rotate(calfa, salfa: ArbFloat; axe: vector);
  153. procedure Show(p,q: ArbInt);
  154. end;
  155. transformorg = record offset: complex; ss, sc: real end;
  156. transform = record
  157. offsetx, offsety, scalex, scaley: ArbFloat
  158. end;
  159. {Standard Functions used in NumLib}
  160. rfunc1r = Function(x : ArbFloat): ArbFloat;
  161. rfunc1rn = Function(x : ArbFloat): ArbFloat is nested;
  162. rfunc2r = Function(x, y : ArbFloat): ArbFloat;
  163. {Complex version}
  164. rfunc1z = Function(z: complex): ArbFloat;
  165. {Special Functions}
  166. oderk1n = procedure(x: ArbFloat; var y, f: ArbFloat);
  167. roofnrfunc = procedure(var x, fx: ArbFloat; var deff: boolean);
  168. {Maximal n x m dimensions of matrix.
  169. +/- highestelement*SIZEOF(elementtype) is
  170. minimal size of matrix.}
  171. const
  172. highestfloatelement = High(ArbInt) div SizeOf(ArbFloat);
  173. highestptrelement = High(ArbInt) div SizeOf(Pointer);
  174. highestintelement = High(ArbInt) div SizeOf(ArbInt);
  175. highestboolelement = High(ArbInt) div SizeOf(boolean);
  176. highestcomplexelement = High(ArbInt) div SizeOf(complex);
  177. highestvectorelement = High(ArbInt) div SizeOf(vector);
  178. type
  179. {Definition of matrix types in NumLib. First some vectors.
  180. The high boundery is a maximal number only. Vectors can be smaller, but
  181. not bigger. The difference is the starting number}
  182. arfloat0 = array[0..highestfloatelement-1] of ArbFloat;
  183. arfloat1 = array[1..highestfloatelement] of ArbFloat;
  184. arfloat2 = array[2..highestfloatelement+1] of ArbFloat;
  185. arfloat_1 = array[-1..highestfloatelement-2] of ArbFloat;
  186. {A matrix is an array of floats}
  187. ar2dr = array[0..highestptrelement-1] of ^arfloat0;
  188. ar2dr1 = array[1..highestptrelement] of ^arfloat1;
  189. {Matrices can get big, so we mosttimes allocate them on the heap.}
  190. par2dr1 = ^ar2dr1;
  191. {Integer vectors}
  192. arint0 = array[0..highestintelement-1] of ArbInt;
  193. arint1 = array[1..highestintelement] of ArbInt;
  194. {Boolean (true/false) vectors}
  195. arbool1 = array[1..highestboolelement] of boolean;
  196. {Complex vectors}
  197. arcomp0 = array[0..highestcomplexelement-1] of complex;
  198. arcomp1 = array[1..highestcomplexelement] of complex;
  199. arvect0 = array[0..highestvectorelement-1] of vector;
  200. vectors = array[1..highestvectorelement] of vector;
  201. parcomp = ^arcomp1;
  202. {(de) Allocate mxn matrix to A}
  203. procedure AllocateAr2dr(m, n: integer; var a: par2dr1);
  204. procedure DeAllocateAr2dr(m, n: integer; var a: par2dr1);
  205. {(de) allocate below-left triangle matrix for (de)convolution
  206. (a 3x3 matrix looks like this
  207. x
  208. x x
  209. x x x)
  210. }
  211. procedure AllocateL2dr(n: integer; var a: par2dr1);
  212. procedure DeAllocateL2dr(n: integer; var a: par2dr1);
  213. {Get the Re and Im parts of a complex type}
  214. Function Re(z: complex): ArbFloat;
  215. Function Im(z: complex): ArbFloat;
  216. { Creates a string from a floatingpoint value}
  217. Function R2S(x: ArbFloat; p, q: integer): ShortString;
  218. {Calculate inproduct of V1 and V2, which are vectors with N elements;
  219. I1 and I2 are the SIZEOF the datatypes of V1 and V2
  220. MvdV: Change this to "V1,V2:array of ArbFloat and forget the i1 and i2
  221. parameters?}
  222. Function Inprod(var V1, V2; n, i1, i2: ArbInt): ArbFloat;
  223. {Return certain special machine constants.(macheps=1, Nan=7)}
  224. Function MachCnst(n: ArbInt): ArbFloat;
  225. function dllversion:LONGINT;
  226. implementation
  227. Function MachCnst(n: ArbInt): ArbFloat;
  228. begin
  229. case n of
  230. 1: MachCnst := macheps;
  231. 2: MachCnst := giant;
  232. 3: MachCnst := midget;
  233. 4: MachCnst := infinity;
  234. 5: MachCnst := LnGiant;
  235. 6: MachCnst := LnMidget;
  236. 7: MachCnst := Nan;
  237. end
  238. end;
  239. { Are used in many of the example programs}
  240. Function Re(z: complex): ArbFloat;
  241. begin
  242. Re := z.xreal
  243. end;
  244. Function Im(z: complex): ArbFloat;
  245. begin
  246. Im := z.imag
  247. end;
  248. {Kind of Sysutils.TrimRight and TrimLeft called after eachother}
  249. procedure Compress(var s: ShortString);
  250. var i, j: LONGINT;
  251. begin
  252. j := length(s);
  253. while (j>0) and (s[j]=' ') do dec(j);
  254. i := 1;
  255. while (i<=j) and (s[i]=' ') do Inc(i);
  256. s := copy(s, i, j+1-i)
  257. end;
  258. Function R2S(x: ArbFloat; p, q: integer): ShortString;
  259. var s: ShortString;
  260. i, j, k: integer;
  261. begin
  262. if q=-1 then
  263. begin
  264. Str(x:p, s);
  265. i := Pos('E', s)-1; k := i+1;
  266. j := i+3; while (j<length(s)) and (s[j]='0') do inc(j);
  267. while s[i]='0' do dec(i); if s[i]='.' then dec(i);
  268. if s[j]='0' then s := copy(s,1,i) else
  269. if s[k]='-' then
  270. s := copy(s, 1, i)+'E-'+Copy(s, j, length(s)+1-j)
  271. else
  272. s := copy(s, 1, i)+'E'+Copy(s, j, length(s)+1-j)
  273. end
  274. else
  275. Str(x:p:q, s);
  276. Compress(s);
  277. R2S := s
  278. end;
  279. procedure AllocateAr2dr(m, n: integer; var a: par2dr1);
  280. var i: integer;
  281. begin
  282. GetMem(a, m*SizeOf(pointer));
  283. for i:=1 to m do GetMem(a^[i], n*SizeOf(ArbFloat))
  284. end;
  285. procedure DeAllocateAr2dr(m, n: integer; var a: par2dr1);
  286. var i: integer;
  287. begin
  288. for i:=m downto 1 do FreeMem(a^[i], n*SizeOf(ArbFloat));
  289. FreeMem(a, m*SizeOf(pointer));
  290. a := Nil
  291. end;
  292. procedure AllocateL2dr(n: integer; var a: par2dr1);
  293. var i: integer;
  294. begin
  295. GetMem(a, n*SizeOf(pointer));
  296. for i:=1 to n do GetMem(a^[i], i*SizeOf(ArbFloat))
  297. end;
  298. procedure DeAllocateL2dr(n: integer; var a: par2dr1);
  299. var i: integer;
  300. begin
  301. for i:=n downto 1 do FreeMem(a^[i], i*SizeOf(ArbFloat));
  302. FreeMem(a, n*SizeOf(pointer));
  303. a := Nil
  304. end;
  305. procedure Complex.Init(r, i: ArbFloat);
  306. begin
  307. xreal:= r;
  308. imag := i
  309. end;
  310. procedure Complex.Conjugate;
  311. begin
  312. imag := -imag
  313. end;
  314. function Complex.Inp(z:complex):ArbFloat;
  315. begin
  316. Inp := xreal*z.xreal + imag*z.imag
  317. end;
  318. procedure Complex.MinC(c: complex);
  319. begin if c.xreal<xreal then xreal := c.xreal;
  320. if c.imag<imag then imag := c.imag
  321. end;
  322. procedure Complex.Maxc(c: complex);
  323. begin if c.xreal>xreal then xreal := c.xreal;
  324. if c.imag>imag then imag := c.imag
  325. end;
  326. procedure Complex.Add(c: complex);
  327. begin
  328. xreal := xreal + c.xreal; imag := imag + c.imag
  329. end;
  330. procedure Complex.Sub(c: complex);
  331. begin
  332. xreal := xreal - c.xreal; imag := imag - c.imag
  333. end;
  334. Function Complex.Norm: ArbFloat;
  335. begin
  336. Norm := Sqr(xreal) + Sqr(imag)
  337. end;
  338. Function Complex.Size: ArbFloat;
  339. begin
  340. Size := Sqrt(Norm)
  341. end;
  342. Function Complex.Re: ArbFloat;
  343. begin
  344. Re := xreal;
  345. end;
  346. Function Complex.Im: ArbFloat;
  347. begin
  348. Im := imag
  349. end;
  350. Procedure Complex.TransF(var t: complex);
  351. var w: complex;
  352. tt: transformorg absolute t;
  353. begin
  354. w := Self; Conjugate;
  355. with tt do
  356. begin
  357. w.scale(ss);
  358. scale(sc);
  359. Add(offset)
  360. end;
  361. Add(w)
  362. end;
  363. procedure Complex.Unary;
  364. begin
  365. xreal := -xreal;
  366. imag := -imag
  367. end;
  368. procedure Complex.Scale(s:ArbFloat);
  369. begin
  370. xreal := xreal*s; imag := imag*s
  371. end;
  372. Function Complex.Arg: ArbFloat;
  373. begin
  374. if xreal=0 then
  375. if imag>0 then Arg := 0.5*pi else
  376. if imag=0 then Arg := 0 else Arg := -0.5*pi else
  377. if xReal>0 then Arg := ArcTan(imag/xReal)
  378. else if imag>=0 then Arg := ArcTan(imag/xReal) + pi
  379. else Arg := ArcTan(imag/xReal) - pi
  380. end;
  381. Function exp(x: ArbFloat): ArbFloat;
  382. begin
  383. if x<LnMidget then exp := 0 else exp := system.exp(x)
  384. end;
  385. { procedure berekent: v1 = v1 + r*v2 i1 en i2 geven de
  386. increments in bytes voor v1 en v2 }
  387. Function Inprod(var V1, V2; n, i1, i2: ArbInt): ArbFloat;
  388. VAR i: LONGINT;
  389. p1, p2: ^ArbFloat;
  390. s: ArbFloat;
  391. begin
  392. IF I1 <>SIZEOF(ArbFloat) THEN
  393. BEGIN
  394. WRITELN('1 Something went probably wrong while porting!');
  395. HALT;
  396. END;
  397. p1 := @v1; p2 := @v2; s := 0;
  398. for i:=1 to n do
  399. begin
  400. s := s + p1^*p2^;
  401. Inc(ptrint(p1), i1);
  402. Inc(ptrint(p2), i2)
  403. end;
  404. Inprod := s
  405. end;
  406. procedure Vector.Init(vii, vjj, vkk: ArbFloat);
  407. begin
  408. i := vii; j := vjj; k := vkk
  409. end;
  410. procedure Vector.Unary;
  411. begin i := -i; j := -j; k := -k end;
  412. procedure Vector.Add(c: vector);
  413. begin
  414. i := i + c.i; j := j + c.j; k := k + c.k
  415. end;
  416. procedure Vector.Sub(c: vector);
  417. begin
  418. i := i - c.i; j := j - c.j; k := k - c.k
  419. end;
  420. function Vector.Vi : ArbFloat; begin Vi := i end;
  421. function Vector.Vj : ArbFloat; begin Vj := j end;
  422. function Vector.Vk : ArbFloat; begin Vk := k end;
  423. function Vector.Norm:ArbFloat;
  424. begin
  425. Norm := Sqr(i) + Sqr(j) + Sqr(k)
  426. end;
  427. function Vector.Norm8:ArbFloat;
  428. var r: ArbFloat;
  429. begin
  430. r := abs(i);
  431. if abs(j)>r then r := abs(j);
  432. if abs(k)>r then r := abs(k);
  433. Norm8 := r
  434. end;
  435. function Vector.Size: ArbFloat;
  436. begin
  437. Size := Sqrt(Norm)
  438. end;
  439. function Vector.InProd(c: vector): ArbFloat;
  440. begin
  441. InProd := i*c.i + j*c.j + k*c.k
  442. end;
  443. procedure Vector.Uitprod(c: vector; var e: vector);
  444. begin
  445. e.i := j*c.k - k*c.j;
  446. e.j := k*c.i - i*c.k;
  447. e.k := i*c.j - j*c.i
  448. end;
  449. procedure Vector.Scale(s: ArbFloat);
  450. begin
  451. i := i*s; j := j*s; k := k*s
  452. end;
  453. procedure Vector.DScale(s: ArbFloat);
  454. begin
  455. i := i/s; j := j/s; k := k/s
  456. end;
  457. procedure Vector.Normalize;
  458. begin
  459. DScale(Size)
  460. end;
  461. procedure Vector.Show(p,q:ArbInt);
  462. begin writeln(i:p:q, 'I', j:p:q, 'J', k:p:q, 'K') end;
  463. procedure Vector.Rotate(calfa, salfa: arbfloat; axe: vector);
  464. var qv : vector;
  465. begin
  466. Uitprod(axe, qv); qv.scale(salfa);
  467. axe.scale((1-calfa)*Inprod(axe));
  468. scale(calfa); sub(qv); add(axe)
  469. end;
  470. function dllversion:LONGINT;
  471. BEGIN
  472. dllversion:=numlib_version;
  473. END;
  474. END.