gonum.org/v1/gonum@v0.14.0/num/dualquat/dual_fike.go (about) 1 // Copyright ©2018 The Gonum Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Derived from code by Jeffrey A. Fike at http://adl.stanford.edu/hyperdual/ 6 7 // The MIT License (MIT) 8 // 9 // Copyright (c) 2006 Jeffrey A. Fike 10 // 11 // Permission is hereby granted, free of charge, to any person obtaining a copy 12 // of this software and associated documentation files (the "Software"), to deal 13 // in the Software without restriction, including without limitation the rights 14 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 // copies of the Software, and to permit persons to whom the Software is 16 // furnished to do so, subject to the following conditions: 17 // 18 // The above copyright notice and this permission notice shall be included in 19 // all copies or substantial portions of the Software. 20 // 21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 // THE SOFTWARE. 28 29 package dualquat 30 31 import ( 32 "math" 33 34 "gonum.org/v1/gonum/num/quat" 35 ) 36 37 // PowReal returns d**p, the base-d exponential of p. 38 // 39 // Special cases are (in order): 40 // 41 // PowReal(NaN+xϵ, ±0) = 1+NaNϵ for any x 42 // PowReal(x, ±0) = 1 for any x 43 // PowReal(1+xϵ, y) = 1+xyϵ for any y 44 // PowReal(x, 1) = x for any x 45 // PowReal(NaN+xϵ, y) = NaN+NaNϵ 46 // PowReal(x, NaN) = NaN+NaNϵ 47 // PowReal(±0, y) = ±Inf for y an odd integer < 0 48 // PowReal(±0, -Inf) = +Inf 49 // PowReal(±0, +Inf) = +0 50 // PowReal(±0, y) = +Inf for finite y < 0 and not an odd integer 51 // PowReal(±0, y) = ±0 for y an odd integer > 0 52 // PowReal(±0, y) = +0 for finite y > 0 and not an odd integer 53 // PowReal(-1, ±Inf) = 1 54 // PowReal(x+0ϵ, +Inf) = +Inf+NaNϵ for |x| > 1 55 // PowReal(x+yϵ, +Inf) = +Inf for |x| > 1 56 // PowReal(x, -Inf) = +0+NaNϵ for |x| > 1 57 // PowReal(x, +Inf) = +0+NaNϵ for |x| < 1 58 // PowReal(x+0ϵ, -Inf) = +Inf+NaNϵ for |x| < 1 59 // PowReal(x, -Inf) = +Inf-Infϵ for |x| < 1 60 // PowReal(+Inf, y) = +Inf for y > 0 61 // PowReal(+Inf, y) = +0 for y < 0 62 // PowReal(-Inf, y) = Pow(-0, -y) 63 func PowReal(d Number, p float64) Number { 64 switch { 65 case p == 0: 66 switch { 67 case quat.IsNaN(d.Real): 68 return Number{Real: quat.Number{Real: 1}, Dual: quat.NaN()} 69 case d.Real == zeroQuat, quat.IsInf(d.Real): 70 return Number{Real: quat.Number{Real: 1}} 71 } 72 case p == 1: 73 return d 74 case math.IsInf(p, 1): 75 if Abs(d).Real > 1 { 76 if d.Dual == zeroQuat { 77 return Number{Real: quat.Inf(), Dual: quat.NaN()} 78 } 79 return Number{Real: quat.Inf(), Dual: quat.Inf()} 80 } 81 return Number{Real: zeroQuat, Dual: quat.NaN()} 82 case math.IsInf(p, -1): 83 if Abs(d).Real > 1 { 84 return Number{Real: zeroQuat, Dual: quat.NaN()} 85 } 86 if d.Dual == zeroQuat { 87 return Number{Real: quat.Inf(), Dual: quat.NaN()} 88 } 89 return Number{Real: quat.Inf(), Dual: quat.Inf()} 90 } 91 deriv := quat.Mul(quat.Number{Real: p}, quat.Pow(d.Real, quat.Number{Real: p - 1})) 92 return Number{ 93 Real: quat.Pow(d.Real, quat.Number{Real: p}), 94 Dual: quat.Mul(d.Dual, deriv), 95 } 96 } 97 98 // Pow return d**p, the base-d exponential of p. 99 func Pow(d, p Number) Number { 100 return Exp(Mul(p, Log(d))) 101 } 102 103 // Sqrt returns the square root of d 104 // 105 // Special cases are: 106 // 107 // Sqrt(+Inf) = +Inf 108 // Sqrt(±0) = (±0+Infϵ) 109 // Sqrt(x < 0) = NaN 110 // Sqrt(NaN) = NaN 111 func Sqrt(d Number) Number { 112 return PowReal(d, 0.5) 113 } 114 115 // Exp returns e**d, the base-e exponential of d. 116 // 117 // Special cases are: 118 // 119 // Exp(+Inf) = +Inf 120 // Exp(NaN) = NaN 121 // 122 // Very large values overflow to 0 or +Inf. 123 // Very small values underflow to 1. 124 func Exp(d Number) Number { 125 fnDeriv := quat.Exp(d.Real) 126 return Number{ 127 Real: fnDeriv, 128 Dual: quat.Mul(fnDeriv, d.Dual), 129 } 130 } 131 132 // Log returns the natural logarithm of d. 133 // 134 // Special cases are: 135 // 136 // Log(+Inf) = (+Inf+0ϵ) 137 // Log(0) = (-Inf±Infϵ) 138 // Log(x < 0) = NaN 139 // Log(NaN) = NaN 140 func Log(d Number) Number { 141 switch { 142 case d.Real == zeroQuat: 143 return Number{ 144 Real: quat.Log(d.Real), 145 Dual: quat.Inf(), 146 } 147 case quat.IsInf(d.Real): 148 return Number{ 149 Real: quat.Log(d.Real), 150 Dual: zeroQuat, 151 } 152 } 153 return Number{ 154 Real: quat.Log(d.Real), 155 Dual: quat.Mul(d.Dual, quat.Inv(d.Real)), 156 } 157 }