gonum: gonum.org/v1/gonum/num/dualcmplx Index | Examples | Files

package dualcmplx

import "gonum.org/v1/gonum/num/dualcmplx"

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

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

Code:

package main

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 main() {
    // 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)
    }

}

Code:

// Displace a point [3, 4] by [4, 3].

// Point to be transformed in the dual imaginary vector.
p := dualcmplx.Number{Real: 1, Dual: 3 + 4i}

// Displacement vector, half [4, 3], in the dual imaginary vector.
d := dualcmplx.Number{Real: 1, Dual: 2 + 1.5i}

fmt.Printf("%.0f\n", dualcmplx.Mul(dualcmplx.Mul(d, p), dualcmplx.Conj(d)).Dual)

Output:

(7+7i)

Code:

// Displace a point [3, 4] by [4, 3] and then rotate
// by 90° around the origin.

// Point to be transformed in the dual imaginary vector.
p := dualcmplx.Number{Real: 1, Dual: 3 + 4i}

// Displacement vector, half [4, 3], in the dual imaginary vector.
d := dualcmplx.Number{Real: 1, Dual: 2 + 1.5i}

// Rotation in the real complex number.
r := dualcmplx.Number{Real: complex(math.Cos(math.Pi/4), math.Sin(math.Pi/4))}

// Combine the rotation and displacement so
// the displacement is performed first.
q := dualcmplx.Mul(r, d)

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

Output:

(-7+7i)

Code:

// Rotate a point [3, 4] by 90° around the origin.

// Point to be transformed in the dual imaginary vector.
p := dualcmplx.Number{Real: 1, Dual: 3 + 4i}

// Half the rotation in the real complex number.
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)

Output:

(-4+3i)

Code:

// Rotate a point [3, 4] by 90° around the origin and then
// displace by [4, 3].

// Point to be transformed in the dual imaginary vector.
p := dualcmplx.Number{Real: 1, Dual: 3 + 4i}

// Displacement vector, half [4, 3], in the dual imaginary vector.
d := dualcmplx.Number{Real: 1, Dual: 2 + 1.5i}

// Rotation in the real complex number.
r := dualcmplx.Number{Real: complex(math.Cos(math.Pi/4), math.Sin(math.Pi/4))}

// Combine the rotation and displacement so
// the displacement is performed first.
q := dualcmplx.Mul(d, r)

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

Output:

(0+6i)

Index

Examples

Package Files

doc.go dual.go

func Abs Uses

func Abs(d Number) float64

Abs returns the absolute value of d.

type Number Uses

type Number struct {
    Real, Dual complex128
}

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

func Add Uses

func Add(x, y Number) Number

Add returns the sum of x and y.

func Conj Uses

func Conj(d Number) Number

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

func Exp Uses

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 Uses

func Inv(d Number) Number

Inv returns the dual inverse of d.

func Log Uses

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 Uses

func Mul(x, y Number) Number

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

func Pow Uses

func Pow(d, p Number) Number

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

func PowReal Uses

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 Uses

func Scale(f float64, d Number) Number

Scale returns d scaled by f.

func Sqrt Uses

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 Uses

func Sub(x, y Number) Number

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

func (Number) Format Uses

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

Format implements fmt.Formatter.

Package dualcmplx imports 4 packages (graph) and is imported by 1 packages. Updated 2019-06-06. Refresh now. Tools for package owners.