# http://mathling.com/core/complex/vector  library module

http://mathling.com/core/complex/vector

Complex numbers (vector implementation)

November 2022
Status: Stable

### Imports

http://mathling.com/core/utilities
```import module namespace util="http://mathling.com/core/utilities"
at "../core/utilities.xqy"```
http://mathling.com/core/vector
```import module namespace v="http://mathling.com/core/vector"
at "../core/vector.xqy"```
http://mathling.com/core/config
```import module namespace config="http://mathling.com/core/config"
at "../core/config.xqy"```
http://mathling.com/core/errors
```import module namespace errors="http://mathling.com/core/errors"
at "../core/errors.xqy"```
http://mathling.com/geometric/point
```import module namespace point="http://mathling.com/geometric/point"
at "../geo/point.xqy"```

### Functions

#### ```Function: complexdeclare function complex(\$real as xs:double, \$imaginary as xs:double) as xs:double*```

complex()
Construct a new complex number.

##### Params
• real as xs:double: the real part of the number
• imaginary as xs:double: the imaginary part of the number
##### Returns
• xs:double*: complex number
```declare function this:complex(
\$real as xs:double,
\$imaginary as xs:double
) as xs:double*
{
(\$real, \$imaginary)
}```

#### `Function: as-complexdeclare function as-complex(\$real as xs:double) as xs:double*`

as-complex()
Cast a real number to a complex.

##### Params
• real as xs:double: the real part of the number
##### Returns
• xs:double*: complex number
```declare function this:as-complex(
\$real as xs:double
) as xs:double*
{
(\$real, 0)
}```

#### `Function: is-realdeclare function is-real(\$z as xs:double*) as xs:boolean`

is-real()
Test whether the number has no imaginary part. (Within ε).

##### Params
• z as xs:double*: the complex number
##### Returns
• xs:boolean: true if complex number has only a real part
```declare function this:is-real(
\$z as xs:double*
) as xs:boolean
{
abs(this:pi(\$z)) < \$config:ε
}```

#### `Function: as-realdeclare function as-real(\$z as xs:double*) as xs:double`

as-real()
Cast a complex number to a double, if possible. Raises error if not.

##### Params
• z as xs:double*: the complex number
##### Returns
• xs:double: double
```declare function this:as-real(
\$z as xs:double*
) as xs:double
{
if (this:is-real(\$z)) then this:pr(\$z)
else errors:error("UTIL-CAST", (\$z,'complex'))
}```
##### Errors

UTIL-CAST if there is an imaginary part

#### ```Function: complex-rφddeclare function complex-rφd(\$r as xs:double, \$φ as xs:double) as xs:double*```

complex-rφd()
Construct a new complex number using radius and phase angle
(polar repesentation re^iφ).

##### Params
• r as xs:double: modulus of complex number
• φ as xs:double: angle of complex number (degrees)
##### Returns
• xs:double*: complex number
```declare function this:complex-rφd(
\$r as xs:double,
\$φ as xs:double
) as xs:double*
{
return
(\$r * math:cos(\$φR), \$r * math:sin(\$φR))
}```

#### ```Function: complex-rφdeclare function complex-rφ(\$r as xs:double, \$φ as xs:double) as xs:double*```

complex-rφ()
Construct a new complex number using radius and phase angle
(polar repesentation re^iφ).

##### Params
• r as xs:double: modulus of complex number
• φ as xs:double: angle of complex number (radians)
##### Returns
• xs:double*: complex number
```declare function this:complex-rφ(
\$r as xs:double,
\$φ as xs:double
) as xs:double*
{
(\$r * math:cos(\$φ), \$r * math:sin(\$φ))
}```

#### `Function: prdeclare function pr(\$z as xs:double*) as xs:double`

pr()
Accessor for real part of the complex number.

##### Params
• z as xs:double*: the complex number
##### Returns
• xs:double: raw real part
```declare function this:pr(\$z as xs:double*) as xs:double
{
v:px(\$z)
}```

#### `Function: pideclare function pi(\$z as xs:double*) as xs:double`

pi()
Accessor for imaginary part of the complex number.

##### Params
• z as xs:double*: the complex number
##### Returns
• xs:double: raw imaginary part
```declare function this:pi(\$z as xs:double*) as xs:double
{
v:py(\$z)
}```

#### `Function: rdeclare function r(\$z as xs:double*) as xs:integer`

r()
Accessor for real part of the complex number, as integer.

##### Params
• z as xs:double*: the complex number
##### Returns
• xs:integer: real part, rounded
```declare function this:r(\$z as xs:double*) as xs:integer
{
v:x(\$z)
}```

#### `Function: ideclare function i(\$z as xs:double*) as xs:integer`

i()
Accessor for imaginary part of the complex number, as integer.

##### Params
• z as xs:double*: the complex number
##### Returns
• xs:integer: imaginary part, rounded
```declare function this:i(\$z as xs:double*) as xs:integer
{
v:y(\$z)
}```

#### ```Function: adddeclare function add(\$z1 as xs:double*, \$z2 as xs:double*) as xs:double*```

##### Params
• z1 as xs:double*: one complex number
• z2 as xs:double*: other complex number
##### Returns
• xs:double*: z1+z2
```declare function this:add(
\$z1 as xs:double*,
\$z2 as xs:double*
) as xs:double*
{
}```

#### `Function: sumdeclare function sum(\$zs as xs:double*) as xs:double*`

sum()
Add several complex numbers in one go.

##### Params
• zs as xs:double*
##### Returns
• xs:double*
```declare function this:sum(
\$zs as xs:double*
) as xs:double*
{
sum(for \$i in 1 to count(\$zs) idiv 2 return \$zs[2*\$i - 1]),
sum(for \$i in 1 to count(\$zs) idiv 2 return \$zs[2*\$i])
}```

#### ```Function: subdeclare function sub(\$z1 as xs:double*, \$z2 as xs:double*) as xs:double*```

sub()
Subtract one complex numbers from another.

##### Params
• z1 as xs:double*: the first complex number
• z2 as xs:double*: the complex number to subtract from the first complex number
##### Returns
• xs:double*: z1-z2
```declare function this:sub(
\$z1 as xs:double*,
\$z2 as xs:double*
) as xs:double*
{
\$z1=>v:sub(\$z2)
}```

#### `Function: minusdeclare function minus(\$z as xs:double*) as xs:double*`

minus()
Negation

##### Params
• z as xs:double*1 the first complex number
##### Returns
• xs:double*: -z1
```declare function this:minus(
\$z as xs:double*
) as xs:double*
{
\$z=>this:times(-1)
}```

#### ```Function: multiplydeclare function multiply(\$z1 as xs:double*, \$z2 as xs:double*) as xs:double*```

multiply()
Multiply two complex numbers.

##### Params
• z1 as xs:double*: one complex number
• z2 as xs:double*: other complex number
##### Returns
• xs:double*: z1*z2
```declare function this:multiply(
\$z1 as xs:double*,
\$z2 as xs:double*
) as xs:double*
{
(: (a + bi)*(c + di) = (ac - bd) + (ad + bc)i :)
(
this:pr(\$z1)*this:pr(\$z2) - this:pi(\$z1)*this:pi(\$z2),
this:pr(\$z1)*this:pi(\$z2) + this:pi(\$z1)*this:pr(\$z2)
)
}```

#### ```Function: powdeclare function pow(\$z as xs:double*, \$pow as xs:integer) as xs:double*```

pow()
Raise a complex number to the given (positive integer) power.
A convenience function for repeated multiplication. For general powers use ppow()

##### Params
• z as xs:double*: the complex number
• pow as xs:integer: the power to raise it to
##### Returns
• xs:double*: z^pow
```declare function this:pow(
\$z as xs:double*,
\$pow as xs:integer
) as xs:double*
{
if (this:pi(\$z)=0) then this:complex(math:pow(this:pr(\$z), \$pow), 0)
else
switch (\$pow)
case 0 return \$this:one
case 1 return \$z
case 2 return \$z=>this:multiply(\$z)
case 3 return \$z=>this:multiply(\$z)=>this:multiply(\$z)
default return
(: General:
: a + ib = r(cosφ + isinφ) r² = a² + b², φ = atan(b/a)
: (a + ib)^N = r^N(cos(Nφ) + isin(Nφ))
:)
let \$r := this:pr(\$z)*this:pr(\$z) + this:pi(\$z)*this:pi(\$z)
let \$φ := math:atan2(this:pi(\$z), this:pr(\$z))
let \$r_N := math:pow(\$r,\$pow)
return
this:complex(\$r_N*math:cos(\$pow*\$φ), \$r_N*math:sin(\$pow*\$φ))
}```

#### ```Function: ppowdeclare function ppow(\$z as xs:double*, \$pow as xs:double*) as xs:double*```

ppow()
Principle power for non-integer powers.

##### Params
• z as xs:double*: the complex number
• pow as xs:double*: the power to raise it to
##### Returns
• xs:double*: z^pow
```declare function this:ppow(
\$z as xs:double*,
\$pow as xs:double*
) as xs:double*
{
(: a^b = e^(b log(a)) :)
this:exp(this:log(\$z)=>this:multiply(\$pow))
}```

#### `Function: logdeclare function log(\$z as xs:double*) as xs:double*`

log()
Natural log of complex number.

##### Params
• z as xs:double*: the complex number
##### Returns
• xs:double*: log(z)
```declare function this:log(
\$z as xs:double*
) as xs:double*
{
}```

#### `Function: sqrtdeclare function sqrt(\$z as xs:double*) as xs:double*`

sqrt()
Principal square root of complex number.

##### Params
• z as xs:double*: the complex number
##### Returns
• xs:double*: √z
```declare function this:sqrt(
\$z as xs:double*
) as xs:double*
{
if (this:pi(\$z) = 0) then (
if (this:pr(\$z) >= 0)
then this:complex(math:sqrt(this:pr(\$z)), 0)
else this:complex(0, math:sqrt(-this:pr(\$z)))
) else (
let \$r := this:modulus(\$z)
return
this:complex(
math:sqrt((\$r + this:pr(\$z)) div 2),
util:sign(this:pi(\$z)) * math:sqrt((\$r - this:pr(\$z)) div 2)
)
)
}```

#### `Function: cbrtdeclare function cbrt(\$z as xs:double*) as xs:double*`

cbrt()
Principal cubic root of a complex number. (Highest real part.)
Roots for n integer: for 0 ≤ k < n
z^(1/n) = r^(1/n)(cos((φ + 2kπ)/n) + i sin((φ + 2kπ)/n))

##### Params
• z as xs:double*: the complex number
##### Returns
• xs:double*: z^1/3
```declare function this:cbrt(
\$z as xs:double*
) as xs:double*
{
if (this:pi(\$z) = 0) then (
if (this:pr(\$z) >= 0)
then this:complex(util:cbrt(this:pr(\$z)), 0)
else this:complex(-util:cbrt(-this:pr(\$z)), 0)
) else (
let \$r := this:modulus(\$z)
let \$rcbrt := util:cbrt(\$r)
let \$k :=
head(for \$k in 0 to 2
order by math:cos((\$φ + 2*\$k*math:pi()) div 3) descending
return \$k)
return (
this:complex(
\$rcbrt * math:cos((\$φ + 2*\$k*math:pi()) div 3),
\$rcbrt * math:sin((\$φ + 2*\$k*math:pi()) div 3)
)
)
)
}```

#### `Function: sindeclare function sin(\$z as xs:double*) as xs:double*`

sin()
Sine of complex number.

##### Params
• z as xs:double*: the complex number
##### Returns
• xs:double*: sin(z)
```declare function this:sin(
\$z as xs:double*
) as xs:double*
{
(:
: sin(x + iy) = sin(x)cosh(y) + i cos(x)sinh(y)
:)
this:complex(
math:sin(this:pr(\$z))*util:cosh(this:pi(\$z)),
math:cos(this:pr(\$z))*util:sinh(this:pi(\$z))
)
}```

#### `Function: cosdeclare function cos(\$z as xs:double*) as xs:double*`

cos()
Cosine of complex number.

##### Params
• z as xs:double*: the complex number
##### Returns
• xs:double*: cos(z)
```declare function this:cos(
\$z as xs:double*
) as xs:double*
{
(:
: cos(x + iy) = cos(x)cosh(y) - i sin(x)sinh(y)
:)
this:complex(
math:cos(this:pr(\$z))*util:cosh(this:pi(\$z)),
-math:sin(this:pr(\$z))*util:sinh(this:pi(\$z))
)
}```

#### `Function: sinhdeclare function sinh(\$z as xs:double*) as xs:double*`

sinh()
Hyperbolic sine.

##### Params
• z as xs:double*: the complex number
##### Returns
• xs:double*: sinh(z)
```declare function this:sinh(\$z as xs:double*) as xs:double*
{
(: sinh(x + iy) = sinh(x)cos(y) + cosh(x)sin(y) :)
this:complex(
util:sinh(this:pr(\$z))*math:cos(this:pi(\$z)),
util:cosh(this:pr(\$z))*math:sin(this:pi(\$z))
)
}```

#### `Function: coshdeclare function cosh(\$z as xs:double*) as xs:double*`

cosh()
Hyperbolic cosine.

##### Params
• z as xs:double*: the complex number
##### Returns
• xs:double*: cosh(z)
```declare function this:cosh(\$z as xs:double*) as xs:double*
{
(: cosh(x + iy) = cosh(x)cos(y) - sinh(x)sin(y) :)
this:complex(
util:cosh(this:pr(\$z))*math:cos(this:pi(\$z)),
-util:sinh(this:pr(\$z))*math:sin(this:pi(\$z))
)
}```

#### `Function: asindeclare function asin(\$z as xs:double*) as xs:double*`

asin()
arcsin(z): -i ln(iz + √(1 - z²))

##### Params
• z as xs:double*: the complex number
##### Returns
• xs:double*: asin(z)
```declare function this:asin(
\$z as xs:double*
) as xs:double*
{
this:log(
this:sqrt(
\$this:one=>this:sub(
this:pow(\$z, 2)
)
)
)
)=>this:multiply(this:minus(\$this:i))
}```

#### `Function: acosdeclare function acos(\$z as xs:double*) as xs:double*`

acos()
arccos(z): (1/i) ln(z + √(z² - 1))

##### Params
• z as xs:double*: the complex number
##### Returns
• xs:double*: acos(z)
```declare function this:acos(
\$z as xs:double*
) as xs:double*
{
this:log(
this:sqrt(
this:pow(\$z, 2)=>this:sub( \$this:one )
)
)
)=>this:multiply( this:reciprocal(\$this:i) )
}```

#### `Function: asinhdeclare function asinh(\$z as xs:double*) as xs:double*`

asinh()
Inverse hyperbolic sine: asinh(z) = ln(z + √(z²+1))

##### Params
• z as xs:double*
##### Returns
• xs:double*
```declare function this:asinh(
\$z as xs:double*
) as xs:double*
{
this:log(
this:sqrt(
)
)
)
}```

#### `Function: acoshdeclare function acosh(\$z as xs:double*) as xs:double*`

acosh()
Inverse hyperbolic cosine: acosh(z) = ln(z + √(z²-1))

##### Params
• z as xs:double*
##### Returns
• xs:double*
```declare function this:acosh(
\$z as xs:double*
) as xs:double*
{
this:log(
this:sqrt(
this:pow(\$z, 2)=>this:sub( \$this:one )
)
)
)
}```

#### `Function: expdeclare function exp(\$z as xs:double*) as xs:double*`

exp()
Exponential of z: e^z

##### Params
• z as xs:double*: the complex number
##### Returns
• xs:double*: e^z
```declare function this:exp(
\$z as xs:double*
) as xs:double*
{
(
math:exp(this:pr(\$z)) * math:cos(this:pi(\$z)),
math:exp(this:pr(\$z)) * math:sin(this:pi(\$z))
)
}```

#### ```Function: timesdeclare function times(\$z as xs:double*, \$k as xs:double) as xs:double*```

times()
Multiply a complex by a constant.

##### Params
• z as xs:double*: the complex number
• k as xs:double: the constant to multiply by
##### Returns
• xs:double*: k*z
```declare function this:times(
\$z as xs:double*,
\$k as xs:double
) as xs:double*
{
\$z=>v:times(\$k)
}```

#### ```Function: plusdeclare function plus(\$z as xs:double*, \$k as xs:double) as xs:double*```

plus()
Add a constant to a complex number. (i.e. add complex number (\$k, 0))

##### Params
• z as xs:double*: the complex number
• k as xs:double: the constant to add
##### Returns
• xs:double*: z+k
```declare function this:plus(
\$z as xs:double*,
\$k as xs:double
) as xs:double*
{
}```

#### ```Function: dividedeclare function divide(\$z1 as xs:double*, \$z2 as xs:double*) as xs:double*```

divide()
Divide two complex numbers.

##### Params
• z1 as xs:double*: one complex number
• z2 as xs:double*: other complex number
##### Returns
• xs:double*: z1/z2
```declare function this:divide(
\$z1 as xs:double*,
\$z2 as xs:double*
) as xs:double*
{
(: (a + bi)/(c + di) = ((ac + bd) + i(bc - ad))/(c² + d²) :)
let \$r2 := this:pr(\$z2)*this:pr(\$z2) + this:pi(\$z2)*this:pi(\$z2)
return
(
(this:pr(\$z1)*this:pr(\$z2) + this:pi(\$z1)*this:pi(\$z2)) div \$r2,
(this:pi(\$z1)*this:pr(\$z2) - this:pr(\$z1)*this:pi(\$z2)) div \$r2
)
}```

#### `Function: divide-by-ideclare function divide-by-i(\$z as xs:double*) as xs:double*`

divide-by-i()
Divide complex numbers by i.

##### Params
• z as xs:double*
##### Returns
• xs:double*: z/i
```declare function this:divide-by-i(
\$z as xs:double*
) as xs:double*
{
(: (a + bi)/(c + di) = ((ac + bd) + i(bc - ad))/(c² + d²) :)
(: (a + bi)/(0 + 1i) = ((0a + b1) + i(b0 - a1))/(0² + 1²) = b - ai :)
( this:pi(\$z), -this:pr(\$z) )
}```

#### `Function: modulusdeclare function modulus(\$z as xs:double*) as xs:double`

modulus()
Modulus of a complex number. Given z = re^iφ, the r.

##### Params
• z as xs:double*: the complex numbers
##### Returns
• xs:double: modulus
```declare function this:modulus(
\$z as xs:double*
) as xs:double
{
math:sqrt(this:pr(\$z)*this:pr(\$z) + this:pi(\$z)*this:pi(\$z))
}```

#### `Function: modsqdeclare function modsq(\$z as xs:double*) as xs:double`

modsq()
Modulus of a complex number, squared. Given z = re^iφ, r². Used for cases
where we want to avoid a lot of square root calculations.

##### Params
• z as xs:double*: the complex number
##### Returns
• xs:double: modulus²
```declare function this:modsq(
\$z as xs:double*
) as xs:double
{
this:pr(\$z)*this:pr(\$z) + this:pi(\$z)*this:pi(\$z)
}```

#### `Function: angledeclare function angle(\$z as xs:double*) as xs:double`

angle()
The angle of the complex number. Given z = re^iφ, the φ in degrees.

##### Params
• z as xs:double*: the complex numbers
##### Returns
• xs:double: phase angle, in degrees
```declare function this:angle(
\$z as xs:double*
) as xs:double
{
math:atan2(this:pi(\$z), this:pr(\$z))=>util:degrees()=>util:remap-degrees()
}```

#### `Function: normalizedeclare function normalize(\$z as xs:double*) as xs:double*`

normalize()
Normalize the complex number so modulus is 1.

##### Params
• z as xs:double*: the complex number to normalize
##### Returns
• xs:double*: complex number
```declare function this:normalize(\$z as xs:double*) as xs:double*
{
let \$l := this:modulus(\$z)
return this:complex(this:pr(\$z) div \$l, this:pi(\$z) div \$l)
}```

#### `Function: is-gauss-primedeclare function is-gauss-prime(\$z as xs:double*) as xs:boolean`

is-gauss-prime()
Test whether complex number is gaussian prime; snaps to integral value.

##### Params
• z as xs:double*: complex number to test
##### Returns
• xs:boolean: true if z is Gaussian prime
```declare function this:is-gauss-prime(\$z as xs:double*) as xs:boolean
{
let \$a := this:r(\$z)
let \$b := this:i(\$z)
return (
if (\$a * \$b != 0) then (
util:is-prime(\$a*\$a + \$b*\$b)
) else (
let \$c := abs(\$a + \$b)
return util:is-prime(\$c) and \$c mod 4 = 3
)
)
}```

#### `Function: conjugatedeclare function conjugate(\$z as xs:double*) as xs:double*`

conjugate()
Return the complex conjugate

##### Params
• z as xs:double*: complex number
##### Returns
• xs:double*: conj(z)
```declare function this:conjugate(\$z as xs:double*) as xs:double*
{
this:complex(this:pr(\$z), -this:pi(\$z))
}```

#### `Function: reciprocaldeclare function reciprocal(\$z as xs:double*) as xs:double*`

reciprocal()
The reciprocal of z: 1 / z

##### Params
• z as xs:double*: complex number
##### Returns
• xs:double*: 1/z
```declare function this:reciprocal(\$z as xs:double*) as xs:double*
{
let \$r := this:pr(\$z)*this:pr(\$z) + this:pi(\$z)*this:pi(\$z)
return
this:complex(this:pr(\$z) div \$r, -this:pi(\$z) div \$r)
}```

#### `Function: absdeclare function abs(\$z as xs:double*) as xs:double*`

abs()
The absolute value of z

##### Params
• z as xs:double*: complex number
##### Returns
• xs:double*: abs(z)
```declare function this:abs(\$z as xs:double*) as xs:double*
{
this:complex(abs(this:pr(\$z)), abs(this:pi(\$z)))
}```

#### `Function: quotedeclare function quote(\$zs as xs:double*) as xs:string`

quote()
Return a string value of the complex numbers

##### Params
• zs as xs:double*: complex numbers
##### Returns
• xs:string: string
```declare function this:quote(\$zs as xs:double*) as xs:string
{
string-join(
let \$chunks :=
for \$z at \$i in \$zs return (
if (\$i mod 2 = 0) then (
array {\$zs[\$i - 1], \$z}
) else ()
)
for \$chunk in \$chunks
let \$z := \$chunk?*
return (
let \$r := this:pr(\$z)
let \$i := this:pi(\$z)
return
if (\$r = 0 and \$i = 0) then "0"
else if (\$r = 0) then \$i||"i"
else if (\$i = 0) then string(\$r)
else if (\$i < 0) then \$r||\$i||"i"
else \$r||"+"||\$i||"i"
)
,
" "
)
}```

#### `Function: unquotedeclare function unquote(\$zs as xs:string) as xs:double*`

unquote()
Parse a string value of a complex number to produce that complex number.
Number is of the form 33+12i

##### Params
• zs as xs:string: the string representation of the number
##### Returns
• xs:double*: complex number
```declare function this:unquote(\$zs as xs:string) as xs:double*
{
(: Cases:
:  2
: -2
:     i
:    3i
:   -3i
:  2+3i
: -2+3i
:  2-3i
: -2-3i
:  2+ i
:  2- i
: -2+ i
: -2- i
:)
let \$z := number(\$zs)
return
if (\$z = \$z) then this:complex(\$z, 0) (: 2 | -2 :)
else if (\$zs = "i") then this:complex(0, 1) (: i :)
else (
let \$parts := analyze-string(\$zs, "[-+]?[0123456789.]+")
return (
switch (count(\$parts/fn:match))
case 0 return
if (\$parts/fn:non-match=("i","+i"))
then this:complex(0, 1)
else if (\$parts/fn:non-match="-i")
then this:complex(0, -1)
case 1 return
let \$next := \$parts/fn:match/following-sibling::fn:non-match[1]
return
if (empty(\$next))
then this:complex(number(\$parts/fn:match), 0)
else if (\$next="+i")
then this:complex(number(\$parts/fn:match), 1)
else if (\$next="-i")
then this:complex(number(\$parts/fn:match), -1)
else this:complex(0, number(\$parts/fn:match))
case 2 return
this:complex(number(\$parts/fn:match[1]), number(\$parts/fn:match[2]))
)
)
}```

#### `Function: eqdeclare function eq(\$z as xs:double*, \$val as xs:double) as xs:boolean`

eq()
Is the complex number equal to the double value? That is, does it have
no imaginary part and a real part equal to the value?

##### Params
• z as xs:double*: one complex number
• val as xs:double: a double value
##### Returns
• xs:boolean: real(z)=val and imaginary(z)=0 (within epsilon)
```declare function this:eq(\$z as xs:double*, \$val as xs:double) as xs:boolean
{
this:pr(\$z)=\$val and this:is-real(\$z)
}```

#### `Function: samedeclare function same(\$z1 as xs:double*, \$z2 as xs:double*) as xs:boolean`

same()
Are the two complex numbers the same?

##### Params
• z1 as xs:double*: one complex number
• z2 as xs:double*: other complex number
##### Returns
• xs:boolean: z1=z2
```declare function this:same(\$z1 as xs:double*, \$z2 as xs:double*) as xs:boolean
{
this:pr(\$z1)=this:pr(\$z2) and
this:pi(\$z1)=this:pi(\$z2)
}```

#### `Function: decimaldeclare function decimal(\$zs as xs:double*, \$digits as xs:integer) as xs:double*`

decimal()
Cast the values to a values with the given number of digits.

##### Params
• zs as xs:double*: the complex numbers
• digits as xs:integer: how many digits to preserve
##### Returns
• xs:double*: complex numbers
```declare function this:decimal(\$zs as xs:double*, \$digits as xs:integer) as xs:double*
{
v:decimal(\$zs, \$digits)
}```

### Original Source Code

```xquery version "3.1";
(:~
: Complex numbers (vector implementation)
:
: @since November 2022
: @custom:Status Stable
:)
module namespace this="http://mathling.com/core/complex/vector";

import module namespace config="http://mathling.com/core/config"
at "../core/config.xqy";
import module namespace errors="http://mathling.com/core/errors"
at "../core/errors.xqy";
import module namespace util="http://mathling.com/core/utilities"
at "../core/utilities.xqy";
import module namespace v="http://mathling.com/core/vector"
at "../core/vector.xqy";
import module namespace point="http://mathling.com/geometric/point"
at "../geo/point.xqy";

declare namespace map="http://www.w3.org/2005/xpath-functions/map";
declare namespace math="http://www.w3.org/2005/xpath-functions/math";

declare variable \$this:i as xs:double* := this:complex(0, 1);
declare variable \$this:one as xs:double* := this:complex(1, 0);

(:~
: complex()
: Construct a new complex number.
:
: @param \$real: the real part of the number
: @param \$imaginary: the imaginary part of the number
: @return complex number
:)
declare function this:complex(
\$real as xs:double,
\$imaginary as xs:double
) as xs:double*
{
(\$real, \$imaginary)
};

(:~
: as-complex()
: Cast a real number to a complex.
:
: @param \$real: the real part of the number
: @return complex number
:)
declare function this:as-complex(
\$real as xs:double
) as xs:double*
{
(\$real, 0)
};

(:~
: is-real()
: Test whether the number has no imaginary part. (Within ε).
:
: @param \$z: the complex number
: @return true if complex number has only a real part
:)
declare function this:is-real(
\$z as xs:double*
) as xs:boolean
{
abs(this:pi(\$z)) < \$config:ε
};

(:~
: as-real()
: Cast a complex number to a double, if possible. Raises error if not.
:
: @param \$z: the complex number
: @return double
: @error UTIL-CAST if there is an imaginary part
:)
declare function this:as-real(
\$z as xs:double*
) as xs:double
{
if (this:is-real(\$z)) then this:pr(\$z)
else errors:error("UTIL-CAST", (\$z,'complex'))
};

(:~
: complex-rφd()
: Construct a new complex number using radius and phase angle
: (polar repesentation re^iφ).
:
: @param \$r: modulus of complex number
: @param \$φ: angle of complex number (degrees)
: @return complex number
:)
declare function this:complex-rφd(
\$r as xs:double,
\$φ as xs:double
) as xs:double*
{
return
(\$r * math:cos(\$φR), \$r * math:sin(\$φR))
};

(:~
: complex-rφ()
: Construct a new complex number using radius and phase angle
: (polar repesentation re^iφ).
:
: @param \$r: modulus of complex number
: @param \$φ: angle of complex number (radians)
: @return complex number
:)
declare function this:complex-rφ(
\$r as xs:double,
\$φ as xs:double
) as xs:double*
{
(\$r * math:cos(\$φ), \$r * math:sin(\$φ))
};

(:~
: pr()
: Accessor for real part of the complex number.
:
: @param \$z: the complex number
: @return raw real part
:)
declare function this:pr(\$z as xs:double*) as xs:double
{
v:px(\$z)
};

(:~
: pi()
: Accessor for imaginary part of the complex number.
:
: @param \$z: the complex number
: @return raw imaginary part
:)
declare function this:pi(\$z as xs:double*) as xs:double
{
v:py(\$z)
};

(:~
: r()
: Accessor for real part of the complex number, as integer.
:
: @param \$z: the complex number
: @return real part, rounded
:)
declare function this:r(\$z as xs:double*) as xs:integer
{
v:x(\$z)
};

(:~
: i()
: Accessor for imaginary part of the complex number, as integer.
:
: @param \$z: the complex number
: @return imaginary part, rounded
:)
declare function this:i(\$z as xs:double*) as xs:integer
{
v:y(\$z)
};

(:~
:
: @param \$z1: one complex number
: @param \$z2: other complex number
: @return z1+z2
:)
\$z1 as xs:double*,
\$z2 as xs:double*
) as xs:double*
{
};

(:~
: sum()
: Add several complex numbers in one go.
:)
declare function this:sum(
\$zs as xs:double*
) as xs:double*
{
sum(for \$i in 1 to count(\$zs) idiv 2 return \$zs[2*\$i - 1]),
sum(for \$i in 1 to count(\$zs) idiv 2 return \$zs[2*\$i])
};

(:~
: sub()
: Subtract one complex numbers from another.
:
: @param \$z1: the first complex number
: @param \$z2: the complex number to subtract from the first complex number
: @return z1-z2
:)
declare function this:sub(
\$z1 as xs:double*,
\$z2 as xs:double*
) as xs:double*
{
\$z1=>v:sub(\$z2)
};

(:~
: minus()
: Negation
:
: @param \$z1 the first complex number
: @return -z1
:)
declare function this:minus(
\$z as xs:double*
) as xs:double*
{
\$z=>this:times(-1)
};

(:~
: multiply()
: Multiply two complex numbers.
:
: @param \$z1: one complex number
: @param \$z2: other complex number
: @return z1*z2
:)
declare function this:multiply(
\$z1 as xs:double*,
\$z2 as xs:double*
) as xs:double*
{
(: (a + bi)*(c + di) = (ac - bd) + (ad + bc)i :)
(
this:pr(\$z1)*this:pr(\$z2) - this:pi(\$z1)*this:pi(\$z2),
this:pr(\$z1)*this:pi(\$z2) + this:pi(\$z1)*this:pr(\$z2)
)
};

(:~
: pow()
: Raise a complex number to the given (positive integer) power.
: A convenience function for repeated multiplication. For general powers use ppow()
:
: @param \$z: the complex number
: @param \$pow: the power to raise it to
: @return z^pow
:)
declare function this:pow(
\$z as xs:double*,
\$pow as xs:integer
) as xs:double*
{
if (this:pi(\$z)=0) then this:complex(math:pow(this:pr(\$z), \$pow), 0)
else
switch (\$pow)
case 0 return \$this:one
case 1 return \$z
case 2 return \$z=>this:multiply(\$z)
case 3 return \$z=>this:multiply(\$z)=>this:multiply(\$z)
default return
(: General:
: a + ib = r(cosφ + isinφ) r² = a² + b², φ = atan(b/a)
: (a + ib)^N = r^N(cos(Nφ) + isin(Nφ))
:)
let \$r := this:pr(\$z)*this:pr(\$z) + this:pi(\$z)*this:pi(\$z)
let \$φ := math:atan2(this:pi(\$z), this:pr(\$z))
let \$r_N := math:pow(\$r,\$pow)
return
this:complex(\$r_N*math:cos(\$pow*\$φ), \$r_N*math:sin(\$pow*\$φ))
};

(:~
: ppow()
: Principle power for non-integer powers.
: @param \$z: the complex number
: @param \$pow: the power to raise it to
: @return z^pow
:)
declare function this:ppow(
\$z as xs:double*,
\$pow as xs:double*
) as xs:double*
{
(: a^b = e^(b log(a)) :)
this:exp(this:log(\$z)=>this:multiply(\$pow))
};

(: https://math.stackexchange.com/questions/1103102/how-to-raise-1-to-non-integer-powers :)
(: http://www.milefoot.com/math/complex/functionsofi.htm :)
(: http://en.wikipedia.org/wiki/Complex_number :)

(:~
: log()
: Natural log of complex number.
:
: @param \$z: the complex number
: @return log(z)
:)
declare function this:log(
\$z as xs:double*
) as xs:double*
{
};

(:~
: sqrt()
: Principal square root of complex number.
:
: @param \$z: the complex number
: @return √z
:)
declare function this:sqrt(
\$z as xs:double*
) as xs:double*
{
if (this:pi(\$z) = 0) then (
if (this:pr(\$z) >= 0)
then this:complex(math:sqrt(this:pr(\$z)), 0)
else this:complex(0, math:sqrt(-this:pr(\$z)))
) else (
let \$r := this:modulus(\$z)
return
this:complex(
math:sqrt((\$r + this:pr(\$z)) div 2),
util:sign(this:pi(\$z)) * math:sqrt((\$r - this:pr(\$z)) div 2)
)
)
};

(:~
: cbrt()
: Principal cubic root of a complex number. (Highest real part.)
: Roots for n integer: for 0 ≤ k < n
: z^(1/n) = r^(1/n)(cos((φ + 2kπ)/n) + i sin((φ + 2kπ)/n))
:
: @param \$z: the complex number
: @return z^1/3
:)
declare function this:cbrt(
\$z as xs:double*
) as xs:double*
{
if (this:pi(\$z) = 0) then (
if (this:pr(\$z) >= 0)
then this:complex(util:cbrt(this:pr(\$z)), 0)
else this:complex(-util:cbrt(-this:pr(\$z)), 0)
) else (
let \$r := this:modulus(\$z)
let \$rcbrt := util:cbrt(\$r)
let \$k :=
head(for \$k in 0 to 2
order by math:cos((\$φ + 2*\$k*math:pi()) div 3) descending
return \$k)
return (
this:complex(
\$rcbrt * math:cos((\$φ + 2*\$k*math:pi()) div 3),
\$rcbrt * math:sin((\$φ + 2*\$k*math:pi()) div 3)
)
)
)
};

(:~
: sin()
: Sine of complex number.
:
: @param \$z: the complex number
: @return sin(z)
:)
declare function this:sin(
\$z as xs:double*
) as xs:double*
{
(:
: sin(x + iy) = sin(x)cosh(y) + i cos(x)sinh(y)
:)
this:complex(
math:sin(this:pr(\$z))*util:cosh(this:pi(\$z)),
math:cos(this:pr(\$z))*util:sinh(this:pi(\$z))
)
};

(:~
: cos()
: Cosine of complex number.
:
: @param \$z: the complex number
: @return cos(z)
:)
declare function this:cos(
\$z as xs:double*
) as xs:double*
{
(:
: cos(x + iy) = cos(x)cosh(y) - i sin(x)sinh(y)
:)
this:complex(
math:cos(this:pr(\$z))*util:cosh(this:pi(\$z)),
-math:sin(this:pr(\$z))*util:sinh(this:pi(\$z))
)
};

(:~
: sinh()
: Hyperbolic sine.
:
: @param \$z: the complex number
: @return sinh(z)
:)
declare function this:sinh(\$z as xs:double*) as xs:double*
{
(: sinh(x + iy) = sinh(x)cos(y) + cosh(x)sin(y) :)
this:complex(
util:sinh(this:pr(\$z))*math:cos(this:pi(\$z)),
util:cosh(this:pr(\$z))*math:sin(this:pi(\$z))
)
};

(:~
: cosh()
: Hyperbolic cosine.
:
: @param \$z: the complex number
: @return cosh(z)
:)
declare function this:cosh(\$z as xs:double*) as xs:double*
{
(: cosh(x + iy) = cosh(x)cos(y) - sinh(x)sin(y) :)
this:complex(
util:cosh(this:pr(\$z))*math:cos(this:pi(\$z)),
-util:sinh(this:pr(\$z))*math:sin(this:pi(\$z))
)
};

(:~
: asin()
: arcsin(z): -i ln(iz + √(1 - z²))
:
: @param \$z: the complex number
: @return asin(z)
:)
declare function this:asin(
\$z as xs:double*
) as xs:double*
{
this:log(
this:sqrt(
\$this:one=>this:sub(
this:pow(\$z, 2)
)
)
)
)=>this:multiply(this:minus(\$this:i))
};

(:~
: acos()
: arccos(z): (1/i) ln(z + √(z² - 1))
:
: @param \$z: the complex number
: @return acos(z)
:)
declare function this:acos(
\$z as xs:double*
) as xs:double*
{
this:log(
this:sqrt(
this:pow(\$z, 2)=>this:sub( \$this:one )
)
)
)=>this:multiply( this:reciprocal(\$this:i) )
};

(:~
: asinh()
: Inverse hyperbolic sine: asinh(z) = ln(z + √(z²+1))
:)
declare function this:asinh(
\$z as xs:double*
) as xs:double*
{
this:log(
this:sqrt(
)
)
)
};

(:~
: acosh()
: Inverse hyperbolic cosine: acosh(z) = ln(z + √(z²-1))
:)
declare function this:acosh(
\$z as xs:double*
) as xs:double*
{
this:log(
this:sqrt(
this:pow(\$z, 2)=>this:sub( \$this:one )
)
)
)
};

(:~
: exp()
: Exponential of z: e^z
:
: @param \$z: the complex number
: @return e^z
:)
declare function this:exp(
\$z as xs:double*
) as xs:double*
{
(
math:exp(this:pr(\$z)) * math:cos(this:pi(\$z)),
math:exp(this:pr(\$z)) * math:sin(this:pi(\$z))
)
};

(:~
: times()
: Multiply a complex by a constant.
:
: @param \$z: the complex number
: @param \$k: the constant to multiply by
: @return k*z
:)
declare function this:times(
\$z as xs:double*,
\$k as xs:double
) as xs:double*
{
\$z=>v:times(\$k)
};

(:~
: plus()
: Add a constant to a complex number. (i.e. add complex number (\$k, 0))
:
: @param \$z: the complex number
: @param \$k: the constant to add
: @return z+k
:)
declare function this:plus(
\$z as xs:double*,
\$k as xs:double
) as xs:double*
{
};

(:~
: divide()
: Divide two complex numbers.
:
: @param \$z1: one complex number
: @param \$z2: other complex number
: @return z1/z2
:)
declare function this:divide(
\$z1 as xs:double*,
\$z2 as xs:double*
) as xs:double*
{
(: (a + bi)/(c + di) = ((ac + bd) + i(bc - ad))/(c² + d²) :)
let \$r2 := this:pr(\$z2)*this:pr(\$z2) + this:pi(\$z2)*this:pi(\$z2)
return
(
(this:pr(\$z1)*this:pr(\$z2) + this:pi(\$z1)*this:pi(\$z2)) div \$r2,
(this:pi(\$z1)*this:pr(\$z2) - this:pr(\$z1)*this:pi(\$z2)) div \$r2
)
};

(:~
: divide-by-i()
: Divide complex numbers by i.
:
: @param \$z
: @return z/i
:)
declare function this:divide-by-i(
\$z as xs:double*
) as xs:double*
{
(: (a + bi)/(c + di) = ((ac + bd) + i(bc - ad))/(c² + d²) :)
(: (a + bi)/(0 + 1i) = ((0a + b1) + i(b0 - a1))/(0² + 1²) = b - ai :)
( this:pi(\$z), -this:pr(\$z) )
};

(:~
: modulus()
: Modulus of a complex number. Given z = re^iφ, the r.
:
: @param \$z: the complex numbers
: @return modulus
:)
declare function this:modulus(
\$z as xs:double*
) as xs:double
{
math:sqrt(this:pr(\$z)*this:pr(\$z) + this:pi(\$z)*this:pi(\$z))
};

(:~
: modsq()
: Modulus of a complex number, squared. Given z = re^iφ, r². Used for cases
: where we want to avoid a lot of square root calculations.
:
: @param \$z: the complex number
: @return modulus²
:)
declare function this:modsq(
\$z as xs:double*
) as xs:double
{
this:pr(\$z)*this:pr(\$z) + this:pi(\$z)*this:pi(\$z)
};

(:~
: angle()
: The angle of the complex number. Given z = re^iφ, the φ in degrees.
:
: @param \$z: the complex numbers
: @return phase angle, in degrees
:)
declare function this:angle(
\$z as xs:double*
) as xs:double
{
math:atan2(this:pi(\$z), this:pr(\$z))=>util:degrees()=>util:remap-degrees()
};

(:~
: normalize()
: Normalize the complex number so modulus is 1.
:
: @param \$z: the complex number to normalize
: @return complex number
:)
declare function this:normalize(\$z as xs:double*) as xs:double*
{
let \$l := this:modulus(\$z)
return this:complex(this:pr(\$z) div \$l, this:pi(\$z) div \$l)
};

(:~
: is-gauss-prime()
: Test whether complex number is gaussian prime; snaps to integral value.
:
: @param \$z: complex number to test
: @return true if z is Gaussian prime
:)
declare function this:is-gauss-prime(\$z as xs:double*) as xs:boolean
{
let \$a := this:r(\$z)
let \$b := this:i(\$z)
return (
if (\$a * \$b != 0) then (
util:is-prime(\$a*\$a + \$b*\$b)
) else (
let \$c := abs(\$a + \$b)
return util:is-prime(\$c) and \$c mod 4 = 3
)
)
};

(:~
: conjugate()
: Return the complex conjugate
:
: @param \$z: complex number
: @return conj(z)
:)
declare function this:conjugate(\$z as xs:double*) as xs:double*
{
this:complex(this:pr(\$z), -this:pi(\$z))
};

(:~
: reciprocal()
: The reciprocal of z: 1 / z
:
: @param \$z: complex number
: @return 1/z
:)
declare function this:reciprocal(\$z as xs:double*) as xs:double*
{
let \$r := this:pr(\$z)*this:pr(\$z) + this:pi(\$z)*this:pi(\$z)
return
this:complex(this:pr(\$z) div \$r, -this:pi(\$z) div \$r)
};

(:~
: abs()
: The absolute value of z
:
: @param \$z: complex number
: @return abs(z)
:)
declare function this:abs(\$z as xs:double*) as xs:double*
{
this:complex(abs(this:pr(\$z)), abs(this:pi(\$z)))
};

(:~
: quote()
: Return a string value of the complex numbers
:
: @param \$zs: complex numbers
: @return string
:)
declare function this:quote(\$zs as xs:double*) as xs:string
{
string-join(
let \$chunks :=
for \$z at \$i in \$zs return (
if (\$i mod 2 = 0) then (
array {\$zs[\$i - 1], \$z}
) else ()
)
for \$chunk in \$chunks
let \$z := \$chunk?*
return (
let \$r := this:pr(\$z)
let \$i := this:pi(\$z)
return
if (\$r = 0 and \$i = 0) then "0"
else if (\$r = 0) then \$i||"i"
else if (\$i = 0) then string(\$r)
else if (\$i < 0) then \$r||\$i||"i"
else \$r||"+"||\$i||"i"
)
,
" "
)
};

(:~
: unquote()
: Parse a string value of a complex number to produce that complex number.
: Number is of the form 33+12i
:
: @param \$zs: the string representation of the number
: @return complex number
:)
declare function this:unquote(\$zs as xs:string) as xs:double*
{
(: Cases:
:  2
: -2
:     i
:    3i
:   -3i
:  2+3i
: -2+3i
:  2-3i
: -2-3i
:  2+ i
:  2- i
: -2+ i
: -2- i
:)
let \$z := number(\$zs)
return
if (\$z = \$z) then this:complex(\$z, 0) (: 2 | -2 :)
else if (\$zs = "i") then this:complex(0, 1) (: i :)
else (
let \$parts := analyze-string(\$zs, "[-+]?[0123456789.]+")
return (
switch (count(\$parts/fn:match))
case 0 return
if (\$parts/fn:non-match=("i","+i"))
then this:complex(0, 1)
else if (\$parts/fn:non-match="-i")
then this:complex(0, -1)
case 1 return
let \$next := \$parts/fn:match/following-sibling::fn:non-match[1]
return
if (empty(\$next))
then this:complex(number(\$parts/fn:match), 0)
else if (\$next="+i")
then this:complex(number(\$parts/fn:match), 1)
else if (\$next="-i")
then this:complex(number(\$parts/fn:match), -1)
else this:complex(0, number(\$parts/fn:match))
case 2 return
this:complex(number(\$parts/fn:match[1]), number(\$parts/fn:match[2]))
)
)
};

(:~
: eq()
: Is the complex number equal to the double value? That is, does it have
: no imaginary part and a real part equal to the value?
:
: @param \$z: one complex number
: @param \$val: a double value
: @return real(z)=val and imaginary(z)=0 (within epsilon)
:)
declare function this:eq(\$z as xs:double*, \$val as xs:double) as xs:boolean
{
this:pr(\$z)=\$val and this:is-real(\$z)
};

(:~
: same()
: Are the two complex numbers the same?
:
: @param \$z1: one complex number
: @param \$z2: other complex number
: @return z1=z2
:)
declare function this:same(\$z1 as xs:double*, \$z2 as xs:double*) as xs:boolean
{
this:pr(\$z1)=this:pr(\$z2) and
this:pi(\$z1)=this:pi(\$z2)
};

(:~
: decimal()
: Cast the values to a values with the given number of digits.
:
: @param \$zs: the complex numbers
: @param \$digits: how many digits to preserve
: @return complex numbers
:)
declare function this:decimal(\$zs as xs:double*, \$digits as xs:integer) as xs:double*
{
v:decimal(\$zs, \$digits)
};```