Skip to content

Commit 63204ac

Browse files
complex
1 parent ce7847f commit 63204ac

File tree

1 file changed

+370
-0
lines changed

1 file changed

+370
-0
lines changed
+370
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,370 @@
1+
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
2+
// © RicardoSantos
3+
4+
//@version=4
5+
study(title='Function: Complex Numbers')
6+
7+
//| Complex numbers prototype: {
8+
//|----------------------------------------------------------------------------||
9+
//|----------------------------------------------------------------------------||
10+
//|----------------------------------------------------------------------------||
11+
//| @description:
12+
//| A set of utility functions to handle complex numbers.
13+
//| @references:
14+
//| https://en.wikipedia.org/wiki/Complex_number
15+
//| js: https://rosettacode.org/wiki/Fast_Fourier_transform
16+
//| https://github.com/trekhleb/javascript-algorithms/blob/477f30b0bdac6024874d2976de1eca7afe0176dd/src/algorithms/math/complex-number/ComplexNumber.js#L3
17+
//| https://github.com/infusion/Complex.js/
18+
//| http://jmvidal.cse.sc.edu/talks/javascript/complexnumbersexample.html
19+
//|----------------------------------------------------------------------------||
20+
//|----------------------------------------------------------------------------||
21+
//|----------------------------------------------------------------------------||
22+
23+
f_complex_new(_real, _imaginary)=>
24+
//| @description:
25+
//| Creates a prototype array to handle complex numbers.
26+
//| @parameters:
27+
//| _real: real value of the complex number.
28+
//| _imaginary: imaginary number of the complex number. optional(use float(na) to not define value)
29+
float[] _complex = array.new_float(size=2, initial_value=0.0)
30+
array.set(id=_complex, index=0, value=_real)
31+
array.set(id=_complex, index=1, value=na(_imaginary)?0.0:_imaginary)
32+
//| @return:
33+
//| _complex: pseudo complex number in the form of a array [real, imaginary].
34+
_complex
35+
36+
f_complex_real_get(_a)=>
37+
//| @description:
38+
//| Get the real part of complex number _a.
39+
//| @parameters:
40+
//| _a: pseudo complex number in the form of a array [real, imaginary].
41+
_real = array.get(id=_a, index=0)
42+
//| @return:
43+
//| _real: Real part of the complex number _a.
44+
_real
45+
46+
f_complex_imaginary_get(_a)=>
47+
//| @description:
48+
//| Get the imaginary part of complex number _a.
49+
//| @parameters:
50+
//| _a: pseudo complex number in the form of a array [real, imaginary].
51+
_imaginary = array.get(id=_a, index=1)
52+
//| @return:
53+
//| _imaginary: Imaginary part of the complex number _a.
54+
_imaginary
55+
56+
f_complex_add(_a, _b)=>
57+
//| @description:
58+
//| Adds complex number _b to _a, in the form:
59+
//| [_a.real + _b.real, _a.imaginary + _b.imaginary].
60+
//| @parameters:
61+
//| _a: pseudo complex number in the form of a array [real, imaginary].
62+
//| _b: pseudo complex number in the form of a array [real, imaginary].
63+
float[] _complex = array.new_float(size=2, initial_value=0.0)
64+
array.set(id=_complex, index=0, value=f_complex_real_get(_a) + f_complex_real_get(_b))
65+
array.set(id=_complex, index=1, value=f_complex_imaginary_get(_a) + f_complex_imaginary_get(_b))
66+
//| @return:
67+
//| _complex: pseudo complex number in the form of a array [real, imaginary]
68+
_complex
69+
70+
f_complex_subtract(_a, _b)=>
71+
//| @description:
72+
//| Subtract complex number _b from _a, in the form:
73+
//| [_a.real - _b.real, _a.imaginary - _b.imaginary].
74+
//| @parameters:
75+
//| _a: pseudo complex number in the form of a array [real, imaginary].
76+
//| _b: pseudo complex number in the form of a array [real, imaginary].
77+
float[] _complex = array.new_float(size=2, initial_value=0.0)
78+
array.set(id=_complex, index=0, value=f_complex_real_get(_a) - f_complex_real_get(_b))
79+
array.set(id=_complex, index=1, value=f_complex_imaginary_get(_a) - f_complex_imaginary_get(_b))
80+
//| @return:
81+
//| _complex: pseudo complex number in the form of a array [real, imaginary]
82+
_complex
83+
84+
f_complex_multiply(_a, _b)=>
85+
//| @description:
86+
//| Multiply complex number _a with _b, in the form:
87+
//| [(_a.real * _b.real) - (_a.imaginary * _b.imaginary), (_a.real * _b.imaginary) + (_a.imaginary * _b.real)]
88+
//| @parameters:
89+
//| _a: pseudo complex number in the form of a array [real, imaginary].
90+
//| _b: pseudo complex number in the form of a array [real, imaginary].
91+
float[] _complex = array.new_float(size=2, initial_value=0.0)
92+
float _a_real = f_complex_real_get(_a)
93+
float _a_imaginary = f_complex_imaginary_get(_a)
94+
float _b_real = f_complex_real_get(_b)
95+
float _b_imaginary = f_complex_imaginary_get(_b)
96+
float _r = _a_real * _b_real - _a_imaginary * _b_imaginary
97+
float _i = _a_real * _b_imaginary + _a_imaginary * _b_real
98+
array.set(id=_complex, index=0, value=_r)
99+
array.set(id=_complex, index=1, value=_i)
100+
//| @return:
101+
//| _complex: pseudo complex number in the form of a array [real, imaginary]
102+
_complex
103+
104+
f_complex_negative(_a)=>
105+
//| @description:
106+
//| Negative of complex number _a, in the form: [-_a.real, -_a.imaginary]
107+
//| @parameters:
108+
//| _a: pseudo complex number in the form of a array [real, imaginary].
109+
float[] _complex = array.new_float(size=2, initial_value=0.0)
110+
float _a_real = f_complex_real_get(_a)
111+
float _a_imaginary = f_complex_imaginary_get(_a)
112+
array.set(id=_complex, index=0, value=-_a_real)
113+
array.set(id=_complex, index=1, value=-_a_imaginary)
114+
//| @return:
115+
//| _complex: pseudo complex number in the form of a array [real, imaginary]
116+
_complex
117+
118+
f_complex_cexp(_a)=>
119+
//| @description:
120+
//| Exponential of complex number _a, in the form:
121+
//| reference: https://en.cppreference.com/w/c/numeric/complex/cexp
122+
//| http://cboard.cprogramming.com/c-programming/89116-how-implement-complex-exponential-functions-c.html#post637921
123+
//| @parameters:
124+
//| _a: pseudo complex number in the form of a array [real, imaginary].
125+
float[] _complex = array.new_float(size=2, initial_value=0.0)
126+
float _a_real = f_complex_real_get(_a)
127+
float _a_imaginary = f_complex_imaginary_get(_a)
128+
var _er = exp(_a_real)
129+
array.set(id=_complex, index=0, value=_er * cos(_a_imaginary))
130+
array.set(id=_complex, index=1, value=_er * sin(_a_imaginary))
131+
//| @return:
132+
//| _complex: pseudo complex number in the form of a array [real, imaginary]
133+
_complex
134+
135+
f_complex_tostring(_a)=>
136+
//| @description:
137+
//| Converts complex number _a to a string format, in the form: "a+bi"
138+
//| @parameters:
139+
//| _a: pseudo complex number in the form of a array [real, imaginary].
140+
float[] _complex = array.new_float(size=2, initial_value=0.0)
141+
float _a_real = f_complex_real_get(_a)
142+
float _a_imaginary = f_complex_imaginary_get(_a)
143+
string _str = ''
144+
if na(_a_real)
145+
_str := tostring(_a_imaginary) + 'i'
146+
else if _a_imaginary < 0
147+
_str := tostring(_a_real) + '' + tostring(_a_imaginary) + 'i'
148+
else
149+
_str := tostring(_a_real) + '+' + tostring(_a_imaginary) + 'i'
150+
//| @return:
151+
//| _str: a string int "a+bi" format
152+
_str
153+
154+
f_complex_conjugate(_a)=>
155+
//| @description:
156+
//| Computes the conjugate of complex number _a by reversing the sign of the imaginary part.
157+
//| reference: https://en.cppreference.com/w/c/numeric/complex/conj
158+
//| @parameters:
159+
//| _a: pseudo complex number in the form of a array [real, imaginary].
160+
float _a_real = f_complex_real_get(_a)
161+
float _a_imaginary = f_complex_imaginary_get(_a)
162+
float[] _complex = f_complex_new(_a_real, -1 * _a_imaginary)
163+
//| @return:
164+
//| _complex: pseudo complex number in the form of a array [real, imaginary]
165+
_complex
166+
167+
f_complex_divide(_a, _b)=>
168+
//| @description:
169+
//| Divide complex number _a with _b, in the form:
170+
//| [(_a.real * _b.real) - (_a.imaginary * _b.imaginary), (_a.real * _b.imaginary) + (_a.imaginary * _b.real)]
171+
//| @parameters:
172+
//| _a: pseudo complex number in the form of a array [real, imaginary].
173+
//| _b: pseudo complex number in the form of a array [real, imaginary].
174+
float[] _complex = array.new_float(size=2, initial_value=0.0)
175+
float _b_real = f_complex_real_get(_b)
176+
float _b_imaginary = f_complex_imaginary_get(_b)
177+
// Make sure we're dealing with complex number.
178+
float[] _complexDivider = f_complex_new(_b_real, _b_imaginary)
179+
// Multiply dividend by divider's conjugate.
180+
float[] _finalDivident = f_complex_multiply(_a, f_complex_conjugate(_complexDivider))
181+
// Calculating final divider using formula (a + bi)(a − bi) = a^2 + b^2
182+
float finalDivider = pow(f_complex_real_get(_complexDivider), 2) + pow(f_complex_imaginary_get(_complexDivider), 2)
183+
float _finaldivident_real = f_complex_real_get(_finalDivident)
184+
float _finaldivident_imaginary = f_complex_imaginary_get(_finalDivident)
185+
array.set(id=_complex, index=0, value=_finaldivident_real / finalDivider)
186+
array.set(id=_complex, index=1, value=_finaldivident_imaginary / finalDivider)
187+
//| @return:
188+
//| _complex: pseudo complex number in the form of a array [real, imaginary]
189+
_complex
190+
191+
f_complex_get_radius(_a)=>
192+
//| @description:
193+
//| Radius of _a, in the form: [sqrt(pow(_a))]
194+
//| Return the magnitude of a complex number. This is defined
195+
//| as its distance from the origin (0,0) of the complex plane.
196+
//| @parameters:
197+
//| _a: pseudo complex number in the form of a array [real, imaginary].
198+
float _radius= sqrt(pow(f_complex_real_get(_a), 2) + pow(f_complex_imaginary_get(_a), 2))
199+
//| @return:
200+
//| _radius: float value with radius.
201+
_radius
202+
203+
f_complex_get_phase(_a, _inRadians)=>
204+
//| @description:
205+
//| The phase value of complex number _a.
206+
//| @parameters:
207+
//| _a: pseudo complex number in the form of a array [real, imaginary].
208+
//| _inRadians: boolean value for the type of angle value, (true: radians, false: degrees)
209+
float _pi = 3.14159265359
210+
float _a_real = f_complex_real_get(_a)
211+
float _a_imaginary = f_complex_imaginary_get(_a)
212+
float _phase = atan(abs(_a_imaginary) / abs(_a_real))
213+
214+
if not _inRadians
215+
_phase := _phase * (180 / _pi) // radian to degrees
216+
else
217+
if _a_real < 0 and _a_imaginary > 0
218+
_phase := _pi - nz(_phase)
219+
else if _a_real < 0 and _a_imaginary < 0
220+
_phase := -(_pi - nz(_phase))
221+
else if _a_real > 0 and _a_imaginary < 0
222+
_phase := -nz(_phase)
223+
else if _a_real == 0 and _a_imaginary > 0
224+
_phase := _pi / 2.0
225+
else if _a_real == 0 and _a_imaginary < 0
226+
_phase := -_pi / 2.0
227+
else if _a_real < 0 and _a_imaginary == 0
228+
_phase := _pi
229+
else if _a_real > 0 and _a_imaginary == 0
230+
_phase := 0.0
231+
else if _a_real == 0 and _a_imaginary == 0
232+
// More correctly would be to set 'indeterminate'.
233+
// But just for simplicity reasons let's set zero.
234+
_phase := 0.0
235+
else
236+
na
237+
//| @return:
238+
//| _phase: float value with phase.
239+
_phase
240+
241+
f_complex_get_polar_form(_a, _inRadians)=>
242+
//| @description:
243+
//| The polar form value of complex number _a.
244+
//| @parameters:
245+
//| _a: pseudo complex number in the form of a array [real, imaginary].
246+
//| _inRadians: boolean value for the type of angle value, (true: radians, false: degrees)
247+
float[] _complex = f_complex_new(f_complex_get_radius(_a), f_complex_get_phase(_a, _inRadians))
248+
//| @return:
249+
//| _complex: **pseudo complex number in the form of a array [real, imaginary]
250+
//| ** returns a array [radius, phase]
251+
_complex
252+
253+
f_complex_array_new(_size, _initial_complex)=>
254+
//| @description:
255+
//| Prototype to initialize a array of complex numbers.
256+
//| @parameters:
257+
//| _size: size of the array.
258+
//| _initial_complex: Complex number to be used as default value, in the form of array [real, imaginary].
259+
float _init_real = array.get(id=_initial_complex, index=0)
260+
float _init_imaginary = array.get(id=_initial_complex, index=1)
261+
262+
float[] _complex_array = array.new_float(0)
263+
for _i = 0 to _size-1
264+
array.push(id=_complex_array, value=_init_real)
265+
array.push(id=_complex_array, value=_init_imaginary)
266+
//| @return:
267+
//| _complex_array: pseudo complex Array in the form of a array [0:real, 1:imaginary, 2:real, 3:imaginary,...]
268+
_complex_array
269+
270+
271+
f_complex_array_get(_id, _index)=>
272+
//| @description:
273+
//| Get the complex number in a array, in the form of a array [real, imaginary]
274+
//| @parameters:
275+
//| _id: ID of the array.
276+
//| _index: Index of the complex number.
277+
float[] _complex = array.new_float(size=2, initial_value=0.0)
278+
int _size = round(array.size(id=_id) / 2)
279+
int _index2 = _index * 2
280+
if _index > -1 and _index < _size
281+
array.set(id=_complex, index=0, value=array.get(id=_id, index=_index2))
282+
array.set(id=_complex, index=1, value=array.get(id=_id, index=_index2 + 1))
283+
//| @return:
284+
//| _complex: pseudo complex number in the form of a array [real, imaginary]
285+
_complex
286+
287+
288+
f_complex_array_set(_id, _index, _a)=>
289+
//| @description:
290+
//| Sets the values complex number in a array.
291+
//| @parameters:
292+
//| _id: ID of the array.
293+
//| _index: Index of the complex number.
294+
//| _a: Complex number, in the form: [real, imaginary].
295+
float _a_real = f_complex_real_get(_a)
296+
float _a_imaginary = f_complex_imaginary_get(_a)
297+
int _size = array.size(id=_id)-1
298+
int _index2 = _index * 2
299+
if _index > -1 and _index2 < _size
300+
array.set(id=_id, index=_index2, value=_a_real)
301+
array.set(id=_id, index=_index2 + 1, value=_a_imaginary)
302+
//| @return: Void, updates array _id.
303+
304+
305+
f_complex_array_tostring(_id)=>
306+
//| @description:
307+
//| Reads a array of complex numbers into a string, of the form: "[ [a+bi], ... ]""
308+
//| @parameters:
309+
//| _id: ID of the array.
310+
int _size = round(array.size(id=_id) / 2)
311+
string _str = '[ '
312+
if _size > 0
313+
for _i = 0 to _size-1
314+
_str := _str + '[ ' + f_complex_tostring(f_complex_array_get(_id, _i)) + ' ]'
315+
if _i == _size
316+
_str := _str + ' ]'
317+
else
318+
_str := _str + ', '
319+
//| @return:
320+
//| _str: Translated complex array into string.
321+
_str
322+
323+
//|----------------------------------------------------------------------------||
324+
//|--------------------------------}-------------------------------------------||
325+
326+
327+
328+
//|----------------------------------------------------------------------------||
329+
//|----------------------------------------------------------------------------||
330+
//|----------------------------------------------------------------------------||
331+
332+
333+
334+
if barstate.ishistory[1] and barstate.isrealtime
335+
float[] a = f_complex_new(0.10, -0.25)
336+
float[] b = f_complex_new(0.66, float(na))
337+
float[] c = f_complex_add(a, b)
338+
float[] d = f_complex_subtract(c, b)
339+
float[] e = f_complex_multiply(a, d)
340+
float[] f = f_complex_cexp(e)
341+
float[] g = f_complex_conjugate(f)
342+
float[] h = f_complex_divide(f, g)
343+
float i = f_complex_get_radius(h)
344+
float j = f_complex_get_phase(h, true)
345+
float[] k = f_complex_get_polar_form(h, true)
346+
float[] L = f_complex_array_new(4, f_complex_new(0, 0))
347+
f_complex_array_set(L, 0, a)
348+
f_complex_array_set(L, 1, b)
349+
f_complex_array_set(L, 2, c)
350+
f_complex_array_set(L, 3, d)
351+
float[] m = f_complex_array_get(L, 2)
352+
float[] n = f_complex_negative(m)
353+
_text = ''
354+
_text := _text + 'a: ' + f_complex_tostring(a) + '\n'
355+
_text := _text + 'b: ' + f_complex_tostring(b) + '\n'
356+
_text := _text + 'c: ' + f_complex_tostring(c) + '\n'
357+
_text := _text + 'd: ' + f_complex_tostring(d) + '\n'
358+
_text := _text + 'e: ' + f_complex_tostring(e) + '\n'
359+
_text := _text + 'f: ' + f_complex_tostring(f) + '\n'
360+
_text := _text + 'g: ' + f_complex_tostring(g) + '\n'
361+
_text := _text + 'h: ' + f_complex_tostring(h) + '\n'
362+
_text := _text + 'i: ' + tostring(i) + '\n'
363+
_text := _text + 'j: ' + tostring(j) + '\n'
364+
_text := _text + 'k: ' + tostring(k) + '\n'
365+
_text := _text + 'L: ' + f_complex_array_tostring(L) + '\n'
366+
_text := _text + 'm: ' + f_complex_tostring(m) + '\n'
367+
_text := _text + 'n: ' + f_complex_tostring(n) + '\n'
368+
label.new(x=bar_index, y=0.0, text=_text, textalign=text.align_left)
369+
370+

0 commit comments

Comments
 (0)