Complex numbers (a library & demonstrations)


From original post by tenochtitlanuk:
  • Several of the group (myself, tsh & bluatigro especially) have found it useful to develop easy ways to handle complex numbers in a transparent way, where the real and imaginary parts are bound together by being part of a single string variable.

'
'   Complex  function library and demo
'
'   ComplexBluatigroJhf5.bas,
'   posted by tenochtitlanuk, modified by tsh73
'
'   To-dos:-
'       change to XOR plotting the vector so it can be erased.                          DONE    18/09/2010
'       add buttons to draw families of say ( 1, zero degrees) to ( 1, 360 degrees)
'       add screen-print
'       function complexFromStr$(a$) should work as Val(): read from the start of string and stop on first invalid symbol
'           For now, it starts from behind and looks for separator of Real and Imaginary parts
'           (works the same for correct representation, but behaves differently for wrong ones)
 
'   Demos of usage in mainwin
 
mainwin 130 20
 
print
print " I will first demonstrate some of the functions."
print
 
print " Printing a complex constant with real & imag spec'd.",
print "complex$( 0, -1)",,
call cprint complex$( 0, -1)
 
'   print a complex number whose components are variables
real =3: imag =4
print " Printing a complex variable.",,
print "real =3: imag =4: complex$( real, imag)",
call cprint complex$( real, imag)
 
'   print absolute value of a complex number
print " Printing magnitude of a complex number.",,
print "cabs( complex$( -3, 5))",,
print cabs( complex$( -3, 5))
 
'   print direction of complex vector in Argand plane
real =4: imag =4
print " Direction of a complex number vector.",,
print "real =4: imag =4: atan2( imag, real)",
print atan2( imag, real); " radians"
 
'   print inverse of a complex number
print " Printing inverse of a complex number.",,
print "cinv$( complex$( 4, -3))",,
call cprint cinv$( complex$( 4, -3))
 
'   print sum of two complex numbers
print " Printing sum of 2 complex numbers.",,
print "cadd$( complex$( 3, 2), complex$( 0, 1))",
call cprint cadd$(   complex$( 3, 2), complex$( 0, 1))
 
'   print difference of two complex numbers
print " Printing difference of two complex numbers.",
print "csub$( complex$( 3, 2), complex$( 0, 1))",
call cprint csub$(   complex$( 3, 2), complex$( 0, 1))
 
'   print product of two complex numbers
print " Printing product of two complex numbers.",
print "cmulti$( complex$(3, 2), complex$(0, 1))",
call cprint cmulti$( complex$( 3, 2), complex$( 0, 1))
 
'   print quotient of two complex numbers
print " Printing quotient of two complex numbers.",
print "cdiv$( complex$( 3, 2), complex$( 0, 1))",
call cprint cdiv$(   complex$( 3, 2), complex$( 0, 1))
 
'   print square root of two complex numbers
print " Printing square root of a complex number.",
print "csqr$( complex$( 4, -4))",,
call cprint csqr$(    complex$( 4, -4))
 
'   print e to a complex value
print " Printing 'e' raised to a complex power.",,
print "cexp$( complex$( 4, -4))",,
call cprint cexp$(    complex$( 4, -4))
 
'   print natural log of a complex number
print " Printing natural ln of a complex number.",
print "cln$( complex$( 4, -4))",,
call cprint cln$(     complex$( 4, -4))
 
print
print " Now I'll open a graphic window demonstration."
 
timer 5000, [j]
wait
[j]
timer 0
 
'   _____________________________________________
'   Demos of usage in graphic windows & boxes.
 
UpperLeftX   = 10
UpperLeftY   = 50
WindowWidth  =870
WindowHeight =500
 
graphicbox #w.g1,    10,  10, 400, 400
textbox    #w.tb1,   20, 420, 200,  30
 
button     #w.b1, "Show Vector", [show],     LR, 510, 18
button     #w.b2, "Random",      [Generate], LR, 570, 18
 
statictext #w.st1 "", 440,  10, 420, 430
 
open "Complex library demos" for window as #w
 
#w "trapclose [quit]"
 
#w.tb1 "!font courier 16 bold"
rndComplex$=complex$(int(11 *rnd( 1)) -5, int( 11 *rnd( 1)) -5)
#w.tb1 formatCompl$(rndComplex$)
 
#w.st1 "!font arial 12"
 
#w.g1  "color darkblue ; home ; down ; size 2"
#w.g1 "circle "; 4
for r =1 to 7
    #w.g1 "circle "; r *40
next r
 
#w.g1 "color cyan"
for x =-5 to 5
    #w.g1 "up ;   goto "; 199 +x *40; "   0"
    #w.g1 "down ; goto "; 199 +x *40; " 400"
next x
 
#w.g1 "color darkgray"
for y =-5 to 5
    #w.g1 "up ;   goto   0 "; 199 -y *40
    #w.g1 "down ; goto 400 "; 199 -y *40
next y
 
st$ =""
for j =1 to 24
    read txt$
    st$ =st$ +txt$ +chr$( 13)
next j
 
#w.st1 st$
 
#w.g1 "up ; goto 400 200 ; size 4 ; color green ; size 4 ; down ; goto 204 200 ; up ; color red ; size 6 ; flush"
'   _____________________________________________
 
wait
 
[show]
#w.tb1 "!contents? complex$"
cEntered$=complexFromStr$(complex$)
r =val( word$( cEntered$, 1))
i =val( word$( cEntered$, 2))
#w.g1, "rule XOR"
#w.g1 "goto 198 199 ; down ; goto "; 198 +r *40; " "; 199 -i *40
timer 1000, [jf]
wait
[jf]
timer 0
#w.g1, "goto 198 199"
wait
 
[Generate]
rndComplex$=complex$(int(11 *rnd( 1)) -5, int( 11 *rnd( 1)) -5)
#w.tb1 formatCompl$(rndComplex$)
wait
 
[quit]
close #w
 
end
 
data "      You are looking at an 'Argand Diagram'."
data ""
data "The rectangular grid show x and y between +5 and -5."
data "The circles show radii up to 7 from the center origin."
data ""
data "Complex numbers are entered as"
data " Re+Imi or Re-Imi (there Im is number and final 'i' is letter)"
data " You can enter just Re or Imi. No spaces inside please."
data ""
data "A valid entry could be         3+2i"
data "         representing 3 right and 2 up,"
data "         or         -3-3i    ( 3 left, 3 down)"
data "A random example will be showing in the text-box."
data "Click the 'Show' button to see it as a vector,"
data ""
data "The green line shows the positive, real direction."
data "Angles are measured anti-clockwise from here."
data "The red line which appears represents your complex no."
data ""
data "Click <Random> for a new random vector."
data ""
data "NB You can alter it to your own vector in the stated format."
data "Decimal values as well as integers are allowed."
data "You can even use exponential form (1.2e3)."
 
'   _____________________________________________
'   **************** THE LIBRARY ****************
'   _____________________________________________
 
sub cprintOld cx$
    print "( "; word$( cx$, 1); " + i *"; word$( cx$, 2); ")"
end sub
 
function formatCompl$(cx$)
    Re = val(word$( cx$, 1))
    Im = val(word$( cx$, 2))
    if Re=0 and Im=0 then  formatCompl$ = "0": exit function
    Re$ = word$( cx$, 1)
    if Re =0 then Re$=""    'and no next "+"
    Im$=str$(Im)+"i"
    if Im =0 then Im$=""
    formatCompl$ = Re$+ iif$(Im>0 and Re<>0, "+", "")+ Im$
end function
 
sub cprint cx$
    print formatCompl$(cx$)
end sub
 
function iif$(test, valYes$, valNo$)
    iif$ =  valNo$
    if test then iif$ =  valYes$
end function
 
function complexFromStr$(a$)
    a$=trim$(a$)
    if right$(a$,1)<>"i" then   'consider thing real
        Re=val(a$)
        complexFromStr$=complex$(Re,0)
        exit function
    end if
    'else we probably have real and imaging parts
    'they could be divided by + or -. Only trouble is to check for exponential form.
    'Because it could quite legitimately look like this: "-12E-4-2e-4i"
    'go from the back('cause we know Im part is definitely here)
    a$=left$(a$, len(a$)-1)
    expFound=0
    divPos=0
    for i = len(a$) to 1 step -1
        c$=mid$(a$, i,1)
        if instr("+-",c$)=0 then
            'do nothing
        else
            if expFound =0 then 'there was not exponent found before
            'we should check if it's part of exponent: lookahead
                prevC$=mid$(a$, i-1,1)
                if instr("eE",prevC$)<>0 then 'indeed part of exponent
                    'do nothing
                else    'we just found divider. We will not bother more and assign all before divider to Re$
                    divPos = i: exit for
                end if
            else
            'found divider
                divPos = i: exit for
            end if
        end if
    next
    'divide by divPos
    Re$=left$(a$,divPos-1)
    Im$=mid$(a$,divPos)
    print Re$, Im$
    complexFromStr$=complex$(val(Re$),val(Im$))
end function
 
function atan2( y, x)
    pi = acs(-1)
    if y =0  and x =0 then notice "atan2( 0,0) undefined": end
    if y >=0 and x <0 then at =atn( y /x) +pi: goto [j]
    if y <0  and x <0 then at =atn( y /x) -pi: goto [j]
    if y >0  and x =0 then at =    pi /2:      goto [j]
    if y <0  and x =0 then at = 0 -pi /2:      goto [j]
    if x >0           then at =atn( y /x)
    [j]
    atan2 =at
end function
 
 function complex$( a , bj )
''complex number string-object constructor
  complex$ = str$( a ) ; " " ; str$( bj )
end function
 
function cadd$( a$ , b$ )
  ar = val( word$( a$ , 1 ) )
  ai = val( word$( a$ , 2 ) )
  br = val( word$( b$ , 1 ) )
  bi = val( word$( b$ , 2 ) )
  cadd$ = complex$( ar + br , ai + bi )
end function
 
function csub$( a$ , b$ )
  ar = val( word$( a$ , 1 ) )
  ai = val( word$( a$ , 2 ) )
  br = val( word$( b$ , 1 ) )
  bi = val( word$( b$ , 2 ) )
  csub$ = complex$( ar - br , ai - bi )
end function
 
function cmulti$( a$ , b$ )
  ar = val( word$( a$ , 1 ) )
  ai = val( word$( a$ , 2 ) )
  br = val( word$( b$ , 1 ) )
  bi = val( word$( b$ , 2 ) )
  cmulti$ = complex$( ar * br - ai * bi _
                    , ar * bi + ai * br )
end function
 
function cdiv$( a$ , b$ )
  ar = val( word$( a$ , 1 ) )
  ai = val( word$( a$ , 2 ) )
  br = val( word$( b$ , 1 ) )
  bi = val( word$( b$ , 2 ) )
  cdiv$ = complex$((ar*br+ai*bi)/(br*br+bi*bi) _
                  ,(br*ai-ar*bi)/(br*br+bi*bi))
end function
 
function cabs( a$ )
  ar = val( word$( a$ , 1 ) )
  ai = val( word$( a$ , 2 ) )
  cabs = sqr( ar ^ 2 + ai ^ 2 )
end function
 
function csqr$( a$ )
  ar = val( word$( a$ , 1 ) )
  ai = val( word$( a$ , 2 ) )
  ha = sqr((ar+cabs(a$))/2)
  hb = 2*sqr((ar+cabs(a$))/2)
  hb = ai / hb
  csqr$ = complex$( ha , hb )
end function
 
function cexp$( a$ )
  ar = val( word$( a$ , 1 ) )
  ai = val( word$( a$ , 2 ) )
  ha = exp( ar ) * cos( ai )
  hb = exp( ar ) * sin( ai )
  cexp$ = complex$( ha , hb )
end function
 
function cln$( a$ )
  ar = val( word$( a$ , 1 ) )
  ai = val( word$( a$ , 2 ) )
  cln$ = complex$( log( cabs( a$) ) _
       , atn( ai / ar ) )
end function
 
function cinv$( a$)
  ar = val( word$( a$ , 1 ) )
  ai = val( word$( a$ , 2 ) )
  D =ar^2 +ai^2
  cinv$ =complex$( ar /D , 0 -ai /D )
end function