Παρασκευή 25 Νοεμβρίου 2022

Complex Numbers (part 1)

This part has two final classes, the DoubleComplex() and the FloatComplex. Each class define objects of general type Group, with types DoubleComplex & Complex, and FloatComplex & Complex.

Each class has a constructor/ In each constructor we make a Buffer of two at least numbers, for Double Complex we use double type (8bytes per number), for the other we use Single type (4 bytes per number). Each constructor can take 1 to 3 arguments, the first is the real number, the second is the imaginary number and last is how many complex numbers we need. 

We make Value and Set methods to handle the way we assign values and read values from these objects. After we define an object we can assign a new value either from same type or using the another type but from base class Complex.

Just look the code.

Class Complex {
Private:
k, lim=0
Function copy {
=group(this)
}
Public:
Property Ptr {
value {link parent k to k: value=k(0)}
}
Property Ubound {
value {link parent lim to lim: value=lim}
}
Final Lbound=0&
// we use clear to clear value variable which property define as double by default
// using Property a { }=0& we can define the value as long
// but here we use Real for two different buffers, one with type double and one with type single
Property Real {
value {clear:link parent k to k: value=eval(k,0)}
}
Group Real {
operator "++" {
link parent k to k: Return k, 0:=eval(k, 0)+1
}
}
Property Imaginary {
value {clear:link parent k to k: value=eval(k,1)}
}
Group Imaginary {
operator "++" {
link parent k to k: Return k, 1:=eval(k, 1)+1
}
}
Property toString$ {
value {
Link parent k, lim to k, lim
read ? where=0&
if where<0 or where>lim then error "Index out of bound"
where*=2
m=eval(k,where+1)
if m==0 then
value$=format$("({0})",eval(k, where))
else.if eval(k,0)==0 then
u$="({1}i)"
value$=format$("({0}i)",eval(k,where+ 1))
else
if abs(m)==1 then u$="({0}{2}i)" else u$="({0}{2}{1}i)"
value$=format$(u$,eval(k, where),abs(m), IF$(m<0->"-","+"))
end if
}
}
Function Export$() {
=eval$(.k)
}
Module Import (This$) {
m=len(This$)*2
if m>0 and m<=len(.k) then
Return .k, 0:=This$
end if
}
Module SwapBuffers (&a as Complex){
if .len<> a.len then Error "Not compatible buffers"
swap .k, a.k
swap .lim, a.lim

}
Class:
Module Complex {
Error "Can't define objects"
}
}
Class DoubleComplex as Complex {
Private:
len=16
Function newDoubleComplex(a as DoubleComplex, w) {
buffer z as double*2
return z, 0:=eval$(.k, w*.len!, .len)
let a.k=z, a.lim=0 // k is Private in a
=group(a)
}
Function copyme(a as DoubleComplex) {
buffer z as double*2*(a.lim+1)
return z, 0:=eval$(.k)
let a.k=z
=group(a)
}
Public:
Operator "+"  {
read a as Complex
let this=.newFloatComplex(this, 0)
return .k, 0:=eval(.k,0)+a.real, 1:=eval(.k, 1)+a.imaginary
}
Operator "-"  {
read a as Complex
let this=.newFloatComplex(this, 0)
return .k, 0:=eval(.k,0)-a.real, 1:=eval(.k, 1)-a.imaginary
}
Set () {
read a as Complex
read ? where=0&
if where<0 or where>.lim then error "Index out of bound" else where*=2
if a is type FloatComplex then
return .k, where:=a.real, where+1:=a.imaginary
else.if a is type DoubleComplex then
return .k, where:=eval$(a.k)
else
error "can't assign this group"
end if
}
Module Redim (many as long) {
if many<1 then error "Wrong Dimension"
buffer clear .k as double*2*many: .lim<=many-1
}
Module RedimPreserve (many as long) {
if many<1 then error "Wrong Dimension"
buffer .k as double*2*many: .lim<=many-1
}
Function final copy {
=.copyme(this)
}
value () {
read ? where=0&
if where<0 or where>.lim then error "Index out of bound"

if where=0 and .lim=0 then
=this
else
=.newDoubleComplex(this, where)
end if
}
Class:
Module DoubleComplex (r as double=0, i as double=0, many=1&) {
if many<1 then error "Wrong Dimension"
buffer clear .k as double*2*many: .lim<=many-1
return .k, 0:=r, 1:=i
}
}
Class FloatComplex as Complex{
Private:
len=8
Function newFloatComplex(a as FloatComplex, w) {
buffer z as single*2
return z, 0:=eval$(.k, w*.len!, .len)
let a.k=z, a.lim=0
=group(a)
}
Function copyme(a as FloatComplex) {
buffer z as single*2*(a.lim+1)
return z, 0:=eval$(.k)
let a.k=z
=group(a)
}
Public:
Operator "+"  {
read a as Complex
let this=.newFloatComplex(this, 0)
return .k, 0:=eval(.k,0)+a.real, 1:=eval(.k, 1)+a.imaginary
}
Operator "-"  {
read a as Complex
let this=.newFloatComplex(this, 0)
return .k, 0:=eval(.k,0)-a.real, 1:=eval(.k, 1)-a.imaginary
}
Set () {
read a as Complex
read ? where=0&
if where<0 or where>.lim then error "Index out of bound" else where*=2
if a is type DoubleComplex then
return .k, where:=a.real, where+1:=a.imaginary
else.if a is type FloatComplex then
return .k, where:=eval$(a.k)
else
error "can't assign this group"
end if
}
Module Redim (many as long) {
if many<1 then error "Wrong Dimension"
buffer clear .k as single*2*many: .lim<=many-1
}
Module RedimPreserve (many as long) {
if many<1 then error "Wrong Dimension"
buffer .k as single*2*many: .lim<=many-1
}
Function final copy {
=.copyme(this)
}
value (){
read ? where=0&
if where<0 or where>.lim then error "Index out of bound"
if where=0 and .lim=0 then
=this
else
=.newFloatComplex(this, where)
end if
}
Class:
Module FloatComplex (r as single=0, i as single=0, many=1&) {
if many<1 then error "Wrong Dimension"
buffer clear .k as single*2*many: .lim<=many-1
return .k, 0:=r, 1:=i
}
}
def typename$(x)=type$(x)
z1=FloatComplex(2,2) : print z1.toString$="(2+2i)"
z2=DoubleComplex(-2,3) :print z2.toString$="(-2+3i)"
print typename$(z2.real)="Double"
z5=FloatComplex(10,-5) : print z5.toString$="(10-5i)"
print typename$(z5.real)="Single"
z5=FloatComplex(10) :print z5.toString$="(10)"
z6=DoubleComplex() : print z6.toString$="(0)"
z6=z5 :print z6.toString$="(10)"
print z5 is type FloatComplex = true
print z6 is type DoubleComplex = true
z2.imaginary++
z2.imaginary++
print  z2.toString$="(-2+5i)"
z5=z2
print typename$(z5.real)="Single"
print z5 is type FloatComplex = true
z5.real++
print z5.toString$="(-1+5i)"
zArray=FloatComplex(1,1,10)
zArray(4)=FloatComplex(30,-5)
zArray(5)=FloatComplex(3,-75)
zArray(7)=zArray(4)
for i=zArray.Lbound to zArray.Ubound
print i, zArray.toString$(i)
next
z5=zArray(4)
print z5.toString$="(30-5i)"
print zArray(4).toString$ = zArray.toString$(4)
print  z5.toString$="(30-5i)"
zk=z5+zArray+FloatComplex(5, 100)
print zArray(4).toString$="(30-5i)"
print zk.tostring$()="(36+96i)"
zk=zArray
// print zk.ubound, zk.ptr, zArray.ptr, zArray.Ubound
zA=zArray.Copy() // copy 10 items
zArray(5)=FloatComplex(3, 4)
print zArray(5).toString$="(3+4i)"
print za(5).toString$="(3-75i)"
za(7)=zArray(5)+za(5)
print za(7).toString$="(6-71i)"
za(7)=za(7)-za(5)
print za(7).toString$="(3+4i)"
za(7)=za(7)-zArray(5)
print za(7).toString$="(0)"
z5.import z1.export$()
print z5.tostring$="(2+2i)"
zArray.import za.export$()
print zArray.toString$(7)="(0)"
print zArray.ptr<>za.ptr
print zArray.Ubound=9, z5.Ubound=0
zArray.SwapBuffers &z5 // swap data only
print zArray.Ubound=0, z5.Ubound=9, z5(5).toString$="(3-75i)"


Δεν υπάρχουν σχόλια:

Δημοσίευση σχολίου

You can feel free to write any suggestion, or idea on the subject.