http://mathling.com/core/complex library module
http://mathling.com/core/complex
Complex numbers
Copyright© Mary Holstege 2021-2023
CC-BY (https://creativecommons.org/licenses/by/4.0/)
Status: Stable
Imports
http://mathling.com/core/utilitiesimport module namespace util="http://mathling.com/core/utilities" at "../core/utilities.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"
Variables
Variable: $i as map(xs:string,item()*)
Variable: $one as map(xs:string,item()*)
Functions
Function: complex
declare function complex($real as xs:double,
$imaginary as xs:double) as map(xs:string,item()*)
declare function complex($real as xs:double, $imaginary as xs:double) as map(xs:string,item()*)
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
- map(xs:string,item()*): complex number
declare function this:complex( $real as xs:double, $imaginary as xs:double ) as map(xs:string,item()*) { point:point($real, $imaginary) }
Function: as-vector
declare function as-vector($complex as map(xs:string,item()*)) as xs:double*
declare function as-vector($complex as map(xs:string,item()*)) as xs:double*
as-vector()
Cast to the vector form of a complex number.
Params
- complex as map(xs:string,item()*): complex number
Returns
- xs:double*: complex number vector
declare function this:as-vector( $complex as map(xs:string,item()*) ) as xs:double* { point:pcoordinates($complex) }
Function: vector
declare function vector($complex as xs:double*) as map(xs:string,item()*)
declare function vector($complex as xs:double*) as map(xs:string,item()*)
vector()
Cast from the vector form of a complex number.
Params
- complex as xs:double*: complex number vector
Returns
- map(xs:string,item()*): complex number
declare function this:vector( $complex as xs:double* ) as map(xs:string,item()*) { point:vector($complex) }
Function: as-complex
declare function as-complex($real as xs:double) as map(xs:string,item()*)
declare function as-complex($real as xs:double) as map(xs:string,item()*)
as-complex()
Cast a real number to a complex.
Params
- real as xs:double: the real part of the number
Returns
- map(xs:string,item()*): complex number
declare function this:as-complex( $real as xs:double ) as map(xs:string,item()*) { point:point($real, 0) }
Function: is-real
declare function is-real($z as map(xs:string,item()*)) as xs:boolean
declare function is-real($z as map(xs:string,item()*)) as xs:boolean
is-real()
Test whether the number has no imaginary part. (Within ε).
Params
- z as map(xs:string,item()*): the complex number
Returns
- xs:boolean: true if complex number has only a real part
declare function this:is-real( $z as map(xs:string,item()*) ) as xs:boolean { abs(this:pi($z)) < $config:ε }
Function: as-real
declare function as-real($z as map(xs:string,item()*)) as xs:double
declare function as-real($z as map(xs:string,item()*)) as xs:double
as-real()
Cast a complex number to a double, if possible. Raises error if not.
Params
- z as map(xs:string,item()*): the complex number
Returns
- xs:double: double
declare function this:as-real( $z as map(xs:string,item()*) ) 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φd
declare function complex-rφd($r as xs:double,
$φ as xs:double) as map(xs:string,item()*)
declare function complex-rφd($r as xs:double, $φ as xs:double) as map(xs:string,item()*)
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
- map(xs:string,item()*): complex number
declare function this:complex-rφd( $r as xs:double, $φ as xs:double ) as map(xs:string,item()*) { let $φR := util:radians($φ) return point:point($r * math:cos($φR), $r * math:sin($φR)) }
Function: complex-rφ
declare function complex-rφ($r as xs:double,
$φ as xs:double) as map(xs:string,item()*)
declare function complex-rφ($r as xs:double, $φ as xs:double) as map(xs:string,item()*)
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
- map(xs:string,item()*): complex number
declare function this:complex-rφ( $r as xs:double, $φ as xs:double ) as map(xs:string,item()*) { point:point($r * math:cos($φ), $r * math:sin($φ)) }
Function: pr
declare function pr($z as map(xs:string,item()*)) as xs:double
declare function pr($z as map(xs:string,item()*)) as xs:double
pr()
Accessor for real part of the complex number.
Params
- z as map(xs:string,item()*): the complex number
Returns
- xs:double: raw real part
declare function this:pr($z as map(xs:string,item()*)) as xs:double { point:px($z) }
Function: pi
declare function pi($z as map(xs:string,item()*)) as xs:double
declare function pi($z as map(xs:string,item()*)) as xs:double
pi()
Accessor for imaginary part of the complex number.
Params
- z as map(xs:string,item()*): the complex number
Returns
- xs:double: raw imaginary part
declare function this:pi($z as map(xs:string,item()*)) as xs:double { point:py($z) }
Function: r
declare function r($z as map(xs:string,item()*)) as xs:integer
declare function r($z as map(xs:string,item()*)) as xs:integer
r()
Accessor for real part of the complex number, as integer.
Params
- z as map(xs:string,item()*): the complex number
Returns
- xs:integer: real part, rounded
declare function this:r($z as map(xs:string,item()*)) as xs:integer { point:x($z) }
Function: i
declare function i($z as map(xs:string,item()*)) as xs:integer
declare function i($z as map(xs:string,item()*)) as xs:integer
i()
Accessor for imaginary part of the complex number, as integer.
Params
- z as map(xs:string,item()*): the complex number
Returns
- xs:integer: imaginary part, rounded
declare function this:i($z as map(xs:string,item()*)) as xs:integer { point:y($z) }
Function: add
declare function add($z1 as map(xs:string,item()*),
$z2 as map(xs:string,item()*)) as map(xs:string,item()*)
declare function add($z1 as map(xs:string,item()*), $z2 as map(xs:string,item()*)) as map(xs:string,item()*)
add()
Add two complex numbers.
Params
- z1 as map(xs:string,item()*): one complex number
- z2 as map(xs:string,item()*): another complex number
Returns
- map(xs:string,item()*): z1+z2
declare function this:add( $z1 as map(xs:string,item()*), $z2 as map(xs:string,item()*) ) as map(xs:string,item()*) { $z1=>point:add($z2) }
Function: sum
declare function sum($zs as map(xs:string,item()*)*) as map(xs:string,item()*)
declare function sum($zs as map(xs:string,item()*)*) as map(xs:string,item()*)
sum()
Add several complex numbers in one go.
Params
- zs as map(xs:string,item()*)*
Returns
- map(xs:string,item()*)
declare function this:sum( $zs as map(xs:string,item()*)* ) as map(xs:string,item()*) { point:sum($zs) }
Function: sub
declare function sub($z1 as map(xs:string,item()*),
$z2 as map(xs:string,item()*)) as map(xs:string,item()*)
declare function sub($z1 as map(xs:string,item()*), $z2 as map(xs:string,item()*)) as map(xs:string,item()*)
sub()
Subtract one complex numbers from another.
Params
- z1 as map(xs:string,item()*): the first complex number
- z2 as map(xs:string,item()*): the complex number to subtract from the first complex number
Returns
- map(xs:string,item()*): z1-z2
declare function this:sub( $z1 as map(xs:string,item()*), $z2 as map(xs:string,item()*) ) as map(xs:string,item()*) { $z1=>point:sub($z2) }
Function: minus
declare function minus($z as map(xs:string,item()*)) as map(xs:string,item()*)
declare function minus($z as map(xs:string,item()*)) as map(xs:string,item()*)
minus()
Negation
Params
- z as map(xs:string,item()*)1 the first complex number
Returns
- map(xs:string,item()*): -z1
declare function this:minus( $z as map(xs:string,item()*) ) as map(xs:string,item()*) { $z=>point:times(-1) }
Function: multiply
declare function multiply($z1 as map(xs:string,item()*),
$z2 as map(xs:string,item()*)) as map(xs:string,item()*)
declare function multiply($z1 as map(xs:string,item()*), $z2 as map(xs:string,item()*)) as map(xs:string,item()*)
multiply()
Multiply two complex numbers.
Params
- z1 as map(xs:string,item()*): one complex number
- z2 as map(xs:string,item()*): another complex number
Returns
- map(xs:string,item()*): z1*z2
declare function this:multiply( $z1 as map(xs:string,item()*), $z2 as map(xs:string,item()*) ) as map(xs:string,item()*) { (: (a + bi)*(c + di) = (ac - bd) + (ad + bc)i :) point:point( 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: pow
declare function pow($z as map(xs:string,item()*),
$pow as xs:integer) as map(xs:string,item()*)
declare function pow($z as map(xs:string,item()*), $pow as xs:integer) as map(xs:string,item()*)
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 map(xs:string,item()*): the complex number
- pow as xs:integer: the power to raise it to
Returns
- map(xs:string,item()*): z^pow
declare function this:pow( $z as map(xs:string,item()*), $pow as xs:integer ) as map(xs:string,item()*) { 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: ppow
declare function ppow($z as map(xs:string,item()*),
$pow as map(xs:string,item()*)) as map(xs:string,item()*)
declare function ppow($z as map(xs:string,item()*), $pow as map(xs:string,item()*)) as map(xs:string,item()*)
ppow()
Principle power for non-integer powers.
Params
- z as map(xs:string,item()*): the complex number
- pow as map(xs:string,item()*): the power to raise it to
Returns
- map(xs:string,item()*): z^pow
declare function this:ppow( $z as map(xs:string,item()*), $pow as map(xs:string,item()*) ) as map(xs:string,item()*) { (: a^b = e^(b log(a)) :) this:exp(this:log($z)=>this:multiply($pow)) }
Function: log
declare function log($z as map(xs:string,item()*)) as map(xs:string,item()*)
declare function log($z as map(xs:string,item()*)) as map(xs:string,item()*)
log()
Natural log of complex number.
Params
- z as map(xs:string,item()*): the complex number
Returns
- map(xs:string,item()*): log(z)
declare function this:log( $z as map(xs:string,item()*) ) as map(xs:string,item()*) { this:complex(math:log(this:modulus($z)), this:angle($z)=>util:radians()) }
Function: sqrt
declare function sqrt($z as map(xs:string,item()*)) as map(xs:string,item()*)
declare function sqrt($z as map(xs:string,item()*)) as map(xs:string,item()*)
sqrt()
Principal square root of complex number.
Params
- z as map(xs:string,item()*): the complex number
Returns
- map(xs:string,item()*): √z
declare function this:sqrt( $z as map(xs:string,item()*) ) as map(xs:string,item()*) { 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: cbrt
declare function cbrt($z as map(xs:string,item()*)) as map(xs:string,item()*)
declare function cbrt($z as map(xs:string,item()*)) as map(xs:string,item()*)
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 map(xs:string,item()*): the complex number
Returns
- map(xs:string,item()*): z^1/3
declare function this:cbrt( $z as map(xs:string,item()*) ) as map(xs:string,item()*) { 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 $φ := this:angle($z)=>util:radians() 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: sin
declare function sin($z as map(xs:string,item()*)) as map(xs:string,item()*)
declare function sin($z as map(xs:string,item()*)) as map(xs:string,item()*)
sin()
Sine of complex number.
Params
- z as map(xs:string,item()*): the complex number
Returns
- map(xs:string,item()*): sin(z)
declare function this:sin( $z as map(xs:string,item()*) ) as map(xs:string,item()*) { (: : 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: cos
declare function cos($z as map(xs:string,item()*)) as map(xs:string,item()*)
declare function cos($z as map(xs:string,item()*)) as map(xs:string,item()*)
cos()
Cosine of complex number.
Params
- z as map(xs:string,item()*): the complex number
Returns
- map(xs:string,item()*): cos(z)
declare function this:cos( $z as map(xs:string,item()*) ) as map(xs:string,item()*) { (: : 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: sinh
declare function sinh($z as map(xs:string,item()*)) as map(xs:string,item()*)
declare function sinh($z as map(xs:string,item()*)) as map(xs:string,item()*)
sinh()
Hyperbolic sine.
Params
- z as map(xs:string,item()*): the complex number
Returns
- map(xs:string,item()*): sinh(z)
declare function this:sinh($z as map(xs:string,item()*)) as map(xs:string,item()*) { (: 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: cosh
declare function cosh($z as map(xs:string,item()*)) as map(xs:string,item()*)
declare function cosh($z as map(xs:string,item()*)) as map(xs:string,item()*)
cosh()
Hyperbolic cosine.
Params
- z as map(xs:string,item()*): the complex number
Returns
- map(xs:string,item()*): cosh(z)
declare function this:cosh($z as map(xs:string,item()*)) as map(xs:string,item()*) { (: 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: asin
declare function asin($z as map(xs:string,item()*)) as map(xs:string,item()*)
declare function asin($z as map(xs:string,item()*)) as map(xs:string,item()*)
asin()
arcsin(z): -i ln(iz + √(1 - z²))
Params
- z as map(xs:string,item()*): the complex number
Returns
- map(xs:string,item()*): asin(z)
declare function this:asin( $z as map(xs:string,item()*) ) as map(xs:string,item()*) { this:log( this:multiply($this:i, $z)=>this:add( this:sqrt( $this:one=>this:sub( this:pow($z, 2) ) ) ) )=>this:multiply(this:minus($this:i)) }
Function: acos
declare function acos($z as map(xs:string,item()*)) as map(xs:string,item()*)
declare function acos($z as map(xs:string,item()*)) as map(xs:string,item()*)
acos()
arccos(z): (1/i) ln(z + √(z² - 1))
Params
- z as map(xs:string,item()*): the complex number
Returns
- map(xs:string,item()*): acos(z)
declare function this:acos( $z as map(xs:string,item()*) ) as map(xs:string,item()*) { this:log( $z=>this:add( this:sqrt( this:pow($z, 2)=>this:sub($this:one) ) ) )=>this:multiply( this:reciprocal($this:i) ) }
Function: asinh
declare function asinh($z as map(xs:string,item()*)) as map(xs:string,item()*)
declare function asinh($z as map(xs:string,item()*)) as map(xs:string,item()*)
asinh()
Inverse hyperbolic sine: asinh(z) = ln(z + √(z²+1))
Params
- z as map(xs:string,item()*)
Returns
- map(xs:string,item()*)
declare function this:asinh( $z as map(xs:string,item()*) ) as map(xs:string,item()*) { this:log( $z=>this:add( this:sqrt( this:pow($z, 2)=>this:add($this:one) ) ) ) }
Function: acosh
declare function acosh($z as map(xs:string,item()*)) as map(xs:string,item()*)
declare function acosh($z as map(xs:string,item()*)) as map(xs:string,item()*)
acosh()
Inverse hyperbolic cosine: acosh(z) = ln(z + √(z²-1))
Params
- z as map(xs:string,item()*)
Returns
- map(xs:string,item()*)
declare function this:acosh( $z as map(xs:string,item()*) ) as map(xs:string,item()*) { this:log( $z=>this:add( this:sqrt( this:pow($z, 2)=>this:sub($this:one) ) ) ) }
Function: exp
declare function exp($z as map(xs:string,item()*)) as map(xs:string,item()*)
declare function exp($z as map(xs:string,item()*)) as map(xs:string,item()*)
exp()
Exponential of z: e^z
Params
- z as map(xs:string,item()*): the complex number
Returns
- map(xs:string,item()*): e^z
declare function this:exp( $z as map(xs:string,item()*) ) as map(xs:string,item()*) { this:complex( math:exp(this:pr($z)) * math:cos(this:pi($z)), math:exp(this:pr($z)) * math:sin(this:pi($z)) ) }
Function: times
declare function times($z as map(xs:string,item()*),
$k as xs:double) as map(xs:string,item()*)
declare function times($z as map(xs:string,item()*), $k as xs:double) as map(xs:string,item()*)
times()
Multiply a complex by a constant.
Params
- z as map(xs:string,item()*): the complex number
- k as xs:double: the constant to multiply by
Returns
- map(xs:string,item()*): k*z
declare function this:times( $z as map(xs:string,item()*), $k as xs:double ) as map(xs:string,item()*) { $z=>point:times($k) }
Function: plus
declare function plus($z as map(xs:string,item()*),
$k as xs:double) as map(xs:string,item()*)
declare function plus($z as map(xs:string,item()*), $k as xs:double) as map(xs:string,item()*)
plus()
Add a constant to a complex number. (i.e. add complex number ($k, 0))
Params
- z as map(xs:string,item()*): the complex number
- k as xs:double: the constant to add
Returns
- map(xs:string,item()*): z+k
declare function this:plus( $z as map(xs:string,item()*), $k as xs:double ) as map(xs:string,item()*) { $z=>this:add(this:complex($k, 0)) }
Function: divide
declare function divide($z1 as map(xs:string,item()*),
$z2 as map(xs:string,item()*)) as map(xs:string,item()*)
declare function divide($z1 as map(xs:string,item()*), $z2 as map(xs:string,item()*)) as map(xs:string,item()*)
divide()
Divide two complex numbers.
Params
- z1 as map(xs:string,item()*): one complex number
- z2 as map(xs:string,item()*): another complex number
Returns
- map(xs:string,item()*): z1/z2
declare function this:divide( $z1 as map(xs:string,item()*), $z2 as map(xs:string,item()*) ) as map(xs:string,item()*) { (: (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 point:point( (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-i
declare function divide-by-i($z as map(xs:string,item()*)) as map(xs:string,item()*)
declare function divide-by-i($z as map(xs:string,item()*)) as map(xs:string,item()*)
divide-by-i()
Divide complex numbers by i.
Params
- z as map(xs:string,item()*)
Returns
- map(xs:string,item()*): z/i
declare function this:divide-by-i( $z as map(xs:string,item()*) ) as map(xs:string,item()*) { (: (a + bi)/(c + di) = ((ac + bd) + i(bc - ad))/(c² + d²) :) (: (a + bi)/(0 + 1i) = ((0a + b1) + i(b0 - a1))/(0² + 1²) = b - ai :) point:point( this:pi($z), -this:pr($z) ) }
Function: modulus
declare function modulus($z as map(xs:string,item()*)) as xs:double
declare function modulus($z as map(xs:string,item()*)) as xs:double
modulus()
Modulus of a complex number. Given z = re^iφ, the r.
Params
- z as map(xs:string,item()*): the complex number
Returns
- xs:double: modulus
declare function this:modulus( $z as map(xs:string,item()*) ) as xs:double { math:sqrt(this:pr($z)*this:pr($z) + this:pi($z)*this:pi($z)) }
Function: modsq
declare function modsq($z as map(xs:string,item()*)) as xs:double
declare function modsq($z as map(xs:string,item()*)) 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 map(xs:string,item()*): the complex number
Returns
- xs:double: modulus²
declare function this:modsq( $z as map(xs:string,item()*) ) as xs:double { this:pr($z)*this:pr($z) + this:pi($z)*this:pi($z) }
Function: angle
declare function angle($z as map(xs:string,item()*)) as xs:double
declare function angle($z as map(xs:string,item()*)) as xs:double
angle()
The angle of the complex number. Given z = re^iφ, the φ in degrees.
Params
- z as map(xs:string,item()*): the complex numbers
Returns
- xs:double: phase angle, in degrees
declare function this:angle( $z as map(xs:string,item()*) ) as xs:double { math:atan2(this:pi($z), this:pr($z))=>util:degrees()=>util:remap-degrees() }
Function: normalize
declare function normalize($z as map(xs:string,item()*)) as map(xs:string,item()*)
declare function normalize($z as map(xs:string,item()*)) as map(xs:string,item()*)
normalize()
Normalize the complex number so modulus is 1.
Params
- z as map(xs:string,item()*): the complex number to normalize
Returns
- map(xs:string,item()*): complex number
declare function this:normalize($z as map(xs:string,item()*)) as map(xs:string,item()*) { let $l := this:modulus($z) return this:complex(this:pr($z) div $l, this:pi($z) div $l) }
Function: is-gauss-prime
declare function is-gauss-prime($z as map(xs:string,item()*)) as xs:boolean
declare function is-gauss-prime($z as map(xs:string,item()*)) as xs:boolean
is-gauss-prime()
Test whether complex number is Gaussian prime; snaps to integral value.
Params
- z as map(xs:string,item()*): complex number to test
Returns
- xs:boolean: true if z is Gaussian prime
declare function this:is-gauss-prime($z as map(xs:string,item()*)) 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: conjugate
declare function conjugate($z as map(xs:string,item()*)) as map(xs:string,item()*)
declare function conjugate($z as map(xs:string,item()*)) as map(xs:string,item()*)
conjugate()
Return the complex conjugate
Params
- z as map(xs:string,item()*): complex number
Returns
- map(xs:string,item()*): conj(z)
declare function this:conjugate($z as map(xs:string,item()*)) as map(xs:string,item()*) { this:complex(this:pr($z), -this:pi($z)) }
Function: reciprocal
declare function reciprocal($z as map(xs:string,item()*)) as map(xs:string,item()*)
declare function reciprocal($z as map(xs:string,item()*)) as map(xs:string,item()*)
reciprocal()
The reciprocal of z: 1 / z
Params
- z as map(xs:string,item()*): complex number
Returns
- map(xs:string,item()*): 1/z
declare function this:reciprocal($z as map(xs:string,item()*)) as map(xs:string,item()*) { 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: abs
declare function abs($z as map(xs:string,item()*)) as map(xs:string,item()*)
declare function abs($z as map(xs:string,item()*)) as map(xs:string,item()*)
abs()
The absolute value of z
Params
- z as map(xs:string,item()*): complex number
Returns
- map(xs:string,item()*): abs(z)
declare function this:abs($z as map(xs:string,item()*)) as map(xs:string,item()*) { this:complex(abs(this:pr($z)), abs(this:pi($z))) }
Function: quote
declare function quote($zs as map(xs:string,item()*)*) as xs:string
declare function quote($zs as map(xs:string,item()*)*) as xs:string
quote()
Return a string value of the complex numbers
Params
- zs as map(xs:string,item()*)*: complex numbers
Returns
- xs:string: string
declare function this:quote($zs as map(xs:string,item()*)*) as xs:string { string-join( for $z in $zs 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: unquote
declare function unquote($zs as xs:string) as map(xs:string,item()*)
declare function unquote($zs as xs:string) as map(xs:string,item()*)
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
- map(xs:string,item()*): complex number
declare function this:unquote($zs as xs:string) as map(xs:string,item()*) { (: 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) else errors:error("UTIL-BADCOMPLEX", $zs) 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])) default return errors:error("UTIL-BADCOMPLEX", $zs) ) ) }
Function: eq
declare function eq($z as map(xs:string,item()*), $val as xs:double) as xs:boolean
declare function eq($z as map(xs:string,item()*), $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 map(xs:string,item()*): 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 map(xs:string,item()*), $val as xs:double) as xs:boolean { this:pr($z)=$val and this:is-real($z) }
Function: same
declare function same($z1 as map(xs:string,item()*), $z2 as map(xs:string,item()*)) as xs:boolean
declare function same($z1 as map(xs:string,item()*), $z2 as map(xs:string,item()*)) as xs:boolean
same()
Are the two complex numbers the same?
Params
- z1 as map(xs:string,item()*): one complex number
- z2 as map(xs:string,item()*): another complex number
Returns
- xs:boolean: z1=z2
declare function this:same($z1 as map(xs:string,item()*), $z2 as map(xs:string,item()*)) as xs:boolean { this:pr($z1)=this:pr($z2) and this:pi($z1)=this:pi($z2) }
Function: decimal
declare function decimal($zs as map(xs:string,item()*)*, $digits as xs:integer) as map(xs:string,item()*)*
declare function decimal($zs as map(xs:string,item()*)*, $digits as xs:integer) as map(xs:string,item()*)*
decimal()
Cast the values to a values with the given number of digits.
Params
- zs as map(xs:string,item()*)*: the complex numbers
- digits as xs:integer: how many digits to preserve
Returns
- map(xs:string,item()*)*: complex numbers
declare function this:decimal($zs as map(xs:string,item()*)*, $digits as xs:integer) as map(xs:string,item()*)* { point:decimal($zs, $digits) }
Original Source Code
xquery version "3.1"; (:~ : Complex numbers : : Copyright© Mary Holstege 2021-2023 : CC-BY (https://creativecommons.org/licenses/by/4.0/) : @since October 2021 : @custom:Status Stable :) module namespace this="http://mathling.com/core/complex"; 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 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 map(xs:string,item()*) := this:complex(0, 1); declare variable $this:one as map(xs:string,item()*) := 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 map(xs:string,item()*) { point:point($real, $imaginary) }; (:~ : as-vector() : Cast to the vector form of a complex number. : @param $complex: complex number : @return complex number vector :) declare function this:as-vector( $complex as map(xs:string,item()*) ) as xs:double* { point:pcoordinates($complex) }; (:~ : vector() : Cast from the vector form of a complex number. : @param $complex: complex number vector : @return complex number :) declare function this:vector( $complex as xs:double* ) as map(xs:string,item()*) { point:vector($complex) }; (:~ : 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 map(xs:string,item()*) { point:point($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 map(xs:string,item()*) ) 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 map(xs:string,item()*) ) 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 map(xs:string,item()*) { let $φR := util:radians($φ) return point:point($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 map(xs:string,item()*) { point:point($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 map(xs:string,item()*)) as xs:double { point: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 map(xs:string,item()*)) as xs:double { point: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 map(xs:string,item()*)) as xs:integer { point: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 map(xs:string,item()*)) as xs:integer { point:y($z) }; (:~ : add() : Add two complex numbers. : : @param $z1: one complex number : @param $z2: another complex number : @return z1+z2 :) declare function this:add( $z1 as map(xs:string,item()*), $z2 as map(xs:string,item()*) ) as map(xs:string,item()*) { $z1=>point:add($z2) }; (:~ : sum() : Add several complex numbers in one go. :) declare function this:sum( $zs as map(xs:string,item()*)* ) as map(xs:string,item()*) { point:sum($zs) }; (:~ : 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 map(xs:string,item()*), $z2 as map(xs:string,item()*) ) as map(xs:string,item()*) { $z1=>point:sub($z2) }; (:~ : minus() : Negation : : @param $z1 the first complex number : @return -z1 :) declare function this:minus( $z as map(xs:string,item()*) ) as map(xs:string,item()*) { $z=>point:times(-1) }; (:~ : multiply() : Multiply two complex numbers. : : @param $z1: one complex number : @param $z2: another complex number : @return z1*z2 :) declare function this:multiply( $z1 as map(xs:string,item()*), $z2 as map(xs:string,item()*) ) as map(xs:string,item()*) { (: (a + bi)*(c + di) = (ac - bd) + (ad + bc)i :) point:point( 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 map(xs:string,item()*), $pow as xs:integer ) as map(xs:string,item()*) { 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 map(xs:string,item()*), $pow as map(xs:string,item()*) ) as map(xs:string,item()*) { (: 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 map(xs:string,item()*) ) as map(xs:string,item()*) { this:complex(math:log(this:modulus($z)), this:angle($z)=>util:radians()) }; (:~ : sqrt() : Principal square root of complex number. : : @param $z: the complex number : @return √z :) declare function this:sqrt( $z as map(xs:string,item()*) ) as map(xs:string,item()*) { 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 map(xs:string,item()*) ) as map(xs:string,item()*) { 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 $φ := this:angle($z)=>util:radians() 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 map(xs:string,item()*) ) as map(xs:string,item()*) { (: : 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 map(xs:string,item()*) ) as map(xs:string,item()*) { (: : 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 map(xs:string,item()*)) as map(xs:string,item()*) { (: 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 map(xs:string,item()*)) as map(xs:string,item()*) { (: 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 map(xs:string,item()*) ) as map(xs:string,item()*) { this:log( this:multiply($this:i, $z)=>this:add( 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 map(xs:string,item()*) ) as map(xs:string,item()*) { this:log( $z=>this:add( 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 map(xs:string,item()*) ) as map(xs:string,item()*) { this:log( $z=>this:add( this:sqrt( this:pow($z, 2)=>this:add($this:one) ) ) ) }; (:~ : acosh() : Inverse hyperbolic cosine: acosh(z) = ln(z + √(z²-1)) :) declare function this:acosh( $z as map(xs:string,item()*) ) as map(xs:string,item()*) { this:log( $z=>this:add( 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 map(xs:string,item()*) ) as map(xs:string,item()*) { this:complex( 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 map(xs:string,item()*), $k as xs:double ) as map(xs:string,item()*) { $z=>point: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 map(xs:string,item()*), $k as xs:double ) as map(xs:string,item()*) { $z=>this:add(this:complex($k, 0)) }; (:~ : divide() : Divide two complex numbers. : : @param $z1: one complex number : @param $z2: another complex number : @return z1/z2 :) declare function this:divide( $z1 as map(xs:string,item()*), $z2 as map(xs:string,item()*) ) as map(xs:string,item()*) { (: (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 point:point( (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 map(xs:string,item()*) ) as map(xs:string,item()*) { (: (a + bi)/(c + di) = ((ac + bd) + i(bc - ad))/(c² + d²) :) (: (a + bi)/(0 + 1i) = ((0a + b1) + i(b0 - a1))/(0² + 1²) = b - ai :) point:point( this:pi($z), -this:pr($z) ) }; (:~ : modulus() : Modulus of a complex number. Given z = re^iφ, the r. : : @param $z: the complex number : @return modulus :) declare function this:modulus( $z as map(xs:string,item()*) ) 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 map(xs:string,item()*) ) 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 map(xs:string,item()*) ) 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 map(xs:string,item()*)) as map(xs:string,item()*) { 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 map(xs:string,item()*)) 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 map(xs:string,item()*)) as map(xs:string,item()*) { 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 map(xs:string,item()*)) as map(xs:string,item()*) { 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 map(xs:string,item()*)) as map(xs:string,item()*) { 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 map(xs:string,item()*)*) as xs:string { string-join( for $z in $zs 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 map(xs:string,item()*) { (: 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) else errors:error("UTIL-BADCOMPLEX", $zs) 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])) default return errors:error("UTIL-BADCOMPLEX", $zs) ) ) }; (:~ : 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 map(xs:string,item()*), $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: another complex number : @return z1=z2 :) declare function this:same($z1 as map(xs:string,item()*), $z2 as map(xs:string,item()*)) 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 map(xs:string,item()*)*, $digits as xs:integer) as map(xs:string,item()*)* { point:decimal($zs, $digits) };