github.com/jingcheng-WU/gonum@v0.9.1-0.20210323123734-f1a2a11a8f7b/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 "github.com/jingcheng-WU/gonum/num/quat" 35 ) 36 37 // PowReal returns d**p, the base-d exponential of p. 38 // 39 // Special cases are (in order): 40 // PowReal(NaN+xϵ, ±0) = 1+NaNϵ for any x 41 // PowReal(x, ±0) = 1 for any x 42 // PowReal(1+xϵ, y) = 1+xyϵ for any y 43 // PowReal(x, 1) = x for any x 44 // PowReal(NaN+xϵ, y) = NaN+NaNϵ 45 // PowReal(x, NaN) = NaN+NaNϵ 46 // PowReal(±0, y) = ±Inf for y an odd integer < 0 47 // PowReal(±0, -Inf) = +Inf 48 // PowReal(±0, +Inf) = +0 49 // PowReal(±0, y) = +Inf for finite y < 0 and not an odd integer 50 // PowReal(±0, y) = ±0 for y an odd integer > 0 51 // PowReal(±0, y) = +0 for finite y > 0 and not an odd integer 52 // PowReal(-1, ±Inf) = 1 53 // PowReal(x+0ϵ, +Inf) = +Inf+NaNϵ for |x| > 1 54 // PowReal(x+yϵ, +Inf) = +Inf for |x| > 1 55 // PowReal(x, -Inf) = +0+NaNϵ for |x| > 1 56 // PowReal(x, +Inf) = +0+NaNϵ for |x| < 1 57 // PowReal(x+0ϵ, -Inf) = +Inf+NaNϵ for |x| < 1 58 // PowReal(x, -Inf) = +Inf-Infϵ for |x| < 1 59 // PowReal(+Inf, y) = +Inf for y > 0 60 // PowReal(+Inf, y) = +0 for y < 0 61 // PowReal(-Inf, y) = Pow(-0, -y) 62 func PowReal(d Number, p float64) Number { 63 switch { 64 case p == 0: 65 switch { 66 case quat.IsNaN(d.Real): 67 return Number{Real: quat.Number{Real: 1}, Dual: quat.NaN()} 68 case d.Real == zeroQuat, quat.IsInf(d.Real): 69 return Number{Real: quat.Number{Real: 1}} 70 } 71 case p == 1: 72 return d 73 case math.IsInf(p, 1): 74 if Abs(d).Real > 1 { 75 if d.Dual == zeroQuat { 76 return Number{Real: quat.Inf(), Dual: quat.NaN()} 77 } 78 return Number{Real: quat.Inf(), Dual: quat.Inf()} 79 } 80 return Number{Real: zeroQuat, Dual: quat.NaN()} 81 case math.IsInf(p, -1): 82 if Abs(d).Real > 1 { 83 return Number{Real: zeroQuat, Dual: quat.NaN()} 84 } 85 if d.Dual == zeroQuat { 86 return Number{Real: quat.Inf(), Dual: quat.NaN()} 87 } 88 return Number{Real: quat.Inf(), Dual: quat.Inf()} 89 } 90 deriv := quat.Mul(quat.Number{Real: p}, quat.Pow(d.Real, quat.Number{Real: p - 1})) 91 return Number{ 92 Real: quat.Pow(d.Real, quat.Number{Real: p}), 93 Dual: quat.Mul(d.Dual, deriv), 94 } 95 } 96 97 // Pow return d**p, the base-d exponential of p. 98 func Pow(d, p Number) Number { 99 return Exp(Mul(p, Log(d))) 100 } 101 102 // Sqrt returns the square root of d 103 // 104 // Special cases are: 105 // Sqrt(+Inf) = +Inf 106 // Sqrt(±0) = (±0+Infϵ) 107 // Sqrt(x < 0) = NaN 108 // Sqrt(NaN) = NaN 109 func Sqrt(d Number) Number { 110 return PowReal(d, 0.5) 111 } 112 113 // Exp returns e**d, the base-e exponential of d. 114 // 115 // Special cases are: 116 // Exp(+Inf) = +Inf 117 // Exp(NaN) = NaN 118 // Very large values overflow to 0 or +Inf. 119 // Very small values underflow to 1. 120 func Exp(d Number) Number { 121 fnDeriv := quat.Exp(d.Real) 122 return Number{ 123 Real: fnDeriv, 124 Dual: quat.Mul(fnDeriv, d.Dual), 125 } 126 } 127 128 // Log returns the natural logarithm of d. 129 // 130 // Special cases are: 131 // Log(+Inf) = (+Inf+0ϵ) 132 // Log(0) = (-Inf±Infϵ) 133 // Log(x < 0) = NaN 134 // Log(NaN) = NaN 135 func Log(d Number) Number { 136 switch { 137 case d.Real == zeroQuat: 138 return Number{ 139 Real: quat.Log(d.Real), 140 Dual: quat.Inf(), 141 } 142 case quat.IsInf(d.Real): 143 return Number{ 144 Real: quat.Log(d.Real), 145 Dual: zeroQuat, 146 } 147 } 148 return Number{ 149 Real: quat.Log(d.Real), 150 Dual: quat.Mul(d.Dual, quat.Inv(d.Real)), 151 } 152 }