PDA

View Full Version : Rust - а на фиг он нужен ваще ? :)



crazy-mike
06-11-2019, 03:04 PM
:111: :111: :111:
:111: :111:
:111:

поддержки комплексных числе по умолчанию там вообще нет.
Для "embedded" вообще линкуется с какой-то хренью для gcc.
:111:
Ни scientific ни biz ни sys ! :111:
Если только для написания плагинов под Firefox - слишком длинное ведь. Намного проще собственно JavaScript компилировать.

crazy-mike
06-27-2019, 10:16 AM
ну типа crash test:

берём откуда-нибудь вменяемо-короткую реализвацию алгоритма быстрого преобразования Фурье ( FFT ) - у меня что-то на VB.NET нашлось. Ну нашлось - так нашлось. Попробуем из него сделать что-то исполняемое с тестовыми данными и запустить.



Imports System

Module Program

' https://soltau.ru/index.php/themes/dev/item/500-diskretnoe-preobrazovanie-fure-na-vb-net

Class ComplexNumber
Public Real As Double = 0
Public Imaginary As Double = 0
Public Sub New()
Real = 0
Imaginary = 0
End Sub
Public Sub New(ByVal r As Double, Optional ByVal im As Double = 0)
Real = r
Imaginary = im
End Sub
Public Overrides Function ToString() As String
Dim z as String
z = "+"
If Imaginary < 0.0 Then
z = ""
End If
Return (Real.ToString() & z & Imaginary.ToString() & "i")
End Function
End Class

Function FFT(ByVal signal As ComplexNumber()) As ComplexNumber()
Dim order As Integer = signal.Length 'порядок ДПФ
Dim spectrumLen As Integer = order \ 2
Dim j As Integer = spectrumLen
'Бит-реверсная сортировка:
For i As Integer = 1 To order - 2
If (i < j) Then
Dim tmpRe As Double = signal(j).Real
Dim tmpIm As Double = signal(j).Imaginary
signal(j).Real = signal(i).Real
signal(j).Imaginary = signal(i).Imaginary
signal(i).Real = tmpRe
signal(i).Imaginary = tmpIm
End If
Dim k As Integer = spectrumLen
Do Until (k > j)
j -= k
k \= 2
Loop
j += k
Next
'Цикл по уровням разложения:
For level As Integer = 1 To CInt(Math.Log(order) / Math.Log(2))
Dim lvl As Integer = CInt(2 ^ level)
Dim lvl2 As Integer = lvl \ 2
Dim tmp As Double = Math.PI / lvl2
Dim sr As Double = Math.Cos(tmp)
Dim si As Double = -Math.Sin(tmp)

Dim tr As Double = 0
Dim ur As Double = 1
Dim ui As Double = 0
For jj As Integer = 1 To lvl2 'Цикл по спектрам внутри уровня
For i As Integer = (jj - 1) To (order - 1) Step lvl 'Цикл по отдельным "бабочкам"
Dim ip As Integer = i + lvl2
tr = signal(ip).Real * ur - signal(ip).Imaginary * ui 'Операция "бабочка"
Dim ti As Double = signal(ip).Real * ui + signal(ip).Imaginary * ur
signal(ip).Real = signal(i).Real - tr
signal(ip).Imaginary = signal(i).Imaginary - ti
signal(i).Real = signal(i).Real + tr
signal(i).Imaginary = signal(i).Imaginary + ti
Next
tr = ur
ur = tr * sr - ui * si
ui = tr * si + ui * sr
Next
Next
'Заполняем массив комплексных чисел, обработанных БПФ:
Dim spectrum(order - 1) As ComplexNumber
For i As Integer = 0 To order - 1
With signal(i)
spectrum(i) = New ComplexNumber(.Real, .Imaginary)
End With
Next
Return spectrum
End Function

Sub Main
Dim JJJ as Integer = CInt(Math.Log(8) / Math.Log(2))
Console.WriteLine("JJJ={0}",JJJ)
Dim A As ComplexNumber() = New ComplexNumber() {
New ComplexNumber(0.1,0.0),New ComplexNumber(0.2,0.0),
New ComplexNumber(0.3,0.0),New ComplexNumber(0.4,0.0),New ComplexNumber(0.5,0.0),
New ComplexNumber(0.6,0.0),New ComplexNumber(0.7,0.0),New ComplexNumber(0.8,0.0)
}
Dim B As ComplexNumber() = FFT(A)
For i As Integer = 0 To B.Length-1
Console.WriteLine("{0}",B(i))
Next
End Sub
End Module

crazy-mike
06-27-2019, 10:19 AM
Типа запустилось - вопрос правильно ли работает.
Проверим эту хрень при помощи numpy на Python3:



#!/usr/bin/python3
#
#
import numpy as np
#
b=np.array([0.1+0j,0.2+0j,0.3+0j,0.4+0j,0.5+0j,0.6+0j,0.7+0j,0 .8+0j]);
a=np.fft.fft(b)
np.set_printoptions(threshold=np.nan)
print(a)
print("ok")
#


убедились , что на VB.NET всё как бы правильно. Ну а теперь можно на C и потом на rust.

crazy-mike
06-27-2019, 10:22 AM
На gcc всё чуточку радикальнее:


/*
https://soltau.ru/index.php/themes/dev/item/500-diskretnoe-preobrazovanie-fure-na-vb-net

быстрое дискретное преобразование Фурье - портировано с vb.net

*/

#include <stdio.h>
#include <complex.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>

static int order=0;

complex* FFT(complex* xsignal,int xsignal_length) {
order=xsignal_length;
int spectrumLen=order/2;
complex* spectrum=(complex*)malloc(sizeof(complex)*order);
int i;
for(i=0; i<order; i++) spectrum[i]=xsignal[i];
/* Бит-реверсная сортировка */
i=1;
int j=spectrumLen;
while(i<= (order-2)) {
if(i<j) {
complex tmp=spectrum[j];
spectrum[j]=spectrum[i];
spectrum[i]=tmp;
};
int k=spectrumLen;
for(;;) {
if(k>j) break;
j-=k;
k/=2;
};
j+=k;
i++;
};
/* Цикл по уровням разложения */
for(int level=1; level<=(int)floor(log((double)order)/log(2)); level++ ) {
int lvl = (int)floor(pow((double)2,(double)level));
int lvl2 = lvl / 2;
double tmp = M_PI / (double) lvl2;
double sr = cos(tmp);
double si = -sin(tmp);
double tr = 0.0;
double ur = 1.0;
double ui = 0.0;
/* Цикл по спектрам внутри уровня */
for(int jj = 1; jj<= lvl2; jj++) {
/* Цикл по отдельным бабочкам */
for(i = (jj - 1); i<=(order - 1); i+=lvl) {
int ip=i+lvl2;
tr=crealf(spectrum[ip])*ur-cimagf(spectrum[ip])*ui; /* Операция бабочка */
double ti=crealf(spectrum[ip])*ui + cimagf(spectrum[ip])*ur;
spectrum[ip]=(crealf(spectrum[i])-tr)+(cimagf(spectrum[i])-ti)*I;
spectrum[i]=(crealf(spectrum[i])+tr)+(cimagf(spectrum[i])+ti)*I;
};
tr = ur;
ur = tr * sr - ui * si;
ui = tr * si + ui * sr;
};
};
/* Заполняем массив комплексных чисел, обработанных БПФ */

return spectrum;
}

static complex aa[]={ 0.1+0i, 0.2+0i, 0.3+0i, 0.4+0i, 0.5+0.i, 0.6+0i, 0.7+0i, 0.8+0i };

int main(int argc,char** argv) {
printf("\n типа быстрое преобразование Фурье ( дискретное ) a la Кули-Таки\n");
complex* r=FFT(aa,8);
for(int i=0; i<8; i++) {
complex d=r[i];
double imf=cimagf(d);
if(imf<0) {
printf("%g%gi\n",crealf(d),imf);
} else printf("%g+%gi\n",crealf(d),imf);
};
free(r);
return 0;
}


результат совпал с VB.NET и Python3. Ну а теперь можно и на rust. И начинается цирк! :111:

crazy-mike
06-27-2019, 10:27 AM
struct Complex {
re :f64,im :f64
}

fn mypi() -> f64 {
let d :f64=(0 as f64).acos();
return d+d;
}


fn myfft(s :&[Complex]) -> [Complex;8] {
let mut r :[Complex; 8] = [
Complex { re :0.0,im :0.0 },Complex { re :0.0,im :0.0 },
Complex { re :0.0,im :0.0 },Complex { re :0.0,im :0.0 },
Complex { re :0.0,im :0.0 },Complex { re :0.0,im :0.0 },
Complex { re :0.0,im :0.0 },Complex { re :0.0,im :0.0 }
];
let mut jx :usize=0;

while jx<s.len() {
r[jx].re=s[jx].re;
r[jx].im=s[jx].im;
jx=jx+1;
};
let order :usize=8;
let spectrum_len :usize=order/2;
/* Бит-реверсная сортировка */
let mut j:usize=spectrum_len;
let mut i:usize=1;
while i <=(order-2) {
if i<j {
let tmp_re:f64=r[j].re;
let tmp_im:f64=r[j].im;
r[j].re=r[i].re; r[j].im=r[i].im;
r[i].re=tmp_re; r[i].im=tmp_im;
};
let mut k :usize=spectrum_len;
loop {
if k>j { break; };
j=j-k;
k=k/2;
};
j=j+k;
i=i+1;
};

/* Цикл по уровням разложения */
let ibreak :usize=((order as f64).ln()/(2.0 as f64).ln()).trunc() as usize;
let mut level:usize=1;
while level<=ibreak {
let lvl:usize = ((2.0 as f64).powf(level as f64)).trunc() as usize;
let lvl2:usize = lvl / 2;
let tmp:f64 = mypi() / (lvl2 as f64);
let sr:f64 = tmp.cos();
let si:f64 = -tmp.sin();
let mut ur:f64 = 1.0;
let mut ui:f64 = 0.0;
/* Цикл по спектрам внутри уровня */
let mut jj:usize=1;
while jj<=lvl2 {
/* Цикл по отдельным бабочкам */
let mut i:usize = jj-1;
while i<=(order-1) {
let ip:usize=i+lvl2;
let tr:f64=r[ip].re*ur-r[ip].im*ui; /* Операция бабочка */
let ti:f64=r[ip].re*ui+r[ip].im*ur;
r[ip].re=r[i].re-tr;
r[ip].im=r[i].im-ti;
r[i].re=r[i].re+tr;
r[i].im=r[i].im+ti;
//
i=i+lvl;
};
let tr:f64 = ur;
ur = tr * sr - ui * si;
ui = tr * si + ui * sr;
jj=jj+1;
};
level=level+1;
};
return r;
}

fn main() {
println!("FFT быстрое преобразование Фурье (алгоритм Кули-Таки)");
let a :[Complex; 8 ]=[
Complex { re :0.1,im :0.0 },Complex { re :0.2,im :0.0 },Complex { re :0.3,im :0.0 },
Complex { re :0.4,im :0.0 },
Complex { re :0.5,im :0.0 },Complex { re :0.6,im :0.0 },Complex { re :0.7,im :0.0 },
Complex { re :0.8,im :0.0 }
];
let b :[Complex;8]=myfft(&a);
let mut i:usize=0;
while i<b.len() {
println!("{ } { }",&b[i].re,&b[i].im);
i=i+1;
};
}


Вот так оно даже правильно работает , но чего это стоило! ( жаркий рабочий день без кондиционера - окно открыто и в окно время от времени залетают осы )

crazy-mike
06-27-2019, 10:35 AM
у этих "редисок" в Rust нужно в описание переменной добавлять модификатор mut только для того , чтобы после начального присваивания переменная могла изменять своё значение.
Ну присваивание структур по умолчанию не работает - если для структуры нет имплементации операции copy. Ну массив можно создать только известной во время компиляции длины...

Но мы всё это have had overcame ... :111:

Хуже было совсем другое - инструкция for , которая внешне была похожа на соответствующую инструкцию VB.NET - но работала не так. Пришлось вместо for всё сделать через while - и только тогда резульат вычисления совпал с "правильным".

А "достало" больше всего - запись арифметических выражений:


let d :f64=(0 as f64).acos();