diff --git a/src/GradientNumber.jl b/src/GradientNumber.jl index 613725f7..057e5af8 100644 --- a/src/GradientNumber.jl +++ b/src/GradientNumber.jl @@ -201,7 +201,7 @@ end @inline calc_atan2(y::Real, x::GradientNumber) = atan2(y, value(x)) @inline calc_atan2(y::GradientNumber, x::Real) = atan2(value(y), x) -for Y in (:Real, :GradientNumber), X in (:Real, :GradientNumber) +for Y in (:GradientNumber, :Real), X in (:GradientNumber, :Real) if !(Y == :Real && X == :Real) @eval begin @inline function atan2(y::$Y, x::$X) diff --git a/src/HessianNumber.jl b/src/HessianNumber.jl index 38b3d225..418d8bfd 100644 --- a/src/HessianNumber.jl +++ b/src/HessianNumber.jl @@ -92,12 +92,6 @@ end # Multiplication # #----------------# -for T in (:Bool, :Real) - @eval begin - *(h::HessianNumber, x::$(T)) = HessianNumber(gradnum(h) * x, hess(h) * x) - *(x::$(T), h::HessianNumber) = HessianNumber(x * gradnum(h), x * hess(h)) - end -end function *{N}(h1::HessianNumber{N}, h2::HessianNumber{N}) mul_g = gradnum(h1)*gradnum(h2) @@ -118,22 +112,15 @@ function *{N}(h1::HessianNumber{N}, h2::HessianNumber{N}) return HessianNumber(mul_g, hessvec) end +for T in (:Bool, :Real) + @eval begin + *(h::HessianNumber, x::$(T)) = HessianNumber(gradnum(h) * x, hess(h) * x) + *(x::$(T), h::HessianNumber) = HessianNumber(x * gradnum(h), x * hess(h)) + end +end + # Division # #----------# -/(h::HessianNumber, x::Real) = HessianNumber(gradnum(h) / x, hess(h) / x) - -function /(x::Real, h::HessianNumber) - a = value(h) - - div_a = x / a - div_a_sq = div_a / a - div_a_cb = div_a_sq / a - - deriv1 = -div_a_sq - deriv2 = div_a_cb + div_a_cb - - return hessnum_from_deriv(h, div_a, deriv1, deriv2) -end function /{N}(h1::HessianNumber{N}, h2::HessianNumber{N}) div_g = gradnum(h1)/gradnum(h2) @@ -157,31 +144,24 @@ function /{N}(h1::HessianNumber{N}, h2::HessianNumber{N}) return HessianNumber(div_g, hessvec) end -# Exponentiation # -#----------------# -^(::Base.Irrational{:e}, h::HessianNumber) = exp(h) +/(h::HessianNumber, x::Real) = HessianNumber(gradnum(h) / x, hess(h) / x) -for T in (:Rational, :Integer, :Real) - @eval begin - function ^(h::HessianNumber, x::$(T)) - a = value(h) - x_min_one = x - 1 - exp_a = a^x - deriv1 = x * a^x_min_one - deriv2 = x * x_min_one * a^(x - 2) - return hessnum_from_deriv(h, exp_a, deriv1, deriv2) - end +function /(x::Real, h::HessianNumber) + a = value(h) - function ^(x::$(T), h::HessianNumber) - log_x = log(x) - exp_x = x^value(h) - deriv1 = exp_x * log_x - deriv2 = deriv1 * log_x - return hessnum_from_deriv(h, exp_x, deriv1, deriv2) - end - end + div_a = x / a + div_a_sq = div_a / a + div_a_cb = div_a_sq / a + + deriv1 = -div_a_sq + deriv2 = div_a_cb + div_a_cb + + return hessnum_from_deriv(h, div_a, deriv1, deriv2) end +# Exponentiation # +#----------------# + function ^{N}(h1::HessianNumber{N}, h2::HessianNumber{N}) exp_g = gradnum(h1)^gradnum(h2) hessvec = Array(eltype(exp_g), halfhesslen(N)) @@ -212,6 +192,29 @@ function ^{N}(h1::HessianNumber{N}, h2::HessianNumber{N}) return HessianNumber(exp_g, hessvec) end +^(::Base.Irrational{:e}, h::HessianNumber) = exp(h) + +for T in (:Rational, :Integer, :Real) + @eval begin + function ^(h::HessianNumber, x::$(T)) + a = value(h) + x_min_one = x - 1 + exp_a = a^x + deriv1 = x * a^x_min_one + deriv2 = x * x_min_one * a^(x - 2) + return hessnum_from_deriv(h, exp_a, deriv1, deriv2) + end + + function ^(x::$(T), h::HessianNumber) + log_x = log(x) + exp_x = x^value(h) + deriv1 = exp_x * log_x + deriv2 = deriv1 * log_x + return hessnum_from_deriv(h, exp_x, deriv1, deriv2) + end + end +end + # Unary functions on HessianNumbers # #-----------------------------------# # the second derivatives of functions in @@ -261,7 +264,7 @@ end @inline calc_atan2(y::Real, x::HessianNumber) = calc_atan2(y, gradnum(x)) @inline calc_atan2(y::HessianNumber, x::Real) = calc_atan2(gradnum(y), x) -for Y in (:Real, :HessianNumber), X in (:Real, :HessianNumber) +for Y in (:HessianNumber, :Real), X in (:HessianNumber, :Real) if !(Y == :Real && X == :Real) @eval begin function atan2(y::$Y, x::$X) diff --git a/src/TensorNumber.jl b/src/TensorNumber.jl index a1c12fc3..ba33a984 100644 --- a/src/TensorNumber.jl +++ b/src/TensorNumber.jl @@ -101,13 +101,6 @@ end # Multiplication # #----------------# -for T in (:Bool, :Real) - @eval begin - *(t::TensorNumber, x::$(T)) = TensorNumber(hessnum(t) * x, tens(t) * x) - *(x::$(T), t::TensorNumber) = TensorNumber(x * hessnum(t), x * tens(t)) - end -end - function *{N}(t1::TensorNumber{N}, t2::TensorNumber{N}) mul_h = hessnum(t1)*hessnum(t2) tensvec = Array(eltype(mul_h), halftenslen(N)) @@ -134,23 +127,15 @@ function *{N}(t1::TensorNumber{N}, t2::TensorNumber{N}) return TensorNumber(mul_h, tensvec) end -# Division # -#----------# -/(t::TensorNumber, x::Real) = TensorNumber(hessnum(t) / x, tens(t) / x) - -function /(x::Real, t::TensorNumber) - a = value(t) - div_a = x / a - div_a_sq = div_a / a - div_a_cb = div_a_sq / a - - deriv1 = -div_a_sq - deriv2 = div_a_cb + div_a_cb - deriv3 = -(deriv2 + deriv2 + deriv2)/a - - return tensnum_from_deriv(t, div_a, deriv1, deriv2, deriv3) +for T in (:Bool, :Real) + @eval begin + *(t::TensorNumber, x::$(T)) = TensorNumber(hessnum(t) * x, tens(t) * x) + *(x::$(T), t::TensorNumber) = TensorNumber(x * hessnum(t), x * tens(t)) + end end +# Division # +#----------# function /{N}(t1::TensorNumber{N}, t2::TensorNumber{N}) div_h = hessnum(t1)/hessnum(t2) tensvec = Array(eltype(div_h), halftenslen(N)) @@ -187,39 +172,23 @@ function /{N}(t1::TensorNumber{N}, t2::TensorNumber{N}) return TensorNumber(div_h, tensvec) end -# Exponentiation # -#----------------# -^(::Base.Irrational{:e}, t::TensorNumber) = exp(t) - -for T in (:Rational, :Integer, :Real) - @eval begin - function ^(t::TensorNumber, x::$(T)) - a = value(t) - x_min_one = x - 1 - x_min_two = x - 2 - x_x_min_one = x * x_min_one - - exp_a = a^x - deriv1 = x * a^x_min_one - deriv2 = x_x_min_one * a^x_min_two - deriv3 = x_x_min_one * x_min_two * a^(x - 3) - - return tensnum_from_deriv(t, exp_a, deriv1, deriv2, deriv3) - end +/(t::TensorNumber, x::Real) = TensorNumber(hessnum(t) / x, tens(t) / x) - function ^(x::$(T), t::TensorNumber) - log_x = log(x) +function /(x::Real, t::TensorNumber) + a = value(t) + div_a = x / a + div_a_sq = div_a / a + div_a_cb = div_a_sq / a - exp_x = x^value(t) - deriv1 = exp_x * log_x - deriv2 = deriv1 * log_x - deriv3 = deriv2 * log_x + deriv1 = -div_a_sq + deriv2 = div_a_cb + div_a_cb + deriv3 = -(deriv2 + deriv2 + deriv2)/a - return tensnum_from_deriv(t, exp_x, deriv1, deriv2, deriv3) - end - end + return tensnum_from_deriv(t, div_a, deriv1, deriv2, deriv3) end +# Exponentiation # +#----------------# function ^{N}(t1::TensorNumber{N}, t2::TensorNumber{N}) exp_h = hessnum(t1)^hessnum(t2) tensvec = Array(eltype(exp_h), halftenslen(N)) @@ -273,6 +242,37 @@ function ^{N}(t1::TensorNumber{N}, t2::TensorNumber{N}) return TensorNumber(exp_h, tensvec) end +^(::Base.Irrational{:e}, t::TensorNumber) = exp(t) + +for T in (:Rational, :Integer, :Real) + @eval begin + function ^(t::TensorNumber, x::$(T)) + a = value(t) + x_min_one = x - 1 + x_min_two = x - 2 + x_x_min_one = x * x_min_one + + exp_a = a^x + deriv1 = x * a^x_min_one + deriv2 = x_x_min_one * a^x_min_two + deriv3 = x_x_min_one * x_min_two * a^(x - 3) + + return tensnum_from_deriv(t, exp_a, deriv1, deriv2, deriv3) + end + + function ^(x::$(T), t::TensorNumber) + log_x = log(x) + + exp_x = x^value(t) + deriv1 = exp_x * log_x + deriv2 = deriv1 * log_x + deriv3 = deriv2 * log_x + + return tensnum_from_deriv(t, exp_x, deriv1, deriv2, deriv3) + end + end +end + # Unary functions on TensorNumbers # #----------------------------------# # the third derivatives of functions in unsupported_unary_tens_funcs @@ -325,7 +325,7 @@ end @inline calc_atan2(y::Real, x::TensorNumber) = calc_atan2(y, hessnum(x)) @inline calc_atan2(y::TensorNumber, x::Real) = calc_atan2(hessnum(y), x) -for Y in (:Real, :TensorNumber), X in (:Real, :TensorNumber) +for Y in (:TensorNumber, :Real), X in (:TensorNumber, :Real) if !(Y == :Real && X == :Real) @eval begin function atan2(y::$Y, x::$X)