Subversion Repositories Kolibri OS

Rev

Rev 8859 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
9893 akron1 1
(* ***********************************************
2
    Модуль работы с комплексными числами.
3
    Вадим Исаев, 2020
4
    Module for complex numbers.
5
    Vadim Isaev, 2020
6
*************************************************** *)
7
 
8
MODULE CMath;
9
 
10
IMPORT Math, Out;
11
 
12
TYPE
13
  complex* = POINTER TO RECORD
14
    re*: REAL;
15
    im*: REAL
16
  END;
17
 
18
VAR
19
  result: complex;
20
 
21
  i* : complex;
22
  _0*: complex;
23
 
24
(* Инициализация комплексного числа.
25
   Init complex number. *)
26
PROCEDURE CInit* (re : REAL; im: REAL): complex;
27
VAR
28
  temp: complex;
29
BEGIN
30
  NEW(temp);
31
  temp.re:=re;
32
  temp.im:=im;
33
 
34
  RETURN temp
35
END CInit;
36
 
37
 
38
(* Четыре основных арифметических операций.
39
   Four base operations  +, -, * , / *)
40
 
41
(* Сложение
42
   addition : z := z1 + z2 *)
43
PROCEDURE CAdd* (z1, z2: complex): complex;
44
BEGIN
45
  result.re := z1.re + z2.re;
46
  result.im := z1.im + z2.im;
47
 
48
  RETURN result
49
END CAdd;
50
 
51
(* Сложение с REAL.
52
   addition : z := z1 + r1 *)
53
PROCEDURE CAdd_r* (z1: complex; r1: REAL): complex;
54
BEGIN
55
  result.re := z1.re + r1;
56
  result.im := z1.im;
57
 
58
  RETURN result
59
END CAdd_r;
60
 
61
(* Сложение с INTEGER.
62
   addition : z := z1 + i1 *)
63
PROCEDURE CAdd_i* (z1: complex; i1: INTEGER): complex;
64
BEGIN
65
  result.re := z1.re + FLT(i1);
66
  result.im := z1.im;
67
 
68
  RETURN result
69
END CAdd_i;
70
 
71
(* Смена знака.
72
   substraction : z := - z1 *)
73
PROCEDURE CNeg (z1 : complex): complex;
74
BEGIN
75
  result.re := -z1.re;
76
  result.im := -z1.im;
77
 
78
  RETURN result
79
END CNeg;
80
 
81
(* Вычитание.
82
   substraction : z := z1 - z2 *)
83
PROCEDURE CSub* (z1, z2 : complex): complex;
84
BEGIN
85
  result.re := z1.re - z2.re;
86
  result.im := z1.im - z2.im;
87
 
88
  RETURN result
89
END CSub;
90
 
91
(* Вычитание REAL.
92
   substraction : z := z1 - r1 *)
93
PROCEDURE CSub_r1* (z1 : complex; r1 : REAL): complex;
94
BEGIN
95
  result.re := z1.re - r1;
96
  result.im := z1.im;
97
 
98
  RETURN result
99
END CSub_r1;
100
 
101
(* Вычитание из REAL.
102
   substraction : z := r1 - z1 *)
103
PROCEDURE CSub_r2* (r1 : REAL; z1 : complex): complex;
104
BEGIN
105
  result.re := r1 - z1.re;
106
  result.im := - z1.im;
107
 
108
  RETURN result
109
END CSub_r2;
110
 
111
(* Вычитание INTEGER.
112
   substraction : z := z1 - i1 *)
113
PROCEDURE CSub_i* (z1 : complex; i1 : INTEGER): complex;
114
BEGIN
115
  result.re := z1.re - FLT(i1);
116
  result.im := z1.im;
117
 
118
  RETURN result
119
END CSub_i;
120
 
121
(* Умножение.
122
   multiplication : z := z1 * z2 *)
123
PROCEDURE CMul (z1, z2 : complex): complex;
124
BEGIN
125
  result.re := (z1.re * z2.re) - (z1.im * z2.im);
126
  result.im := (z1.re * z2.im) + (z1.im * z2.re);
127
 
128
  RETURN result
129
END CMul;
130
 
131
(* Умножение с REAL.
132
   multiplication : z := z1 * r1 *)
133
PROCEDURE CMul_r (z1 : complex; r1 : REAL): complex;
134
BEGIN
135
  result.re := z1.re * r1;
136
  result.im := z1.im * r1;
137
 
138
  RETURN result
139
END CMul_r;
140
 
141
(* Умножение с INTEGER.
142
   multiplication : z := z1 * i1 *)
143
PROCEDURE CMul_i (z1 : complex; i1 : INTEGER): complex;
144
BEGIN
145
  result.re := z1.re * FLT(i1);
146
  result.im := z1.im * FLT(i1);
147
 
148
  RETURN result
149
END CMul_i;
150
 
151
(* Деление.
152
   division : z := znum / zden *)
153
PROCEDURE CDiv (z1, z2 : complex): complex;
154
    (* The following algorithm is used to properly handle
155
      denominator overflow:
156
 
157
                 |  a + b(d/c)   c - a(d/c)
158
                 |  ---------- + ---------- I     if |d| < |c|
159
      a + b I    |  c + d(d/c)   a + d(d/c)
160
      -------  = |
161
      c + d I    |  b + a(c/d)   -a+ b(c/d)
162
                 |  ---------- + ---------- I     if |d| >= |c|
163
                 |  d + c(c/d)   d + c(c/d)
164
    *)
165
VAR
166
  tmp, denom : REAL;
167
BEGIN
168
   IF ( ABS(z2.re) > ABS(z2.im) ) THEN
169
     tmp := z2.im / z2.re;
170
     denom := z2.re + z2.im * tmp;
171
     result.re := (z1.re + z1.im * tmp) / denom;
172
     result.im := (z1.im - z1.re * tmp) / denom;
173
   ELSE
174
     tmp := z2.re / z2.im;
175
     denom := z2.im + z2.re * tmp;
176
     result.re := (z1.im + z1.re * tmp) / denom;
177
     result.im := (-z1.re + z1.im * tmp) / denom;
178
   END;
179
 
180
   RETURN result
181
END CDiv;
182
 
183
(* Деление на REAL.
184
   division : z := znum / r1 *)
185
PROCEDURE CDiv_r* (z1 : complex; r1 : REAL): complex;
186
BEGIN
187
  result.re := z1.re / r1;
188
  result.im := z1.im / r1;
189
 
190
  RETURN result
191
END CDiv_r;
192
 
193
(* Деление на INTEGER.
194
   division : z := znum / i1 *)
195
PROCEDURE CDiv_i* (z1 : complex; i1 : INTEGER): complex;
196
BEGIN
197
  result.re := z1.re / FLT(i1);
198
  result.im := z1.im / FLT(i1);
199
 
200
  RETURN result
201
END CDiv_i;
202
 
203
(* fonctions elementaires *)
204
 
205
(* Вывод на экран.
206
   out complex number *)
207
PROCEDURE CPrint* (z: complex; width: INTEGER);
208
BEGIN
209
  Out.Real(z.re, width);
210
  IF z.im>=0.0 THEN
211
    Out.String("+");
212
  END;
213
  Out.Real(z.im, width);
214
  Out.String("i");
215
END CPrint;
216
 
217
PROCEDURE CPrintLn* (z: complex; width: INTEGER);
218
BEGIN
219
  CPrint(z, width);
220
  Out.Ln;
221
END CPrintLn;
222
 
223
(* Вывод на экран с фиксированным кол-вом знаков
224
   после запятой (p) *)
225
PROCEDURE CPrintFix* (z: complex; width, p: INTEGER);
226
BEGIN
227
  Out.FixReal(z.re, width, p);
228
  IF z.im>=0.0 THEN
229
    Out.String("+");
230
  END;
231
  Out.FixReal(z.im, width, p);
232
  Out.String("i");
233
END CPrintFix;
234
 
235
PROCEDURE CPrintFixLn* (z: complex; width, p: INTEGER);
236
BEGIN
237
  CPrintFix(z, width, p);
238
  Out.Ln;
239
END CPrintFixLn;
240
 
241
(* Модуль числа.
242
   module : r = |z| *)
243
PROCEDURE CMod* (z1 : complex): REAL;
244
BEGIN
245
  RETURN Math.sqrt((z1.re * z1.re) + (z1.im * z1.im))
246
END CMod;
247
 
248
(* Квадрат числа.
249
   square : r := z*z *)
250
PROCEDURE CSqr* (z1: complex): complex;
251
BEGIN
252
  result.re := z1.re * z1.re - z1.im * z1.im;
253
  result.im := 2.0 * z1.re * z1.im;
254
 
255
  RETURN result
256
END CSqr;
257
 
258
(* Квадратный корень числа.
259
   square root : r := sqrt(z) *)
260
PROCEDURE CSqrt* (z1: complex): complex;
261
VAR
262
  root, q: REAL;
263
BEGIN
264
  IF (z1.re#0.0) OR (z1.im#0.0) THEN
265
    root := Math.sqrt(0.5 * (ABS(z1.re) + CMod(z1)));
266
    q := z1.im / (2.0 * root);
267
    IF z1.re >= 0.0 THEN
268
      result.re := root;
269
      result.im := q;
270
    ELSE
271
      IF z1.im < 0.0 THEN
272
        result.re := - q;
273
        result.im := - root
274
      ELSE
275
        result.re :=  q;
276
        result.im :=  root
277
      END
278
    END
279
  ELSE
280
    result := z1;
281
  END;
282
 
283
  RETURN result
284
END CSqrt;
285
 
286
(* Экспонента.
287
   exponantial : r := exp(z) *)
288
(* exp(x + iy) = exp(x).exp(iy) = exp(x).[cos(y) + i sin(y)] *)
289
PROCEDURE CExp* (z: complex): complex;
290
VAR
291
  expz : REAL;
292
BEGIN
293
  expz := Math.exp(z.re);
294
  result.re := expz * Math.cos(z.im);
295
  result.im := expz * Math.sin(z.im);
296
 
297
  RETURN result
298
END CExp;
299
 
300
(* Натуральный логарифм.
301
   natural logarithm : r := ln(z) *)
302
(* ln( p exp(i0)) = ln(p) + i0 + 2kpi *)
303
PROCEDURE CLn* (z: complex): complex;
304
BEGIN
305
  result.re := Math.ln(CMod(z));
306
  result.im := Math.arctan2(z.im, z.re);
307
 
308
  RETURN result
309
END CLn;
310
 
311
(* Число в степени.
312
   exp : z := z1^z2 *)
313
PROCEDURE CPower* (z1, z2 : complex): complex;
314
VAR
315
  a: complex;
316
BEGIN
317
   a:=CLn(z1);
318
   a:=CMul(z2, a);
319
   result:=CExp(a);
320
 
321
   RETURN result
322
END CPower;
323
 
324
(* Число в степени REAL.
325
   multiplication : z := z1^r *)
326
PROCEDURE CPower_r* (z1: complex; r: REAL): complex;
327
VAR
328
  a: complex;
329
BEGIN
330
  a:=CLn(z1);
331
  a:=CMul_r(a, r);
332
  result:=CExp(a);
333
 
334
  RETURN result
335
END CPower_r;
336
 
337
(* Обратное число.
338
   inverse : r := 1 / z *)
339
PROCEDURE CInv* (z: complex): complex;
340
VAR
341
  denom : REAL;
342
BEGIN
343
  denom := (z.re * z.re) + (z.im * z.im);
344
  (* generates a fpu exception if denom=0 as for reals *)
345
  result.re:=z.re/denom;
346
  result.im:=-z.im/denom;
347
 
348
  RETURN result
349
END CInv;
350
 
351
(* direct trigonometric functions *)
352
 
353
(* Косинус.
354
   complex cosinus *)
355
(* cos(x+iy) = cos(x).cos(iy) - sin(x).sin(iy) *)
356
(* cos(ix) = cosh(x) et sin(ix) = i.sinh(x) *)
357
PROCEDURE CCos* (z: complex): complex;
358
BEGIN
359
  result.re := Math.cos(z.re) * Math.cosh(z.im);
360
  result.im := - Math.sin(z.re) * Math.sinh(z.im);
361
 
362
  RETURN result
363
END CCos;
364
 
365
(* Синус.
366
   sinus complex *)
367
(* sin(x+iy) = sin(x).cos(iy) + cos(x).sin(iy) *)
368
(* cos(ix) = cosh(x) et sin(ix) = i.sinh(x) *)
369
PROCEDURE CSin (z: complex): complex;
370
BEGIN
371
  result.re := Math.sin(z.re) * Math.cosh(z.im);
372
  result.im := Math.cos(z.re) * Math.sinh(z.im);
373
 
374
  RETURN result
375
END CSin;
376
 
377
(* Тангенс.
378
   tangente *)
379
PROCEDURE CTg* (z: complex): complex;
380
VAR
381
  temp1, temp2: complex;
382
BEGIN
383
  temp1:=CSin(z);
384
  temp2:=CCos(z);
385
  result:=CDiv(temp1, temp2);
386
 
387
  RETURN result
388
END CTg;
389
 
390
(* inverse complex hyperbolic functions *)
391
 
392
(* Гиперболический арккосинус.
393
   hyberbolic arg cosinus *)
394
(*                          _________  *)
395
(* argch(z) = -/+ ln(z + i.V 1 - z.z)  *)
396
PROCEDURE CArcCosh* (z : complex): complex;
397
BEGIN
398
  result:=CNeg(CLn(CAdd(z, CMul(i, CSqrt(CSub_r2(1.0, CMul(z, z)))))));
399
 
400
  RETURN result
401
END CArcCosh;
402
 
403
(* Гиперболический арксинус.
404
   hyperbolic arc sinus       *)
405
(*                    ________  *)
406
(* argsh(z) = ln(z + V 1 + z.z) *)
407
PROCEDURE CArcSinh* (z : complex): complex;
408
BEGIN
409
  result:=CLn(CAdd(z, CSqrt(CAdd_r(CMul(z, z), 1.0))));
410
 
411
  RETURN result
412
END CArcSinh;
413
 
414
(* Гиперболический арктангенс.
415
   hyperbolic arc tangent *)
416
(* argth(z) = 1/2 ln((z + 1) / (1 - z)) *)
417
PROCEDURE CArcTgh (z : complex): complex;
418
BEGIN
419
  result:=CDiv_r(CLn(CDiv(CAdd_r(z, 1.0), CSub_r2(1.0, z))), 2.0);
420
 
421
  RETURN result
422
END CArcTgh;
423
 
424
(* trigonometriques inverses *)
425
 
426
(* Арккосинус.
427
   arc cosinus complex *)
428
(* arccos(z) = -i.argch(z) *)
429
PROCEDURE CArcCos* (z: complex): complex;
430
BEGIN
431
  result := CNeg(CMul(i, CArcCosh(z)));
432
 
433
  RETURN result
434
END CArcCos;
435
 
436
(* Арксинус.
437
   arc sinus complex *)
438
(* arcsin(z) = -i.argsh(i.z) *)
439
PROCEDURE CArcSin* (z : complex): complex;
440
BEGIN
441
  result := CNeg(CMul(i, CArcSinh(z)));
442
 
443
  RETURN result
444
END CArcSin;
445
 
446
(* Арктангенс.
447
   arc tangente complex *)
448
(* arctg(z) = -i.argth(i.z) *)
449
PROCEDURE CArcTg* (z : complex): complex;
450
BEGIN
451
  result := CNeg(CMul(i, CArcTgh(CMul(i, z))));
452
 
453
  RETURN result
454
END CArcTg;
455
 
456
BEGIN
457
 
458
  result:=CInit(0.0, 0.0);
459
  i :=CInit(0.0, 1.0);
460
  _0:=CInit(0.0, 0.0);
461
 
462
END CMath.