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  }