1
### Complex.BC - Rudimentary complex number handling for GNU BC
3
## Not to be regarded as suitable for any purpose
4
## Not guaranteed to return correct answers
6
# Read a digit from the decimal representation of a number
7
# read_digit(3210.987, -1) returns 9 as that is the digit in
9
define read_digit(number, place) {
18
# MakeComplex: Turn two numbers into one by interleaving the digits
19
define makecomplex(r,i) {
20
auto c, rd, id, ri, ii, j, sign
28
if (r<0){r*=-1;sign+=2}
29
if (i<0){i*=-1;sign+=1}
36
for(j=-scale;j<ri;j++) {
49
# workhorse for real & imag
50
define realimag_(c,f) {
51
auto x, sign, cs, ci, j, os
53
cs = scale(c);ci = length(c)-cs-1
55
sign = read_digit(c,ci)
60
for(j=-scale;j*2<ci;j++) {
61
x += 10^j * read_digit(c,j*2+f)
64
if ( (sign == 2+f) || (sign == 4) )x*=-1
70
# Extract the real part of a generated complex number
75
# Extract the imaginary part of a generated complex number
80
# Print a generated complex number
81
# (normal print functions don't work on complex numbers)
87
if(i<0){print " -";i*=-1}else{print " +"}
92
## Basic math - ordinary bc operators don't work on these special
93
## interleaved complex numbers
95
# Add two complex numbers and return another complex number
97
return makecomplex(real(c1)+real(c2),imag(c1)+imag(c2))
100
# Subtract a complex number from another, returning complex
102
return makecomplex(real(c1)-real(c2),imag(c1)-imag(c2))
105
# Multiply two complex, return complex
112
return makecomplex(r1*r2-i1*i2, r2*i1+r1*i2)
115
# Calculates the absolute value of a complex number
116
# NB: returns a standard bc number and not a new fangled 'complex'
118
return sqrt(real(c)^2+imag(c)^2)
121
# Returns the complex conjugate of a complex number
122
# ...is faster than the hashed out return line
124
#return makecomplex(real(c), -imag(c))
125
return c - 2*10^(length(c)-scale(c)-1)
128
# Divide one complex by another, returning a third
136
return makecomplex((r1*r2+i1*i2)/aa, (r2*i1-r1*i2)/aa)
139
# Negate a complex number (i.e. multiply by -1)
140
# ...faster than cmul(c, makecomplex(-1,0))
141
# ...or the hashed out return line
144
# return makecomplex(-real(c), -imag(c))
145
t = length(c) - scale(c) - 1
146
sign = read_digit(c,t)
147
c += (5-2*sign)*(10^t)
151
## Basic Math II - fast[er] squaring, square roots and integer power
153
# Square a complex number
158
return makecomplex(r^2-i^2, 2*r*i)
161
# Find the primary square root of a complex number
167
return(makecomplex(sqrt(r),0))
169
return(makecomplex(0,sqrt(-r)))
171
sr = sqrt((sqrt(r^2+i^2)+r)/2)
173
return makecomplex(sr,si)
176
# subfunctions for use by cintpow
177
define mod(n,m) {auto s;s=scale;scale=0;n%=m;scale=s;return(n)}
178
define int(n) {auto s;s=scale;scale=0;n/=1;scale=s;return(n)}
180
# Raise a complex number [c] to an integer power [n]
181
# NB: n is a standard bc number and not a complex
182
define cintpow(c, n) {
186
if(n<0)return( cdiv(x,cintpow(c,-n)) )
189
if(n==2)return( csquare(c) )
192
x = cmul(x, c) ; n -= 1
193
#print "DEBUG: cintpow - odd_ (",n,")\n"
195
c = csquare(c) ; n = int(n/2)
196
#print "DEBUG: cintpow - even (",n,")\n"