Nimen takaa paljastuu niinkin tylsä asia kuin kompleksilukumatematiikkakirjasto, jonka löysin koneeni syövereistä sattumalta. Ajattelin, että siitä voisi olla jollekin hyötyä, joten lähetänpä sen tänne. Tein tällä kokeeksi mm. mandelbrotin fraktaaleja, mikä tosin osoittautui erittäin hitaaksi verrattuna ilman varsinaista kompleksilukutietotyyppiä toteutettuun versioon, joten suurin hyöty kirjastosta lienee kompleksilukulaskennan opettelussa. Lisäksi CB:n 32-bittiset liukuluvut ovat niin epätarkkoja, että pyöristysvirheet näkyvät hyvin yksinkertaisillakin laskutoimituksilla.
Mikä ihmeen kompleksiluku?
Kompleksiluvut on "suurin" (ehkä paremminkin monimutkaisin :P) lukujoukko, jolle on mahdollista määritellä reaalilukujen kanssa analogiset (yhtenevät) laskulait. Kompleksiluvut muistuttavat hieman vektoreita, sillä ne ovat kaksikomponenttisia. Kuitenkin kompleksiluvut toimivat sellaisenaan vain tasossa eli kahdessa ulottuvuudessa (neliulotteisia kompleksilukuja kutsutaan kvaternioiksi ja kahdeksanulotteisia oktonioiksi, mutta reaalilukujen laskulait eivät niille päde) - toisin kuin vektorit, jotka voivat käsittää kuinka monta ulottuvuutta tahansa. Toisekseen vektorien keskinäinen tulo (ristitulo) on antikommutatiivinen, kun kompleksilukujen tulo taas on kommutatiivinen, kuten reaalilukujenkin. Lisäinformaatiota saa mm. Wikipediasta
Kommenteista pitäisi irrota kaikki tarvittava tieto kirjaston käyttämiseksi. En muista, olenko ihan jokaista funktiota edes käyttänyt, joten mahdollisista virheistä saa ilmoitella.
Kirjasto:
Code: Select all
//Kompleksilukukirjasto CoolCPLX by Pontus "SPuntte" Lundström
Const e = 2.71828182845904523536
Const pi_ = 3.14159265358979323846
//Luo kompleksiluvun ja palauttaa sen kahvan
//a# Reaaliosa
//b# Imaginaariosa
Function CPLX_New(a#=0, b#=0)
Dim c% As Integer
c = MakeMEMBlock(8)
PokeFloat c, 0, a
PokeFloat c, 4, b
Return c
EndFunction
//Sijoittaa olemassa olevaan kompleksilukuun annetun reaali- ja imaginaariosan
//a# Reaaliosa
//b# Imaginaariosa
Function CPLX_Assign(c%, a#, b#)
PokeFloat c, 0, a
PokeFloat c, 4, b
EndFunction
//Sijoittaa olemassa olevaan instanssiin annetun reaaliosan
//a# Reaaliosa
Function CPLX_AssignRe(c%, a#)
PokeFloat c, 0, a
EndFunction
//Sijoittaa olemassa olevaan instanssiin annetun imaginaariosan
//b# Imaginaariosa
Function CPLX_AssignIm(c%, b#)
PokeFloat c, 4, b
EndFunction
//Palauttaa 1, jos annetut kompleksiluvut ovat yhtä suuria
//c1% ensimmäisen kompleksilukuinstanssin kahva
//c2% toisen kompleksilukuinstanssin kahva
Function CPLX_Equals(c1%, c2%, threshold#=0.00001)
If Abs(PeekFloat(c1, 0) - PeekFloat(c2, 0)) <= threshold And Abs(PeekFloat(c1, 4) - PeekFloat(c2, 4)) <= threshold Then
Return True
Else
Return False
EndIf
EndFunction
//Palauttaa kompleksiluvun reaaliosan
//c% kompleksilukuinstanssin kahva
Function CPLX_Re(c%)
Return PeekFloat(c, 0)
EndFunction
//Palauttaa kompleksiluvun
//c% kompleksilukuinstanssin kahva
Function CPLX_Im(c%)
Return PeekFloat(c, 4)
EndFunction
//Laskee kompleksiluvun kompleksikonjugaatin eli liittoluvun ja sijoittaa sen annettuun kompleksilukuinstanssiin tai palauttaa uuden kompleksiluvun kahvan
//c% kompleksilukuinstanssin kahva
//ret% kahva kompleksilukuinstanssiin, johon tulos sijoitetaan; arvolla -1 luodaan uusi instanssi ja palautetaan sen kahva
Function CPLX_Conjugate(c%, ret%=-1)
Dim z% As Integer
If ret = -1 Then
z = MakeMEMBlock(8)
PokeFloat z, 0, PeekFloat(c, 0)
PokeFloat z, 4, -PeekFloat(c, 4)
Return z
Else
PokeFloat ret, 0, PeekFloat(c, 0)
PokeFloat ret, 4, -PeekFloat(c, 4)
EndIf
EndFunction
//Laskee kompleksiluvun negaation (vastaluku) ja sijoittaa sen annettuun kompleksilukuinstanssiin tai palauttaa uuden kompleksiluvun kahvan
//c% kompleksilukuinstanssin kahva
//ret% kahva kompleksilukuinstanssiin, johon tulos sijoitetaan; arvolla -1 luodaan uusi instanssi ja palautetaan sen kahva
Function CPLX_Inverse(c%, ret=-1)
Dim z% As Integer
Dim a#, b#, sqs# As Float
a = PeekFloat(c, 0)
b = PeekFloat(c, 4)
sqs = a*a + b*b
If ret = -1 Then
z = MakeMEMBlock(8)
PokeFloat z, 0, a/sqs
PokeFloat z, 4, -b/sqs
Return z
Else
PokeFloat ret, 0, a/sqs
PokeFloat ret, 4, -b/sqs
EndIf
EndFunction
//Palauttaa kompleksiluvun modulin eli itseisarvon
//c% kompleksilukuinstanssin kahva
Function CPLX_Modulus(c%)
Return Distance(0, 0, PeekFloat(c, 0), PeekFloat(c, 4))
EndFunction
//Palauttaa kompleksiluvun argumentin eli vaihekulman
//c% kompleksilukuinstanssin kahva
//rad arvolla TOSI kulmayksikkönä on radiaani, muuten aste
Function CPLX_Argument(c%, rad=1)
Dim a# As Float
a = GetAngle(0, 0, PeekFloat(c, 0), -PeekFloat(c, 4))
a = a - (a > 180.0)*360.0
If rad Then Return a*pi_/180
Return a
EndFunction
//Laskee kahden kompleksiluvun summan ja sijoittaa sen annettuun kompleksilukuinstanssiin tai palauttaa uuden kompleksiluvun kahvan
//c1% ensimmäisen kompleksilukuinstanssin kahva
//c2% toisen kompleksilukuinstanssin kahva
//ret% kahva kompleksilukuinstanssiin, johon tulos sijoitetaan; arvolla -1 luodaan uusi instanssi ja palautetaan sen kahva
Function CPLX_Add(c1%, c2%, ret=-1)
Dim z% As Integer
Dim a1#, a2#, b1#, b2# As Float
a1 = PeekFloat(c1, 0)
b1 = PeekFloat(c1, 4)
a2 = PeekFloat(c2, 0)
b2 = PeekFloat(c2, 4)
If ret = -1 Then
z = MakeMEMBlock(8)
PokeFloat z, 0, a1 + a2
PokeFloat z, 4, b1 + b2
Return z
Else
PokeFloat ret, 0, a1 + a2
PokeFloat ret, 4, b1 + b2
EndIf
EndFunction
//Laskee kahden kompleksiluvun erotuksen ja sijoittaa sen annettuun kompleksilukuinstanssiin tai palauttaa uuden kompleksiluvun kahvan
//c1% ensimmäisen kompleksilukuinstanssin kahva
//c2% toisen kompleksilukuinstanssin kahva
//ret% kahva kompleksilukuinstanssiin, johon tulos sijoitetaan; arvolla -1 luodaan uusi instanssi ja palautetaan sen kahva
Function CPLX_Subtract(c1%, c2%, ret=-1)
Dim z% As Integer
Dim a1#, a2#, b1#, b2# As Float
a1 = PeekFloat(c1, 0)
b1 = PeekFloat(c1, 4)
a2 = PeekFloat(c2, 0)
b2 = PeekFloat(c2, 4)
If ret = -1 Then
z = MakeMEMBlock(8)
PokeFloat z, 0, a1 - a2
PokeFloat z, 4, b1 - b2
Return z
Else
PokeFloat ret, 0, a1 - a2
PokeFloat ret, 4, b1 - b2
EndIf
EndFunction
//Kertoo kompleksiluvun reaaliluvulla eli "skaalaa" sen
//r# reaaliluku
//c% kompleksilukuinstanssin kahva
Function CPLX_RealMultiply(r#, c%)
PokeFloat c, 0, r*PeekFloat(c, 0)
PokeFloat c, 4, r*PeekFloat(c, 4)
EndFunction
//Laskee kahden kompleksiluvun tulon ja sijoittaa sen annettuun kompleksilukuinstanssiin tai palauttaa uuden kompleksiluvun kahvan
//c1% ensimmäisen kompleksilukuinstanssin kahva
//c2% toisen kompleksilukuinstanssin kahva
//ret% kahva kompleksilukuinstanssiin, johon tulos sijoitetaan; arvolla -1 luodaan uusi instanssi ja palautetaan sen kahva
Function CPLX_Multiply(c1%, c2%, ret%=-1)
Dim z% As Integer
Dim a1#, a2#, b1#, b2# As Float
a1 = PeekFloat(c1, 0)
b1 = PeekFloat(c1, 4)
a2 = PeekFloat(c2, 0)
b2 = PeekFloat(c2, 4)
If ret = -1 Then
z = MakeMEMBlock(8)
PokeFloat z, 0, (a1*a2-b1*b2)
PokeFloat z, 4, (a1*b2+a2*b1)
Return z
Else
PokeFloat ret, 0, (a1*a2-b1*b2)
PokeFloat ret, 4, (a1*b2+a2*b1)
EndIf
EndFunction
//Laskee kahden kompleksiluvun osamäärän ja sijoittaa sen annettuun kompleksilukuinstanssiin tai palauttaa uuden kompleksiluvun kahvan
//c1% ensimmäisen kompleksilukuinstanssin kahva
//c2% toisen kompleksilukuinstanssin kahva
//ret% kahva kompleksilukuinstanssiin, johon tulos sijoitetaan; arvolla -1 luodaan uusi instanssi ja palautetaan sen kahva
Function CPLX_Divide(c1%, c2%, ret%=-1)
Dim z% As Integer
Dim a1#, a2#, b1#, b2#, sqs# As Float
a1 = PeekFloat(c1, 0)
b1 = PeekFloat(c1, 4)
a2 = PeekFloat(c2, 0)
b2 = PeekFloat(c2, 4)
sqs# = a2*a2 + b2*b2
If ret = -1 Then
z = MakeMEMBlock(8)
PokeFloat z, 0, (a1*a2+b1*b2)/sqs
PokeFloat z, 4, (b1*a2-a1*b2)/sqs
Return z
Else
PokeFloat ret, 0, (a1*a2+b1*b2)/sqs
PokeFloat ret, 4, (b1*a2-a1*b2)/sqs
EndIf
EndFunction
//Laskee arvon potenssilausekkeelle, jossa kantaluku on reaalinen ja eksponentti kompleksinen ja sijoittaa sen annettuun kompleksilukuinstanssiin tai palauttaa uuden kompleksiluvun kahvan
//base# kantaluku
//exp% eksponentin kahva
//ret% kahva kompleksilukuinstanssiin, johon tulos sijoitetaan; arvolla -1 luodaan uusi instanssi ja palautetaan sen kahva
Function CPLX_PowRC(base#, exp%, ret%=-1)
Dim z% As Integer
z = MakeMEMBlock(8)
MemCopy exp, 0, z, 0, 8
CPLX_RealMultiply(Log(base#), z)
If ret = -1 Then
CPLX_Exp(z, z)
Return z
Else
CPLX_Exp(z, ret)
DeleteMEMBlock z
EndIf
EndFunction
//Laskee arvon potenssilausekkeelle, jossa kantaluku on kompleksinen ja eksponentti reaalinen ja sijoittaa sen annettuun kompleksilukuinstanssiin tai palauttaa uuden kompleksiluvun kahvan
//base% kantaluvun kahva
//exp# eksponentti
//ret% kahva kompleksilukuinstanssiin, johon tulos sijoitetaan; arvolla -1 luodaan uusi instanssi ja palautetaan sen kahva
Function CPLX_PowCR(base%, exp#, ret%=-1)
Dim z, i As Integer
If RoundUp(exp) = RoundDown(exp) Then
z = CPLX_New(1, 0)
If ret = -1 Then
For i = 1 To exp
CPLX_Multiply(z, base, z)
Next i
Return z
Else
For i = 1 To exp - 1
CPLX_Multiply(z, base, z)
Next i
CPLX_Multiply(z, base, ret)
DeleteMEMBlock z
EndIf
Else
z = CPLX_Log(base)
CPLX_RealMultiply(exp, z)
If ret = -1 Then
CPLX_Exp(z, z)
Return z
Else
CPLX_Exp(z, ret)
DeleteMEMBlock z
EndIf
EndIf
EndFunction
//Laskee arvon potenssilausekkeelle, jossa sekä kantaluku että eksponentti ovat kompleksilukuja ja sijoittaa sen annettuun kompleksilukuinstanssiin tai palauttaa uuden kompleksiluvun kahvan
//base% kantaluvun kahva
//exp% eksponentin kahva
//ret% kahva kompleksilukuinstanssiin, johon tulos sijoitetaan; arvolla -1 luodaan uusi instanssi ja palautetaan sen kahva
Function CPLX_PowCC(base%, exp%, ret%=-1)
Dim z As Integer
z = CPLX_Log(base)
CPLX_Multiply(exp, z, z)
If ret = -1 Then
CPLX_Exp(z, z)
Return z
Else
CPLX_Exp(z, ret)
DeleteMEMBlock z
EndIf
EndFunction
//Korottaa Neeperin luvun (e) annetun kompleksiluvun osoittamaan potenssiin ja sijoittaa tuloksen annettuun kompleksilukuinstanssiin tai palauttaa uuden kompleksiluvun kahvan
//c% kompleksilukuinstanssin kahva
//ret% kahva kompleksilukuinstanssiin, johon tulos sijoitetaan; arvolla -1 luodaan uusi instanssi ja palautetaan sen kahva
Function CPLX_Exp(c%, ret%=-1)
Dim z% As Integer
Dim x#, y#, etox# As Float
x = PeekFloat(c, 0)
y = (PeekFloat(c, 4) * 180.0) / pi_
etox = e^x
If ret = -1 Then
z = MakeMEMBlock(8)
PokeFloat z, 0, Cos(y)*etox
PokeFloat z, 4, Sin(y)*etox
Return z
Else
PokeFloat ret, 0, etox*Cos(y)
PokeFloat ret, 4, etox*Sin(y)
EndIf
EndFunction
//Laskee kompleksisen logaritmin annetulle kompleksiluvulle ja sijoittaa tuloksen annettuun kompleksilukuinstanssiin tai palauttaa uuden kompleksiluvun kahvan
//c% kompleksilukuinstanssin kahva
//ret% kahva kompleksilukuinstanssiin, johon tulos sijoitetaan; arvolla -1 luodaan uusi instanssi ja palautetaan sen kahva
Function CPLX_Log(c%, ret%=-1)
Dim z% As Integer
Dim x#, y#, arg# As Float
x = PeekFloat(c, 0)
y = PeekFloat(c, 4)
arg = CPLX_Argument(c)
If ret = -1 Then
z = MakeMEMBlock(8)
PokeFloat z, 0, 0.5 * Log(x*x + y*y)
PokeFloat z, 4, arg
Return z
Else
PokeFloat ret, 0, 0.5 * Log(x*x + y*y)
PokeFloat ret, 4, arg
EndIf
EndFunction
Code: Select all
//Calculate: i^i
z = CPLX_New(0, 1)
CPLX_PowCC(z, z, z)
//Prove that e^(i * pi) + 1 = 0
w = CPLX_New(0, 1)
realOne = CPLX_New(1, 0) //number 1 LOL
CPLX_RealMultiply(pi_, w)
CPLX_Exp(w, w)
CPLX_Add(w, realOne, w)
DeleteMEMBlock realOne
Repeat
Text 5, 5, "i^i = " + CPLX_Re(z) + " + " + CPLX_Im(z) + " i"
Text 5, 20, "e^(i * pi) + 1 = " + CPLX_Re(w) + " + " + CPLX_Im(w) + " i"
DrawScreen
Forever