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

Package dualcmplx

v0.7.0
Latest Go to latest
Published: Feb 26, 2020 | License: BSD-3-Clause | Module: gonum.org/v1/gonum

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
// license that can be found in the LICENSE file.

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

Examples

Package Files

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

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.

Jump to identifier

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to identifier