Overview
This topic details the design of complex numbers in
CommonLisp.
Wikipedia defines a complex number to be "a number of the for
a + bi where
a and
b are real numbers and
i is the imaginary unit, with the property
i^2 = -1." The implementation of complex numbers in
CLforJava requires a new data type, complex, changes to the Reader and Printer, augmentation of existing arithmetic functions, and creation of new math functions.
#Tree
Inheritance Tree
The following is the hierarchical portion of the
TypeSystem that contains the type Complex:
Implementation
This section contains the implementation details of the type, augmentation of existing arithmetic functions, creation of new arithmetic functions, and changes to the Reader and Writer in order to provide for the addition of the complex number type.
Analysis of Implementation Candidates
Grading Scale
| Categories |
A |
B |
C |
F |
| License |
Free to use and redistribute with no permissions needed |
Free to use and redistribute, but written permission required first |
GNU |
Royalty fees |
| Clarity |
Code is well documented, uses javadoc, has descriptive variable names, solution is simple |
Has good documentation, doesn't use javadoc, has descriptive variable names,solution is simple |
Has documentation but isn't good, uses javadoc, poor variable names, solution is simple |
Has no documentation, doesn't use javadoc, poor variable names, stylistic issues |
| Completeness |
Missing 1 function at the most |
Missing 2-4 functions |
Missing 4-6 functions |
Missing more than 6 functions |
| Correctness |
All functions and work |
All functions work but a bug was found and easily fixed in code |
Only 1 function implemented incorrectly |
More than 1 function has errors |
| Speed |
N/A |
N/A |
N/A |
N/A |
Analysis
| Candidates |
Clarity |
Completeness |
Licensure |
Correctness |
Speed* |
Comments |
| 1 |
B |
C |
A |
B |
A |
Doesn't have overloaded functions |
| 2 |
C |
F |
A |
A |
A |
Bad variable names, doesn't have "equals", and doesn't have overloaded functions |
| 3 |
C |
C |
A |
A |
A |
Doesn't use javadoc, hard to read, doesn't have overloaded functions |
| 4 |
F |
B |
A |
A |
A |
bad variable names, real and image variables are public, bad documentation, no overloaded functions, tough to read |
| 5 |
F |
A |
C |
N/A |
N/A |
doesn't have overloaded functions, no javadoc, no comments, need to import their package, GNU license |
| 6 |
A |
A |
A |
A |
A |
good documentation, uses javadoc, has overloaded functions, complete |
* Speed test consisted of 1,000,000 calls to each of the functions in each of the candidate implementations that we have considered, except candidate implementation 5 as it would have been extremely time consuming to write a test for that particular implementation. As such, the team decided that we would not conduct a speed test on that specific implementation. The results of the speed tests can be found
here.
Function Checklist
* - Indicates that this function is included in this implementation.
X - Indicates that this is the implementation we have chosen to incorporate into
CLforJava.
| Function |
6 |
1 |
2 |
3 |
4 |
5 |
Comments |
HyperSpec |
| abs |
* |
|
|
X |
* |
* |
Completed |
* |
| acos |
X |
|
|
|
|
|
Completed |
* |
| acosh |
X |
|
|
|
|
|
Completed |
* |
| asin |
X |
|
|
|
|
|
Completed |
* |
| asinh |
X |
|
|
|
|
|
Completed |
* |
| atan |
X |
|
|
|
* |
|
Completed |
* |
| atanh |
X |
|
|
|
* |
|
Completed |
* |
| conjugate |
X |
|
* |
* |
* |
|
Completed |
* |
| cos |
* |
|
X |
|
* |
|
Completed |
* |
| cosh |
* |
|
X |
|
|
|
Completed |
* |
| equal |
X |
* |
|
* |
* |
* |
Completed |
* |
| exp |
X |
|
* |
* |
* |
|
Completed |
* |
| imagpart |
X |
* |
* |
|
* |
* |
Completed |
* |
| Zerop |
|
|
|
|
|
|
Completed |
* |
| log |
X |
|
* |
* |
* |
|
Completed |
* |
| minus |
X |
* |
* |
* |
* |
* |
Completed |
* |
| negative |
X |
|
* |
|
* |
|
Completed |
* |
| div |
X |
* |
* |
* |
* |
* |
Completed |
* |
| plus |
X |
* |
* |
* |
* |
* |
Completed |
* |
| expt |
X |
|
|
* |
* |
|
Completed |
* |
| realpart |
X |
* |
* |
* |
* |
* |
Completed |
* |
| sin |
* |
|
X |
* |
* |
|
Completed |
* |
| sinh |
* |
|
X |
* |
* |
|
Completed |
* |
| sqrt |
X |
|
* |
* |
* |
|
Completed |
* |
| tan |
X |
|
* |
|
* |
|
Completed |
* |
| tanh |
X |
|
|
|
* |
|
Completed |
* |
| mult |
X |
* |
* |
* |
* |
* |
Completed |
* |
| toString |
* |
* |
* |
|
* |
* |
Completed |
* |
| oneplus |
|
|
|
|
|
* |
Completed |
* |
| oneminus |
|
|
|
|
|
* |
Completed |
* |
| Complexp |
|
|
|
|
|
|
Completed |
* |
| complex |
|
|
|
|
|
|
Completed |
* |
| cis |
|
|
|
|
|
|
Completed |
* |
| phase |
|
|
|
|
|
|
Completed |
* |
Type Specification (lisp.common.type.Complex)
The type specification must contain the following:
- An instance of the symbol COMPLEX.
- An implementing class with the following:
- A real number representing the real part of a complex number.
- A number representing the imaginary part of a complex number.
- A nested Factory Class.
- Method signatures for new arithmetic functions.
Type Promotion / Demotion
"If all the arguments are the same type of number (rational, floating point, or complex), the result will be the same type except in the case where the result of an operation on complex numbers with rational components yields a number with a zero imaginary part, in which case the result will be a rational. However, floating-point and complex numbers are
contagious--if all the arguments are reals but one or more are floating-point numbers, the other arguments are converted to the nearest floating-point arguments. Floating-point numbers in a "smaller" representation are also converted to the larger representation. Similarly, if any of the arguments are complex, any real arguments are converted to the complex arguments." --
Practical Common Lisp by Peter Seibel
Arithmetic Functions
Plus (lisp.common.function.Plus)
public Number Plus(Complex arg) (
More Info)
Input: Complex
Output: Number
Synopsis: If only one argument is given, then the complex number is added to 0 and then returned. Type Promotion / Demotion applies here.
>(+ #C(1 2))
#C(1 2)
public Number Plus(Complex arg1, Complex arg2) (
More Info)
Input: Complex, Complex
Output: Number
Synopsis: When two complex numbers are passed, the real parts and the imaginary parts are added. Type promotion/demotion applies here.
>(+ #C(1 2) #C(3 4))
#C(4 6)
public Number Plus(Complex arg1, Real arg2) (
More Info)
Input: Complex, Real
Output: Number
Synopsis: If the Complex number and a Real number are passed as parameters, then the real is added to the real part of the Complex. Type promotion/demotion applies here.
>(+ #C(1 2) 3)
#C(4 2)
Minus (lisp.common.function.Minus)
public Number Minus(Complex arg) (
More Info)
Input: Complex
Output: Number
Synopsis: If only a Complex number passed then it is subtract from 0. Type promotion/demotion applies here.
>(- #C(1 2))
#C(-1 2)
public Number Minus(Complex arg1, Complex arg2) (
More Info)
Input: Complex, Complex
Output: Number
Synopsis: If a complex is passed, the real parts and the imaginary parts are resolved. Type promotion/demotion applies here.
>(- #C(1 2) #C(3 4))
#C(-2 -2)
public Number Minus(Complex arg1, Real arg2) (
More Info)
Input: Complex, Real
Output: Number
Synopsis: If a Complex number and a Real number are passed, the then real part of the Complex number is subtracted by the real argument. Type promotion/demotion applies here.
>(- #C(1 2) 3)
#C(-2 2)
Mult (lisp.common.function.Mult)
public Number Mult(Complex arg1, Complex arg2) (
More Info)
Input: Complex, Complex
Output: Number
Synopsis: When two Complex numbers are inputted, the foil method is applied to the real and imaginary parts of both Complex numbers.
>(* #C(1 2) #C(3 4))
#C(-5 10)
public Number Mult(Complex arg1, Real arg2) (
More Info)
Input: Complex, Real
Output: Number
Synopsis: When a Complex and a Real are inputted, both the real and imaginary parts of the Complex number are multiplied by the Real number.
>(* #C(3.0 2.0) 3)
#C(9.0 6.0)
Div (lisp.common.function.Div)
public Complex Div(Complex arg1, Complex arg2) (
More Info)
Input: Complex, Complex
Output: Number
Synopsis: Returns a new Complex number with the real part being equal to the sum of the multiplication of the two real parts and the multiplication of the two imaginary parts all over the sum of arg2's real part squared and arg2's imaginary part squared.
>(/ #C(3.0 1.0) #C(2.0 1.0))
#C(1.4 -0.2)
public Complex Div(Complex arg1, Real arg2) (
More Info)
Input: Complex, Real
Output: Number
Synopsis: Divides the real and imaginary parts of the Complex number by the real number.
>(/ #C(3.0 1.0) 2)
#C(0.6 0.2)
Oneplus (lisp.common.function.Oneplus)
public Complex Oneplus(Complex arg) (
More Info)
Input: Complex
Output: Number
Synopsis: Increments the real number by 1.
>(1+ #C(3.0 1.0))
#C(4.0 1.0)
Oneminus (lisp.common.function.Oneminus)
public Complex Oneminus(Complex arg) (
More Info)
Input: Complex
Output: Number
Synopsis: Decrements the real number by 1.
>(1- #C(3.0 1.0))
#C(2.0 1.0)
Exponential, Logarithmic, and Trigonometric functions
Abs (lisp.common.function.Abs)
public Number Abs(Complex arg) (
More Info)
Input: Complex
Output: Number
Synopsis: Returns the absolute value of number.
>(abs #C(3.0 1.0))
3.1622777
Acos (lisp.common.function.Acos)
public Number Acos(Complex arg) (
More Info)
Input: Complex
Output: Number
Synopsis: Returns the arc cosine of the input in radians.
>(acos #C(3.0 1.0))
#C(0.3377011 -1.8241987))
Acosh (lisp.common.function.Acosh)
public Number Acosh(Complex arg) (
More Info)
Input: Complex
Output: Number
Synopsis: Returns the hyperbolic arc cosine of the input in radians.
>(acosh #C(3.0 1.0))
#C(1.8241987 0.3377011)
Asin (lisp.common.function.Asin)
public Number Asin(Complex arg) (
More Info)
Input: Complex
Output: Number
Synopsis: Returns the arc sine of the input in radians.
>(asin #C(3.0 1.0))
#C(1.2330952 1.8241987)
Asinh (lisp.common.function.Asinh)
public Number Asinh(Complex arg) (
More Info)
Input: Complex
Output: Number
Synopsis: Returns the hyperbolic arc sine of the input in radians.
>(asinh #C(3.0 1.0))
#C(1.8641615 0.30760366)
Atan (lisp.common.function.Atan)
public Number Atan(Complex arg) (
More Info)
Input: Complex
Output: Number
Synopsis: Returns the arc tangent of the input in radians.
>(atan #C(3.0 1.0))
#C(1.276795 0.091931194)
Atanh (lisp.common.function.Atanh)
public Number Atanh(Complex arg) (
More Info)
Input: Complex
Output: Number
Synopsis: Returns the hyperbolic arc tangent of the input in radians.
>(atanh #C(3.0 1.0))
#C(0.30594385 1.4614619)
Cis (lisp.common.function.Cis)
public Complex Cis(Number arg) (
More Info)
Input: Number
Output: Number
Synopsis: Returns a complex with the value of e^i* radians. The real part is equal to the cosine of radians, and the imaginary part is equal to the sine of radians.
>(cis 0)
#C(1.0 0.0)
>(cis 3.14)
#C(-0.99999875 0.001592548)
Cos (lisp.common.function.Cos)
public Number Cos(Complex arg) (
More Info)
Input: Complex
Output: Number
Synopsis: Returns the cosine of the input in radians.
>(cos #C(3.0 1.0))
#C(-1.5276383 -0.1658444)
Cosh (lisp.common.function.Cosh)
public Number Cosh(Complex arg) (
More Info)
Input: Complex
Output: Number
Synopsis: Returns the hyperbolic cosine of the input in radians.
>(cosh #C(3.0 1.0))
#C(5.439581 8.42975)
Exp (lisp.common.function.Exp)
public Number Exp(Complex arg) (
More Info)
Input: Complex
Output: Number
Synopsis: Returns the constant e raised to a power.
>(exp #c(3.0 1.0))
#C(10.852262 16.901396)
Expt (lisp.common.function.Expt)
public Number Expt(Number arg1, Number arg2) (
More Info)
Input: Number, Number
Output: Complex
Synopsis: Returns arg1 raised to the power arg2 where expt is defined as b^x = e^{x log b\/}.
>(expt #c(3.0 1.0) 3)
#C(18.0 26.0)
Log (lisp.common.function.Log)
public Number Log(Number number, [Number base]) (
More Info)
Input: A non-zero Number and an optional base (Number)
Output: A number
Synopsis: Returns the log of the number
>(log #c(1 2))
#C(0.804719 1.1071488)
Phase (lisp.common.function.Phase)
public Number Phase(Complex arg) (
More Info)
Input: Complex
Output: Number
Synopsis: Returns the phase (the angle part of its polar representation) of the input in radians.
>(expt #c(3.0 1.0) 3)
#C(18.0 26.0)
Signum (lisp.common.function.Signum)
public Complex Signum(Complex arg) (
More Info)
Input: Complex
Output: Number
Synopsis: Returns a numerical value that indicates whether number is negative, zero, or positive.
>(signum #c(3.0 1.0))
#C(0.94868327 0.31622776)
>(signum #c(-3.0 1.0))
#C(-0.94868327 0.31622776)
>(signum #c(-3.0 -1.0))
#C(-0.94868327 -0.31622776)
>(signum #c(3.0 -1.0))
#C(0.94868327 -0.31622776)
Sin (lisp.common.function.Sin)
public Number Sin(Complex arg)(
More Info)
Input: Complex
Output: Number
Synopsis: Returns the sine of the input in radians.
>(sin #C(3.0 1.0))
#C(0.21775955162215221 -1.1634403637032504)
Sinh (lisp.common.function.Sinh)
public Number Sinh(Complex arg) (
More Info)
Input: Complex
Output: Number
Synopsis: Returns the hyperbolic sine of the input in radians.
>(sinh #C(3.0 1.0))
#C(5.412680923178194 8.47164545430015)
Sqrt (lisp.common.function.Sqrt)
public Number Sqrt(Complex arg) (
More Info)
Input: Complex
Output: Number
Synopsis: Returns the square root of the input.
>(sqrt #c(0 2))
#C(1.0 1.0)
Tan (lisp.common.function.Tan)
public Number Tan(Complex arg)(
More Info)
Input: Complex
Output: Number
Synopsis: Returns the tangent of the input in radians.
>(tan #C(3.0 1.0))
#C(-0.05916853956605075 0.7680176472869111)
Tanh (lisp.common.function.Tanh)
public Number Tanh(Complex arg) (
More Info)
Input: Complex
Output: Number
Synopsis: Returns the hyperbolic tangent of the input in radians.
>(tanh #C(3.0 1.0))
#C(1.0020549882458119 0.00451713737276658315)
Comparison and Predication Functions
Equal (lisp.common.function.Equal)
public Boolean Equal(Complex arg) (
More Info)
Checks for the equality of multiple complex numbers by comparing the real and imaginaries parts.
Input: Number
Output: Boolean
>(= #C(1.0 2) #C(1 2))
NIL
>(= #C(1 0) #C(1 0.0))
T
>(= #C(1 2) #C(1 2))
T
>(= (* #C(2 1) 3) #C(6 3))
T
Zerop (lisp.common.function.Zerop)
public Boolean Zerop(Complex arg) (
More Info)
Input: Complex
Output: Boolean
Synopsis: Returns true if number is zero (integer, float, or complex); otherwise, returns false.
>(zerop #C(3.0 1.0))
NIL
>(zerop #C(0.0 0.0))
T
Complex Specific Functions
Complex (lisp.common.type.Complex)
public Number Complex(Real arg) (
More Info)
Input: Real
Output: Number
Synopsis: Receives one number as a parameter and returns a complex number type.
>(complex 3.0)
#C(3.0 0.0)
Complex (lisp.common.type.Complex)
public Number Complex(Real arg1, Real arg2) (
More Info)
Input: Real, Real
Output: Number
Synopsis: Receives two numbers as parameters and returns a complex number type.
>(complex 1 1)
#C(1 1)
Complexp (lisp.common.function.Complexp)
public Boolean Complexp(Number arg) (
More Info)
Input: Number
Output: Boolean
Synopsis: Returns T if a number is of complex type and NIL if otherwise.
>(complexp #C(1 1))
T
>(complexp 1)
NIL
>
RealPart? (lisp.common.function.RealPart)
public Real RealPart? (Number arg) (
More Info)
Input: Number
Output: Real
Synopsis: Receives a number as a parameter and returns the real part if the arg is of type Complex, or returns the number if the arg is of type Real.
>(realpart #C(1 2))
1
>(realpart 1)
1
ImagPart? (lisp.common.function.ImagPart)
public Real ImagPart? (Number arg) (
More Info)
Input: Number
Output: Real
Synopsis: Receives a number as a parameter and returns the imaginary part if the arg is of type Complex, or returns ZERO if the arg is of type Real.
>(imagpart #C(1 2))
2
>(imagpart 1)
0
Conjugate (lisp.common.function.Conjugate)
public Number Conjugate(Complex arg) (
More Info)
Input: Complex
Output: Number
Synopsis: Returns the complex conjugate of number. The conjugate of a real number is itself.
>(conjugate #C(3.0 1.0))
#C(3.0 -1.0)
Augmentation to the Reader
The Reader will import the lisp.common.type.Complex. A Read Macro will be created called
SharpCeeMacro? .java. These classes will allow
CLforJava to recognize complex numbers. Complex numbers are notated with a #C followed by a list of two arguments whose type is Real.
>#c(1 1)
#C(1 1)
Augmentation to the Printer
The Printer will print complex numbers as a list of two numbers whose type is Real preceded by the #C. Promotion/demotion applies where necessary.
>#c(1 1)
#C(1 1)
Current Status: Complex numbers were successfully implemented in Spring 2007. This implementation includes the type, functions, augmentation to the reader and to the printer. The test suite still needs to have tests written for each of the functions that support complex numbers.
Status History:
See Complex Numbers Group
Test Suites
Links to JUnit results
References
--
JerryBoetje - 12 Jul 2003