2D-algebra

Seuraa 
Viestejä45973
Liittynyt3.9.2015

Aika paljon on yksinpuhelua noitten algebroitten suhteen. Liekö sitten niin, että kouluissa ei riittävästi painoteta, että C++ istuu kaikkein parhaiten matemaattisten struktuurien kuvaamiseen, ja varsinkin sovelletun matematiikan laskemiseen.

Lyhyesti C++:ssa on kysymys operaattoreiden ylikuormittamisesta. Toisin sanoen esimerkiksi kertolaskulle ja jakolaskulle voi määritellä uuden merkityksen, ja C++ ohjaa automaattisesti substanssit ko. ylikuormitetuille operaatioille.

real2d:llä C++ ymppää real2d-olion operaattoreita. complex2d:llä puolestaan C++ osaa automaattisesti käyttää sen substanssin operaattoreita. Minun mielestä C++ ja sovellettu matematiikka tekivät hyvät naimakaupat noitten operaattoreiden ylikuormitusmahdollisuudessa, koska jos saman mössön vääntäisi perinteisellä C:llä, se olisi yhtä vaikealukuista kuin assembler.

Kirjoitan tuota 2D-algebraa puhtaaksi, mutta koska joudun tekemään melkein puolet päivästä työtä, jaan sen pieneen dokumentointiin per päivä. Yksinpuhelua on siis paljon luvassa, jos vanhat merkit paikkansa pitävät. Samapa tuo. Mutta vastaankin mielelläni kysymyksiin, jos niitä vain joku viitsii esittää. Optimoin/tutkin vielä joiltakin osin tuon 2D-kompleksiluvun ominaisuuksia, mutta olio sisältää kuitenkin tärkeimmät perusoperaatiot.

Lisään funktioita tuonnempana lisää. complex2d-oliossa on kuitenkin mukavaa se, että vain tuo ja vain tuo kertolasku kantavektoreiden keralla johtaa ristiriidattomuuteen. Oliossa pätee siis kaikki algebran aksioomat.

Sitten tuon dokumentoinnin jossain loppuvaiheessa mukaan joitakin sovelletun matematiikan esimerkkejä, miten vaikkapa polynomiapproksimaatiot luonnistuvat 2D-algebrassa samalla suoraviivaisuudella, kuin mihin on tavallisessa koulualgebrassa totuttu. Tämän jälkeen on ehkä pienempi kuilu tarkastella 2D-algebran moniulotteista takaisinkytkentää.

Koodi muuten kääntyy takuulla jokaisessa C++ kääntäjässä ongelmitta, ja lyhyellä main esimerkillä pääsee nopeasti kokeilemaan omia laskutuloksia.

[code:34e6pg7i]#include
#include

class real2d
{
public:

double e[4];
real2d(void);

real2d(int);
real2d(int, int);
real2d(int, int, int, int);

real2d(double);
real2d(double, double);

friend int ifpos(real2d);
friend double abs(real2d);
friend void print(real2d);

friend real2d sqrt(real2d);
friend real2d reduse(real2d);
friend real2d operator-(real2d);

friend real2d operator+(real2d, real2d);
friend real2d operator-(real2d, real2d);

friend real2d operator*(real2d, real2d);
friend real2d operator/(real2d, real2d);

friend real2d operator*(double, real2d);
friend real2d operator/(real2d, double);

friend real2d operator*(real2d, double);
friend real2d operator/(double, real2d);

/* mgn = luvun suuruus */
friend double mgn(real2d);
friend real2d ln(real2d);
friend real2d exp(real2d);
friend real2d sin(real2d);
friend real2d cos(real2d);
friend real2d pow(real2d, int);
friend real2d pow(real2d, double);
friend real2d pow(real2d, real2d);
};

real2d::real2d(double a)
{
e[0]=a; e[1]=0;
e[2]=e[3]=0.00;
}

real2d::real2d(double a, double b)
{
e[0]=a; e[2]=b;
e[1]=e[3]=0.00;
}

real2d::real2d(int a)
{
*this=real2d((double)a);
}

real2d::real2d(int a, int b)
{
*this=real2d((double)a, (double)b);
}

real2d::real2d(int a, int b, int c, int d)
{
e[0]=a; e[1]=b;
e[2]=c; e[3]=d;
}

real2d::real2d(void)
{
*this=real2d((double)0);
}

real2d reduse(real2d a)
{
a.e[0]-=a.e[1];
a.e[2]-=a.e[3];
a.e[1]=a.e[3]=0;
return (real2d)a;
}

double abs(real2d a)
{
double x = a.e[0]-a.e[1];
double y = a.e[2]-a.e[3];
return (double)fabs(x-y);
}

double mgn(real2d a)
{
double x=a.e[0]-a.e[1];
double y=a.e[2]-a.e[3];
return fabs(x)+fabs(y);
}

int ifpos(real2d a)
{
double x=a.e[0]-a.e[1];
double y=a.e[2]-a.e[3];

if (x>=0.0)
{
return fabsl(y)<=x? 1: 0;
}
else
{
return 0;
}
}

real2d operator-(real2d a)
{
for (int i=0; i<4; i++)
a.e[i]=-a.e[i];
return reduse(a);
}

real2d operator+(real2d a, real2d b)
{
for (int i=0; i<4; i++)
a.e[i]+=b.e[i];
return reduse(a);
}

real2d operator-(real2d a, real2d b)
{
for (int i=0; i<4; i++)
a.e[i]-=b.e[i];
return reduse(a);
}

real2d operator*(real2d a, real2d b)
{
real2d t(0.0);
for (int i=0; i<4; i++)
for (int j=0; j<4; j++)
t.e[i^j]+=a.e[i]*b.e[j];
return reduse(t);
}

real2d operator/(real2d x, real2d y)
{
double X[4];
double K[4*4+4];

for (int n=0, p=0; n<4; n++)
{
for (int i=0; i<4; i++)
for (int j=0; j<4; j++)
{
if (n == (i^j))
{
K[p]=y.e[j]; ++p;
}
}
K[p]=x.e[n]; ++p;
}

// gsolve ratkaisee lineaarisen yhtälöryhmän
// Gaussin eliminointimenetelmällä...
int gsolve(double*, double*, int);

gsolve(X, K, 4);
double a=X[0]-X[1];
double b=X[2]-X[3];
return real2d(a, b);
}

void swapRows(double *a, double *b, int n)
{
for (int i=0; i
{
double tmp=a[i];
a[i]=b[i];
b[i]=tmp;
}
}

////////////////////////////////////////////////
// qsolve palautusarvo: //
// 1 <=> yhtälöryhmälle oli ratkaisu //
// 0 <=> yhtälöryhmälle ei ollut ratkaisua //
////////////////////////////////////////////////
int gsolve(double *X, double *f, int n)
{
double k, J;
double *max, *mux;
int i, j, x, M=(int)n+1;

for (i=0; i
{
max=f+i+i*M;
for (j=i+0x01; j < n; j++)
if (fabs(*(mux=f+i+j*M))>fabs(*max)) max=mux;

if (max!=(mux=f+i+i*M))
swapRows(max, mux, M-i);

if (fabs(J=f[i+i*M])<(double)1e-20)
return 0; /* eipä ole ratkaisuva */

for (j=i+1; j
{
if (f[i+j*M])
{
k=-f[i+j*M]/J;
for (x=i+1; x
f[x+j*M]=f[x+j*M]+k*f[x+i*M];
}
}
}

for (i=n-1; i>=0; i--)
{
k=(double)f[n+i*M];
for (j=n-1; j > i; j--)
k=k-(double)(X[j]*f[j+i*M]);

if (fabs(J=f[i+i*M])<(double)1e-20)
return 0; /* eipä ole ratkaisua */
else X[i]=k/J; /* onpa ratkaisu */
}

return 1;
}

real2d operator*(double k, real2d b)
{
real2d a(k);
return a*b;
}

real2d operator/(real2d a, double k)
{
real2d b(k);
return a/b;
}

real2d operator*(real2d a, double k)
{
real2d b(k);
return a*b;
}

real2d operator/(double k, real2d b)
{
real2d a(k);
return a/b;
}

real2d sqrt(real2d c)
{
if (ifpos(c))
{
real2d k(0.5);
real2d x(1.0);

for (int i=0; i<64; i++)
{
x=k*(x+c/x);
}
return x;
}
else
{
/* virhe, luku ei ole positiivinen */
return real2d(-(double)0xfedca201L);
}
}

void print(real2d a)
{
a = (real2d) reduse(a);
printf("(%0.21f, %0.21f)\n",
(double)a.e[0], (double)a.e[2]);
}

real2d pow(real2d x, int n)
{
if (n)
{
real2d t=x;
int i=n<0? -n: n;
for (--i; i; i--) t=t*x;
return n>0? t: real2d(1.0)/t;
}
else
{
return real2d(1.0);
}
}

real2d ln(real2d c)
{
int n=1;
double t;
real2d fx, dx;
real2d x1, x2;
real2d z(1.0);
real2d x(1.0), xx;
#define MAX 3.14159265e+36

if (!ifpos(c))
{
/* virhe, luku ei ole positiivinen */
return real2d(-(double)0xfedca201L);
}

while (abs(c)>1.001)
{
c=sqrt(c);
n+=n;
}

for (int k=2; k<160; k++)
for (int j=0; j<160; j++)
{
xx=x; t=1.0;
fx=z+x; dx=z;

for (int i=2; i<=k; i++)
{
dx=dx+i*xx/(t*=i);
xx=xx*x; fx=fx+xx/t;
if (mgn(fx)>MAX) break;
}

x1=x;
x=x-(fx-c)/dx;
x2=x;

if (k+1 < 160)
{
if (mgn(x1-x2)<1e-15) break;
}
}

return (double)n*x;
}

real2d exp(real2d x)
{
real2d xx;
double t=1.0;
real2d sum(1.0);

sum=sum+(xx=x);

for (int i=2; i<160; i++)
{
xx = xx*x;
sum=sum+xx/(t*=i);
if (mgn(xx)>MAX) break;
}

return sum;
}

real2d pow(real2d a, real2d x)
{
double t=1.0;
real2d sum(1.000);
real2d y=x*ln(a), xx=y;

sum=sum+xx;

for (int i=2; i<160; i++)
{
xx = xx*y;
sum=sum+xx/(t*=i);
if (mgn(xx)>MAX) break;
}

return sum;
}

real2d pow(real2d x, double ex)
{
return pow(x, real2d(ex));
}

real2d sin(real2d x)
{
double t=1.0;
real2d sum(0.0);
real2d y=x*x, xx=x;

for (int i=1, sg=0; i<160; i+=2, sg++)
{
if (sg&1) sum=sum-xx/t;
else /**/ sum=sum+xx/t;
xx=xx*y; t*=(i+1)*(i+2);
if (mgn(xx)>MAX) break;
}
return sum;
}

real2d cos(real2d x)
{
double t=2.0;
real2d sum(1.0);
real2d y=x*x, xx=y;

for (int i=2, sg=1; i<160; i+=2, sg++)
{
if (sg&1) sum=sum-xx/t;
else /**/ sum=sum+xx/t;
xx=xx*y; t*=(i+1)*(i+2);
if (mgn(xx)>MAX) break;
}
return sum;
}

class complex2d
{
public:

real2d r, i, j, k;

complex2d(void);
complex2d(int);

complex2d(double);
complex2d(real2d);

complex2d(double, double);
complex2d(real2d re, real2d im);
complex2d(real2d, real2d, real2d, real2d);

friend double abs(complex2d);
friend void print(complex2d);
friend complex2d sqrt(complex2d);
friend complex2d operator-(complex2d);

friend complex2d operator+(complex2d, complex2d);
friend complex2d operator-(complex2d, complex2d);

friend complex2d operator*(complex2d, complex2d);
friend complex2d operator/(complex2d, complex2d);

friend complex2d operator*(double, complex2d);
friend complex2d operator/(complex2d, double);

friend complex2d operator*(complex2d, double);
friend complex2d operator/(double, complex2d);

/* mgn = luvun suuruus */
friend double mgn(complex2d);
friend complex2d ln(complex2d);
friend complex2d exp(complex2d);
friend complex2d sin(complex2d);
friend complex2d cos(complex2d);
friend complex2d pow(complex2d, int);
friend complex2d pow(complex2d, double);
friend complex2d pow(complex2d, complex2d);
};

complex2d::complex2d(void)
{
r=i=j=k=real2d(0);
}

complex2d::complex2d(int a)
{
r=real2d(a, 0);
i=j=k=real2d(0);
}

complex2d::complex2d(double a)
{
r=real2d(a, 0.0);
i=j=k=real2d(0.0);
}

complex2d::complex2d(real2d a)
{
r=a; i=j=k=real2d(0);
}

complex2d::complex2d(double a, double b)
{
r=real2d(a, b);
i=j=k=real2d(0);
}

complex2d::complex2d(real2d a, real2d b)
{
r=a; i=b; j=k=real2d(0);
}

complex2d::complex2d(real2d a, real2d b, real2d c, real2d d)
{
r=a; i=b; j=c; k=d;
}

complex2d operator-(complex2d a)
{
return complex2d(-a.r, -a.i, -a.j, -a.k);
}

complex2d operator+(complex2d a, complex2d b)
{
return complex2d(a.r+b.r, a.i+b.i, a.j+b.j, a.k+b.k);
}

complex2d operator-(complex2d a, complex2d b)
{
return complex2d(a.r-b.r, a.i-b.i, a.j-b.j, a.k-b.k);
}

complex2d operator*(complex2d a, complex2d b)
{
complex2d c;

c.r = real2d(1,0,0,0)*a.r*b.r + real2d(0,1,0,0)*a.i*b.i
+ real2d(0,0,1,0)*a.j*b.j + real2d(0,0,0,1)*a.k*b.k;

c.i = real2d(1,0,0,0)*a.r*b.i + real2d(1,0,0,0)*a.i*b.r
+ real2d(1,0,0,0)*a.j*b.k + real2d(1,0,0,0)*a.k*b.j;

c.j = real2d(1,0,0,0)*a.r*b.j + real2d(0,0,0,1)*a.i*b.k
+ real2d(1,0,0,0)*a.j*b.r + real2d(0,0,0,1)*a.k*b.i;

c.k = real2d(1,0,0,0)*a.r*b.k + real2d(0,0,1,0)*a.i*b.j
+ real2d(0,0,1,0)*a.j*b.i + real2d(1,0,0,0)*a.k*b.r;

return c;
}

complex2d operator/(complex2d a, complex2d b)
{
complex2d L;
real2d z(0);

L=complex2d(b.r, b.i, -b.j, -b.k);
a = a*L;
b = b*L;

L=complex2d(b.r, -b.i, z, z);
a = a*L;
b = b*L;

a.r = a.r/b.r;
a.i = a.i/b.r;
a.j = a.j/b.r;
a.k = a.k/b.r;

return a;
}

complex2d operator*(double a, complex2d b)
{
return complex2d(a*b.r, a*b.i, a*b.j, a*b.k);
}

complex2d operator/(complex2d a, double b)
{
return complex2d(a.r/b, a.i/b, a.j/b, a.k/b);
}

complex2d operator*(complex2d a, double b)
{
return complex2d(b*a.r, b*a.i, b*a.j, b*a.k);
}

complex2d operator/(double a, complex2d b)
{
return complex2d(a)/b;
}

double mgn(complex2d a)
{
double sum=0;
sum+=mgn(a.r);
sum+=mgn(a.i);
sum+=mgn(a.j);
sum+=mgn(a.k);
return sum;
}

double abs(complex2d a)
{
complex2d L;
real2d z(0);

L=complex2d(a.r, a.i, -a.j, -a.k);
a = a*L;

L=complex2d(a.r, -a.i, z, z);
a = a*L;

a.r=pow(a.r, 0.25);

return abs(a.r);
}

complex2d sqrt(complex2d c)
{
if (mgn(c)<1e-20)
{
return complex2d(0);
}
else
{
complex2d x=c;
for (int i=0; i<160; i++)
x=x-(x*x-c)/(2.0*x);
return (complex2d)x;
}
}

complex2d sin(complex2d x)
{
double t=1.0;
complex2d sum(0.0);
complex2d y=x*x, xx=x;

for (int i=1, sg=0; i<160; i+=2, sg++)
{
if (sg&1) sum=sum-xx/t;
else /**/ sum=sum+xx/t;
xx=xx*y; t*=(i+1)*(i+2);
if (mgn(xx)>MAX) break;
}
return sum;
}

complex2d cos(complex2d x)
{
double t=2.0;
complex2d sum(1.0);
complex2d y=x*x, xx=y;

for (int i=2, sg=1; i<160; i+=2, sg++)
{
if (sg&1) sum=sum-xx/t;
else /**/ sum=sum+xx/t;
xx=xx*y; t*=(i+1)*(i+2);
if (mgn(xx)>MAX) break;
}
return sum;
}

complex2d pow(complex2d x, int n)
{
if (n)
{
complex2d t=x;
int i=n<0? -n: n;
for (--i; i; i--) t=t*x;
return n>0? t: complex2d(1.0)/t;
}
else
{
return complex2d(1.0);
}
}

complex2d ln(complex2d c)
{
int n=1;
double t;
complex2d fx, dx;
complex2d x1, x2;
complex2d z(1.0);
complex2d x(1.0), xx;

while (abs(c)>1.001)
{
c=sqrt(c);
n+=n;
}

for (int k=2; k<160; k++)
for (int j=0; j<160; j++)
{
xx=x; t=1.0;
fx=z+x; dx=z;

for (int i=2; i<=k; i++)
{
dx=dx+i*xx/(t*=i);
xx=xx*x; fx=fx+xx/t;
if (mgn(fx)>MAX) break;
}

x1=x;
x=x-(fx-c)/dx;
x2=x;

if (k+1 < 160)
{
if (mgn(x1-x2)<1e-15) break;
}
}

return (double)n*x;
}

complex2d exp(complex2d x)
{
complex2d xx;
double t=1.000;
complex2d sum(1);

sum=sum+(xx=x);

for (int i=2; i<160; i++)
{
xx = xx*x;
sum=sum+xx/(t*=i);
if (mgn(xx)>MAX) break;
}

return sum;
}

complex2d pow(complex2d a, complex2d x)
{
double t=(double)1;
complex2d sum(1.000);
complex2d ln(complex2d);
complex2d y=x*ln(a), xx=y;

sum=sum+xx;

for (int i=2; i<160; i++)
{
xx = xx*y;
sum=sum+xx/(t*=i);
if (mgn(xx)>MAX) break;
}

return sum;
}

complex2d pow(complex2d x, double n)
{
return pow(x, complex2d(n));
}

void print(complex2d a)
{
printf("[\n");
printf(" r="); print(a.r);
printf(" i="); print(a.i);
printf(" j="); print(a.j);
printf(" k="); print(a.k);
printf("]\n");
}

typedef unsigned long uint32;

uint32 rnd(uint32 max)
{
static uint32 R16A=1L;
static uint32 R16B=2L;
R16A -= 0x012357bfL;
R16B += 0xfedca201L;
R16A += (R16A>>16)^(R16B<<16);
R16B -= (R16A<<16)^(R16B>>16);
return (R16A^R16B)%max;
}

double drand(void)
{
uint32 jak=0xfffffffb;
double sg=rnd(2)? -1: 1;
double x=(double)rnd(jak);
return sg * x / (double)jak;
}

#pragma argsused
int main(int kpl, char* asia[])
{
for (int n=0; n<32767; n++)
{
real2d r(drand(), drand());
real2d i(drand(), drand());
real2d j(drand(), drand());
real2d k(drand(), drand());

complex2d c(r, i, j, k);

complex2d x=sqrt(c);

print(x);

print(x*x-c);

print(sin(c)*sin(c)+cos(c)*cos(c));

printf("================================\n\n");
}
return 0;
}[/code:34e6pg7i]

Sivut

Kommentit (16)

Vierailija

Lisäsin tuohon complex2d-olioon loputkin funktiot. Toivottavasti moni on pannut merkille, että algebran algoritmit/metodit esimerkiksi sarjoissa ovat suhteellisen vakioita. Algebra ei ota kantaa, mistä substanssista se logaritmia on ottamassa, kunhan vain substanssi on itsensä kanssa ristiriidaton.

Jos viimeisenä olevan testi-main funktion korvaa main:lla:

[code:13jwddbf]#pragma argsused
int main(int kpl, char* asia[])
{
for (int n=0; n<32767; n++)
{
real2d r(2.71828182845904523536);
real2d i(drand(), drand());
real2d j(drand(), drand());
real2d k(drand(), drand());
real2d z(0);

complex2d e(r, z, z, z);
complex2d x(z, i, j, k);

complex2d f=pow(e, x);

print(f);

printf("%0.21f\n", abs(f));

printf("================================\n\n");
}
return 0;
}[/code:13jwddbf]
Voi taas todeta, että myös 2D-kompleksiluvuilla on:

|e^(ai+bj+ck)| = 1

Tuon lauseen algebrallisen faktan toteutuminen on erityisen tärkeä muun muassa DFT-/IDFT approksimaatiossa.

Työn tai paremminkin harrastuksen alla on melko voimakkaasti sellainen sovellus, joka pystyisi noitten hitaitten sarjojen sijasta käyttämään suoraviivaisia laskukaavoja logaritmeille, trigonometrisille funktioille, yms. funktioille. Alkaa Pentium hyytymään, jos pitää sarjoilla generoida miljoona 2D-kompleksilukuista logaritmia.

Vierailija

No nyt alan pikkuhiljaa pääsemään kärryille tuosta 2D-kompleksiluvusta. Minä en saanut sitten millään koko oliota ristiriidattomaksi. Ihmettelen vain, että mahtaa sinulla olla tehokas laskukone, jos olet tuon tasapainon koneella loihtinut?

Vaihdannaisuus on täydellistä. Jos kerron jonkin 2D-kompleksen A-luvun B:llä, saan tulokseksi arvon C. Nyt kun jaan päinvastoin C:n B:llä, saan tismalleen tulokseksi A:n. Näemmä jakolaskukin suoritetaan kahden liittoluvun avustuksella, minä yritin ratkaista sitä yhdellä liittoluvulla.

Itse asiassa tuo 2D-kompleksiluku on formuloinniltaan yksinkertaisempi, kuin 2D-reaaliluku. Ajattelin asian olevan päinvastoin, ja ehkä siksi ajauduin suoraan metsähallituksen puolelle, kun yritin saada j- ja k-olioita toimimaan.

Fraktaaleja olen ehtinyt jo tutkimaan vähän, ja Mandelbrotin joukkoa näyttäisi kovasti lykkäävän. Teenkö jotain väärin, vai missä ne kertomasi harmonisemmat fraktaalirakenteet ovat?

-torstai

Vierailija

Miksi muuten käytät C/C++ jos kuitenkin teknisestä/tieteellisestä laskennasta kysymys? Eikös Fortran ole aikalailla standardi tuolla alalla (ollut perinteisesti ja on käsittääkseni vieläkin). Se on yksinkertaisempi kieli, mutta perinteisesti ollut myös hitusen tehokkaampi.

Neutroni
Seuraa 
Viestejä26834
Liittynyt16.3.2005
boner
[Offtopic] Miksi muuten käytät C/C++ jos kuitenkin teknisestä/tieteellisestä laskennasta kysymys? Eikös Fortran ole aikalailla standardi tuolla alalla (ollut perinteisesti ja on käsittääkseni vieläkin). Se on yksinkertaisempi kieli, mutta perinteisesti ollut myös hitusen tehokkaampi.

Kyllä C (tai C++) ovat yleistyneet. Ainakin sillä alalla, jolla itse toimin, noita käytetään hyvin yleisesti Fortranin ohella.

Vierailija

Sitten C/C++:ssa on vielä tehokkaat alemman tason operaatiot muun muassa Boolen algebralle. Ellen väärin muista, Fortran tukee niitä huonosti. Esimerkiksi 2^16 latinalaisen neliön staattinen taulukointi olisi aika järjetöntä, kun C:ssä on suoraan yhden merkin operaatio esim. ehdoton tai operaatiolle.

C:hen sisällytettiin alun perin mukaan kaikki alemman tason vaikutusmahdollisuudet. C:n monipuolisuus esim. osoittimien pyörittelyssä on aivan omaa luokkaansa. Myös C:n strukturointi ansaitsee maininnan.

C:n olemus yleisellä tasolla on eräänlainen hybridi korkeammantason kielestä, sekä alemman tason konekielitasosta. C++:ssa koodin sekaan voi myös kirjoittaa suoraan assembleriakin, jos tarve vaatii.

Vierailija
boner
Eikös Fortran ole aikalailla standardi tuolla alalla (ollut perinteisesti ja on käsittääkseni vieläkin). Se on yksinkertaisempi kieli, mutta perinteisesti ollut myös hitusen tehokkaampi.

Varmasti varsinkin uusimmat Fortran-kääntäjät ajavat asiansa hyvin. Mutta tuota nopeuseroa ei enää ole. Ennen liukuluvut jouduttiin emuloimaan, jota Fortranissa oli nimenomaan kehitetty pidemmälle.

Nykyisissä prosessoreissa sen matematiikkayksikkö vastaa liukulukujen käsittelystä. C kuin myös Fotran dumppaavat liukulukuihin törmätessään ne prosessorin matematiikkayksikköön, ja kopioivat valmiin tuloksen takaisin sieltä parametriin.

Vierailija
torstai
Fraktaaleja olen ehtinyt jo tutkimaan vähän, ja Mandelbrotin joukkoa näyttäisi kovasti lykkäävän. Teenkö jotain väärin, vai missä ne kertomasi harmonisemmat fraktaalirakenteet ovat?

No, noissa saa soveltaa aika lailla, eikä savotta ihan heti lopu. Pullonkaulana on vähän, että kun 2D-kompleksilukuihin liittyvää ilmiötä yrittää pakottaa tasossa kuvatuiksi, informaatio on vain jokin varjokuva todellisuudesta.

Tuohon avatariini laskin 2D-kompleksilukuisen (x^4-1=0) Newtonin prosessin jonkinsorttista varjokuvaa.

Päivässä pitäisi olla enemmän tunteja, jotta ehtisi tutkimaan kunnolla myös fraktaaleja. Toistaiseksi sovellettu matematiikka lohkaisee suurimman osan vapaa-ajastani.

Vierailija

Onnistui lopulta tuo kuvienkin liittäminen. Huoh. Tuohon on nyt sitten laskettuna vähän suurempana yhtälön:
x^4+1=0
Newtonin prosessin jonkin sorttinen varjokuva.

Todellinen ongelma on, että tasosta on vaikea repiä neljää ulottuvuutta. Aivan sama, laskeeko noita moniulotteisella algebralla, tai 2D-algebralla tai vieläkin kummallisemmin moniulotteisella 2D-algebralla.

Oikea tai ainakin parempi tapa visualisoida noita moniulotteisia fraktaaleja, olisi laskea niitä 3D:nä, ja morfata kuvaa liu’uttamalla neljättä akselia. Samaan aikaan tietenkin fraktaalin maisemissa lenneltäisiin aluksella. Hommaan pitäisi sovittaa musiikki, ja yleensäkin tehdä jonkinlainen käsikirjoitus.

Laskutehoa tarvittaisiin helvetisti. Jahka tässä pääsee säästämään, aion hankkia 64 klusterin laskukoneen, jolla tuon lyhytelokuvan toteuttaminen onnistuisi inhimillisessä ajassa.

Joka tapauksessa tuo varokuva on enemmän tai vähemmän perseestä, ja siinä on vain aavistus siitä todellisuudesta, mitä fraktaalirakenteet moniulotteisina ovat.

Vierailija
_jone_
...Oikea tai ainakin parempi tapa visualisoida noita moniulotteisia fraktaaleja, olisi laskea niitä 3D:nä, ja morfata kuvaa liu’uttamalla neljättä akselia.

Olisiko tuosta sitten suurta vaivaa laskea edes yksi 3D-fraktaali? Minun rehellinen mielipiteeni on myös, kuten sanoit, että tuo 2D-kuva on ahterista. Noita 2D-fraktaaleja on kyllä nähty kyllästymiseen asti...valitan suorapuheisuuttani, mutta tänään on ollut vähän huono päivä...

-toorstaaiii

Vierailija
torstai
Olisiko tuosta sitten suurta vaivaa laskea edes yksi 3D-fraktaali?

Periaatteessa on, koska tällä läppärillä yksi 3D-fraktaali on 2-4 vk:n urakka. Valot, varjot, sumut. Samaan aikaan puolet päivästä työtä varsinaisen työn parissa. Mutta voin sinulle kyllä yhden 3D-fraktaalin laskea, ellet sellaista jaksa/osaa itse laskea.

Vierailija
_jone_
Mutta voin sinulle kyllä yhden 3D-fraktaalin laskea, ellet sellaista jaksa/osaa itse laskea.

Anteeksi vain huono päivä, mutta kyllä todellakin pystyisin laskemaan tasan saman, minkä sinäkin. Satun nyt vain ohjelmoimaan yleensäkin 3D:nä.

Sinä olet esittänyt noita algebran laajennuksia, eikä ole minun asiani keksiä niille käytännön sovelluksia, vai onko? Todellinen 3D-fraktaalirakenne olisi kova juttu, lykkyä pyttyyn. Mutta sen visualisointi ei ole minun probleemani.

Toisekseen meinasin menettää hermoni, kun avasin noita sinun koodiasi ilman ensimmäistäkään kommenttia. Kyllä, noin ne toimivat, mutta olisiko muutama selventävä kommentti ollut liikaa vaadittu? Dokumentoi hyvä mies nyt ensin nuo koodisi niin, että niistä voisi joku muukin päästä kärryille, kuin C-spesialisti.

-torstai

Vierailija
torstai
...

No ei noissa koodeissa pitäisi kovin paljon edes avaamista olla. gsolve:kin oli vielä helppo, verrattuna esim. FEM:in spesifiseen nauhamatriisioptimointiin, jolla voi siis pyöritellä vaivattomasti vaikkapa sadan tuhannen tuntemattoman yhtälöryhmiä.

Tiedä sitten, kuinka tunnettu menetelmä tuo käyttämäni osittain derivoinnilla toteutettu luonnollisen logaritmin iterointi on, mutta sellaisella mössöllä ne logaritmit pitää iteroida, muuten arvot karkaavat suorinta tietä lehmän perseeseen.

Kolmanneksi algebran kirjat ovat täynnä sovellusesimerkkejä. Ei kai minun ole järkevää poimia esimerkeiksi niistä kuin joitakin helmiä. Tällainen on muun muassa pienimmän neliösumman polynomiapproksimaatio.

Neljänneksi koodaustaitoasi ja -kykyäsi en ole missään vaiheessa kyseenalaistanut. Ilmeisesti juuri kovan koodaustaitosi ansiosta olet ollut niitä harvoja, joka on mielipiteitään esittänyt.

Sen puoleen ihan asiallinen kehotus, että pränttäisin tuon koodin joukkoon dokumenttia ja esimerkkejä (se oli tarkoituksenikin), mutta kun päivässä on liian vähän tunteja suhteessa pinossa oleviin tehtäviin. Joudun siis välissä hengittämään happea, ja taas jatkamaan hiki hatussa pinon purkamista...

Vierailija
_jone_
Tällainen on muun muassa pienimmän neliösumman polynomiapproksimaatio.

Miksi käytät neliösummaa ? Pitääkö eksponentin olla juuri 2.00000000 eikä esim 2.00001 ?

Tai vaikka 3.5 ?

Vierailija
Boysen
Parin kympin DSP laskee 1024 pisteen kompleksisen FFT:n 100 000 kertaa sekunnissa.

No on noittenkin kanssa joskus työtä tullut tehtyä. Niissä on omat rankat kovo-optimoinnit spesifisille asioille.

Yleiskäyttöön niistä ei ole. Esimerkiksi sähkömoottoreiden magneettikenttiä niillä ei vielä toistaiseksi mallinneta, ehkä kuitenkin joskus tulevaisuudessa.

Kyllä se Pentium suhteellisen tehokkaasti laskee kaikkea maan ja taivaan väliltä, varsinkin jos ne ovat klustereina räkissä.

Sivut

Uusimmat

Suosituimmat