Back to godoc.org
gonum.org/v1/gonum / num / dualcmplx

# Package dualcmplx

v0.7.0
Latest Go to latest
Published: Feb 26, 2020 | License: | Module:

## Overview ¶

Package dualcmplx provides the anti-commutative dual complex numeric type and functions.

See https://arxiv.org/abs/1601.01754v1 for details.

Example

Code:

```// Copyright ©2018 The Gonum Authors. All rights reserved.
// Use of this source code is governed by a BSD-style

package dualcmplx_test

import (
"fmt"
"math"

"gonum.org/v1/gonum/floats"
"gonum.org/v1/gonum/num/dualcmplx"
)

// point is a 2-dimensional point/vector.
type point struct {
x, y float64
}

// raise raises the dimensionality of a point to a complex.
func raise(p point) complex128 {
return complex(p.x, p.y)
}

// raiseDual raises the dimensionality of a point to a dual complex number.
func raiseDual(p point) dualcmplx.Number {
return dualcmplx.Number{
Real: 1,
Dual: complex(p.x, p.y),
}
}

// transform performs the transformation of p by the given dual complex numbers.
// The transformations are normalized to unit vectors.
func transform(p point, by ...dualcmplx.Number) point {
if len(by) == 0 {
return p
}

// Ensure the modulus of by is correctly scaled.
for i := range by {
if len := dualcmplx.Abs(by[i]); len != 1 {
by[i].Real *= complex(1/len, 0)
}
}

// Perform the transformations.
z := by[0]
for _, o := range by[1:] {
z = dualcmplx.Mul(o, z)
}
pp := dualcmplx.Mul(dualcmplx.Mul(z, raiseDual(p)), dualcmplx.Conj(z))

// Extract the point.
return point{x: real(pp.Dual), y: imag(pp.Dual)}
}

func Example() {
// Translate a 1×1 square by [3, 4] and rotate it 90° around the
// origin.
fmt.Println("square:")

// Construct a displacement.
displace := dualcmplx.Number{
Real: 1,
Dual: 0.5 * raise(point{3, 4}),
}

// Construct a rotation.
alpha := math.Pi / 2
rotate := dualcmplx.Number{Real: complex(math.Cos(alpha/2), math.Sin(alpha/2))}

for i, p := range []point{
{x: 0, y: 0},
{x: 0, y: 1},
{x: 1, y: 0},
{x: 1, y: 1},
} {
pp := transform(p,
displace, rotate,
)

// Clean up floating point error for clarity.
pp.x = floats.Round(pp.x, 2)
pp.y = floats.Round(pp.y, 2)

fmt.Printf(" %d %+v -> %+v\n", i, p, pp)
}

// Rotate a line segment 90° around its lower end [2, 2].
fmt.Println("\nline segment:")

// Construct a displacement to the origin from the lower end...
origin := dualcmplx.Number{
Real: 1,
Dual: 0.5 * raise(point{-2, -2}),
}
// ... and back from the origin to the lower end.
replace := dualcmplx.Number{
Real: 1,
Dual: -origin.Dual,
}

for i, p := range []point{
{x: 2, y: 2},
{x: 2, y: 3},
} {
pp := transform(p,
origin,  // Displace to origin.
rotate,  // Rotate around axis.
replace, // Displace back to original location.
)

// Clean up floating point error for clarity.
pp.x = floats.Round(pp.x, 2)
pp.y = floats.Round(pp.y, 2)

fmt.Printf(" %d %+v -> %+v\n", i, p, pp)
}

// Output:
//
// square:
//  0 {x:0 y:0} -> {x:-4 y:3}
//  1 {x:0 y:1} -> {x:-5 y:3}
//  2 {x:1 y:0} -> {x:-4 y:4}
//  3 {x:1 y:1} -> {x:-5 y:4}
//
// line segment:
//  0 {x:2 y:2} -> {x:2 y:2}
//  1 {x:2 y:3} -> {x:1 y:2}
}
```
```
square:
0 {x:0 y:0} -> {x:-4 y:3}
1 {x:0 y:1} -> {x:-5 y:3}
2 {x:1 y:0} -> {x:-4 y:4}
3 {x:1 y:1} -> {x:-5 y:4}

line segment:
0 {x:2 y:2} -> {x:2 y:2}
1 {x:2 y:3} -> {x:1 y:2}
```
Example (Displace)

Code:

```p := dualcmplx.Number{Real: 1, Dual: 3 + 4i}

d := dualcmplx.Number{Real: 1, Dual: 2 + 1.5i}

fmt.Printf("%.0f\n", dualcmplx.Mul(dualcmplx.Mul(d, p), dualcmplx.Conj(d)).Dual)
```
```
(7+7i)
```
Example (DisplaceAndRotate)

Code:

```p := dualcmplx.Number{Real: 1, Dual: 3 + 4i}

d := dualcmplx.Number{Real: 1, Dual: 2 + 1.5i}

r := dualcmplx.Number{Real: complex(math.Cos(math.Pi/4), math.Sin(math.Pi/4))}

q := dualcmplx.Mul(r, d)

fmt.Printf("%.0f\n", dualcmplx.Mul(dualcmplx.Mul(q, p), dualcmplx.Conj(q)).Dual)
```
```
(-7+7i)
```
Example (Rotate)

Code:

```p := dualcmplx.Number{Real: 1, Dual: 3 + 4i}

r := dualcmplx.Number{Real: complex(math.Cos(math.Pi/4), math.Sin(math.Pi/4))}

fmt.Printf("%.0f\n", dualcmplx.Mul(dualcmplx.Mul(r, p), dualcmplx.Conj(r)).Dual)
```
```
(-4+3i)
```
Example (RotateAndDisplace)

Code:

```p := dualcmplx.Number{Real: 1, Dual: 3 + 4i}

d := dualcmplx.Number{Real: 1, Dual: 2 + 1.5i}

r := dualcmplx.Number{Real: complex(math.Cos(math.Pi/4), math.Sin(math.Pi/4))}

q := dualcmplx.Mul(d, r)

fmt.Printf("%.0f\n", dualcmplx.Mul(dualcmplx.Mul(q, p), dualcmplx.Conj(q)).Dual)
```
```
(0+6i)
```

## Index ¶

### func Abs¶

`func Abs(d Number) float64`

Abs returns the absolute value of d.

### type Number¶

```type Number struct {
Real, Dual complex128
}```

Number is a float64 precision anti-commutative dual complex number.

`func Add(x, y Number) Number`

Add returns the sum of x and y.

### func Conj¶

`func Conj(d Number) Number`

Conj returns the conjugate of d₁+d₂ϵ, d̅₁+d₂ϵ.

### func Exp¶

`func Exp(d Number) Number`

Exp returns e**q, the base-e exponential of d.

Special cases are:

```Exp(+Inf) = +Inf
Exp(NaN) = NaN
```

Very large values overflow to 0 or +Inf. Very small values underflow to 1.

### func Inv¶

`func Inv(d Number) Number`

Inv returns the dual inverse of d.

### func Log¶

`func Log(d Number) Number`

Log returns the natural logarithm of d.

Special cases are:

```Log(+Inf) = (+Inf+0ϵ)
Log(0) = (-Inf±Infϵ)
Log(x < 0) = NaN
Log(NaN) = NaN
```

### func Mul¶

`func Mul(x, y Number) Number`

Mul returns the dual product of x and y, x×y.

### func Pow¶

`func Pow(d, p Number) Number`

Pow returns d**p, the base-d exponential of p.

### func PowReal¶

`func PowReal(d Number, p float64) Number`

PowReal returns d**p, the base-d exponential of p.

Special cases are (in order):

```PowReal(NaN+xϵ, ±0) = 1+NaNϵ for any x
Pow(0+xϵ, y) = 0+Infϵ for all y < 1.
Pow(0+xϵ, y) = 0 for all y > 1.
PowReal(x, ±0) = 1 for any x
PowReal(1+xϵ, y) = 1+xyϵ for any y
Pow(Inf, y) = +Inf+NaNϵ for y > 0
Pow(Inf, y) = +0+NaNϵ for y < 0
PowReal(x, 1) = x for any x
PowReal(NaN+xϵ, y) = NaN+NaNϵ
PowReal(x, NaN) = NaN+NaNϵ
PowReal(-1, ±Inf) = 1
PowReal(x+0ϵ, +Inf) = +Inf+NaNϵ for |x| > 1
PowReal(x+yϵ, +Inf) = +Inf for |x| > 1
PowReal(x, -Inf) = +0+NaNϵ for |x| > 1
PowReal(x, +Inf) = +0+NaNϵ for |x| < 1
PowReal(x+0ϵ, -Inf) = +Inf+NaNϵ for |x| < 1
PowReal(x, -Inf) = +Inf-Infϵ for |x| < 1
PowReal(+Inf, y) = +Inf for y > 0
PowReal(+Inf, y) = +0 for y < 0
PowReal(-Inf, y) = Pow(-0, -y)
```

### func Scale¶

`func Scale(f float64, d Number) Number`

Scale returns d scaled by f.

### func Sqrt¶

`func Sqrt(d Number) Number`

Sqrt returns the square root of d.

Special cases are:

```Sqrt(+Inf) = +Inf
Sqrt(±0) = (±0+Infϵ)
Sqrt(x < 0) = NaN
Sqrt(NaN) = NaN
```

### func Sub¶

`func Sub(x, y Number) Number`

Sub returns the difference of x and y, x-y.

### func (Number) Format¶

`func (d Number) Format(fs fmt.State, c rune)`

Format implements fmt.Formatter.

Documentation was rendered with GOOS=linux and GOARCH=amd64.