|
78 | 78 |
|
79 | 79 | function finite_difference!{T<:Real}(df::StridedArray{T}, f, x::StridedArray{T}, ::Type{Val{:forward}})
|
80 | 80 | eps_cbrt = cbrt(eps(T))
|
81 |
| - @fastmath @inbounds for i in 1 : length(x) |
| 81 | + @inbounds for i in 1 : length(x) |
82 | 82 | epsilon = compute_epsilon(Val{:forward}, x[i], eps_cbrt)
|
83 | 83 | epsilon_inv = one(T) / epsilon
|
84 | 84 | x_plus = x[i] + epsilon
|
|
89 | 89 |
|
90 | 90 | function finite_difference!{T<:Real}(df::StridedArray{T}, f, x::StridedArray{T}, ::Type{Val{:forward}}, fx::StridedArray{T})
|
91 | 91 | eps_cbrt = cbrt(eps(T))
|
92 |
| - @fastmath @inbounds for i in 1 : length(x) |
| 92 | + @inbounds for i in 1 : length(x) |
93 | 93 | epsilon = compute_epsilon(Val{:forward}, x[i], eps_cbrt)
|
94 | 94 | epsilon_inv = one(T) / epsilon
|
95 | 95 | x_plus = x[i] + epsilon
|
|
123 | 123 |
|
124 | 124 |
|
125 | 125 | #=
|
126 |
| -Compute the Jacobian matrix of a real-valued callable f. |
| 126 | +Compute the Jacobian matrix of a real-valued callable f: R^n -> R^m. |
127 | 127 | =#
|
128 |
| -# TODO |
| 128 | +function finite_difference_jacobian{T<:Real}(f, x::AbstractArray{T}, t::DataType) |
| 129 | + fx = f.(x) |
| 130 | + J = zeros(T, length(fx), length(x)) |
| 131 | + finite_difference_jacobian!(J, f, x, t, fx) |
| 132 | +end |
| 133 | + |
| 134 | +function finite_difference_jacobian!{T<:Real}(J::AbstractArray{T}, f, x::AbstractArray{T}, t::DataType, fx::AbstractArray{T}) |
| 135 | + m, n = size(J) |
| 136 | + if t == Val{:forward} |
| 137 | + shifted_x = copy(x) |
| 138 | + eps_sqrt = sqrt(eps(T)) |
| 139 | + for i in 1 : n |
| 140 | + epsilon = compute_epsilon(t, x, eps_sqrt) |
| 141 | + shifted_x[i] += epsilon |
| 142 | + @. J[:, i] = (f(shifted_x) - f_x) / epsilon |
| 143 | + shifted_x[i] = x[i] |
| 144 | + end |
| 145 | + elseif t == Val{:central} |
| 146 | + shifted_x_plus = copy(x) |
| 147 | + shifted_x_minus = copy(x) |
| 148 | + eps_cbrt = cbrt(eps(T)) |
| 149 | + for i in 1 : n |
| 150 | + epsilon = compute_epsilon(t, x, eps_cbrt) |
| 151 | + shifted_x_plus[i] += epsilon |
| 152 | + shifted_x_minus[i] -= epsilon |
| 153 | + @. J[:, i] = (f(shifted_x_plus) - f(shifted_x_minus)) / (epsilon + epsilon) |
| 154 | + shifted_x_plus[i] = x[i] |
| 155 | + shifted_x_minus[i] = x[i] |
| 156 | + end |
| 157 | + end |
| 158 | + J |
| 159 | +end |
| 160 | + |
| 161 | +function finite_difference_jacobian{T<:Real}(f, x::StridedArray{T}, t::DataType, fx::StridedArray{T}) |
| 162 | + J = zeros(T, length(fx), length(x)) |
| 163 | + finite_difference_jacobian!(J, f, x, t, fx) |
| 164 | +end |
| 165 | + |
| 166 | +function finite_difference_jacobian!{T<:Real}(J::StridedArray{T}, f, x::StridedArray{T}, ::Type{Val{:forward}}, fx::StridedArray{T}) |
| 167 | + m, n = size(J) |
| 168 | + eps_sqrt = sqrt(eps(T)) |
| 169 | + @inbounds for i = 1 : n |
| 170 | + epsilon = compute_epsilon(Val{:forward}, x[i], eps_sqrt) |
| 171 | + epsilon_inv = one(T) / epsilon |
| 172 | + for j in 1 : m |
| 173 | + if i == j |
| 174 | + J[j,i] = (f(x[j]+epsilon) - fx[j]) * epsilon_inv |
| 175 | + else |
| 176 | + J[j,i] = zero(T) |
| 177 | + end |
| 178 | + end |
| 179 | + end |
| 180 | + J |
| 181 | +end |
| 182 | + |
| 183 | +function finite_difference_jacobian!{T<:Real}(J::StridedArray{T}, f, x::StridedArray{T}, ::Type{Val{:central}}, ::Union{Void,StridedArray{T}}=nothing) |
| 184 | + m, n = size(J) |
| 185 | + eps_cbrt = cbrt(eps(T)) |
| 186 | + @inbounds for i = 1 : n |
| 187 | + epsilon = compute_epsilon(Val{:central}, x[i], eps_cbrt) |
| 188 | + epsilon_double_inv = one(T) / (2 * epsilon) |
| 189 | + for j in 1 : m |
| 190 | + if i==j |
| 191 | + J[j,i] = (f(x[j]+epsilon) - f(x[j]-epsilon)) * epsilon_double_inv |
| 192 | + else |
| 193 | + J[j,i] = zero(T) |
| 194 | + end |
| 195 | + end |
| 196 | + end |
| 197 | + J |
| 198 | +end |
| 199 | + |
| 200 | +# TODO: Jacobians for complex-valued callables |
0 commit comments