@@ -1039,6 +1039,11 @@ function inv(A::StridedMatrix{T}) where T
1039
1039
return Ai
1040
1040
end
1041
1041
1042
+ # helper function to perform a broadcast in-place if the destination is strided
1043
+ # otherwise, this performs an out-of-place broadcast
1044
+ @inline _broadcast!! (f, dest:: StridedArray , args... ) = broadcast! (f, dest, args... )
1045
+ @inline _broadcast!! (f, dest, args... ) = broadcast (f, args... )
1046
+
1042
1047
"""
1043
1048
cos(A::AbstractMatrix)
1044
1049
@@ -1061,19 +1066,22 @@ function cos(A::AbstractMatrix{<:Real})
1061
1066
elseif issymmetric (A)
1062
1067
return copytri! (parent (cos (Symmetric (A))), ' U' )
1063
1068
end
1064
- T = complex ( float ( eltype (A)) )
1065
- return real (exp! ( T .(im .* A) ))
1069
+ M = im .* float .(A )
1070
+ return real (exp_maybe_inplace (M ))
1066
1071
end
1067
1072
function cos (A:: AbstractMatrix{<:Complex} )
1068
1073
if isdiag (A)
1069
1074
return applydiagonal (cos, A)
1070
1075
elseif ishermitian (A)
1071
1076
return copytri! (parent (cos (Hermitian (A))), ' U' , true )
1072
1077
end
1073
- T = complex (float (eltype (A)))
1074
- X = exp! (T .(im .* A))
1075
- @. X = (X + $ exp! (T (- im* A))) / 2
1076
- return X
1078
+ M = im .* float .(A)
1079
+ N = - M
1080
+ X = exp_maybe_inplace (M)
1081
+ Y = exp_maybe_inplace (N)
1082
+ # Compute (X + Y)/2 and return the result.
1083
+ # Compute the result in-place if X is strided
1084
+ _broadcast!! ((x,y) -> (x + y)/ 2 , X, X, Y)
1077
1085
end
1078
1086
1079
1087
"""
@@ -1098,23 +1106,22 @@ function sin(A::AbstractMatrix{<:Real})
1098
1106
elseif issymmetric (A)
1099
1107
return copytri! (parent (sin (Symmetric (A))), ' U' )
1100
1108
end
1101
- T = complex ( float ( eltype (A)) )
1102
- return imag (exp! ( T .(im .* A) ))
1109
+ M = im .* float .(A )
1110
+ return imag (exp_maybe_inplace (M ))
1103
1111
end
1104
1112
function sin (A:: AbstractMatrix{<:Complex} )
1105
1113
if isdiag (A)
1106
1114
return applydiagonal (sin, A)
1107
1115
elseif ishermitian (A)
1108
1116
return copytri! (parent (sin (Hermitian (A))), ' U' , true )
1109
1117
end
1110
- T = complex (float (eltype (A)))
1111
- X = exp! (T .(im .* A))
1112
- Y = exp! (T .(.- im .* A))
1113
- @inbounds for i in eachindex (X, Y)
1114
- x, y = X[i]/ 2 , Y[i]/ 2
1115
- X[i] = Complex (imag (x)- imag (y), real (y)- real (x))
1116
- end
1117
- return X
1118
+ M = im .* float .(A)
1119
+ Mneg = - M
1120
+ X = exp_maybe_inplace (M)
1121
+ Y = exp_maybe_inplace (Mneg)
1122
+ # Compute (X - Y)/2im and return the result.
1123
+ # Compute the result in-place if X is strided
1124
+ _broadcast!! ((x,y) -> (x - y)/ 2im , X, X, Y)
1118
1125
end
1119
1126
1120
1127
"""
@@ -1144,8 +1151,8 @@ function sincos(A::AbstractMatrix{<:Real})
1144
1151
cosA = copytri! (parent (symcosA), ' U' )
1145
1152
return sinA, cosA
1146
1153
end
1147
- T = complex ( float ( eltype (A)) )
1148
- c, s = reim (exp! ( T .(im .* A) ))
1154
+ M = im .* float .(A )
1155
+ c, s = reim (exp_maybe_inplace (M ))
1149
1156
return s, c
1150
1157
end
1151
1158
function sincos (A:: AbstractMatrix{<:Complex} )
@@ -1155,16 +1162,26 @@ function sincos(A::AbstractMatrix{<:Complex})
1155
1162
cosA = copytri! (parent (hermcosA), ' U' , true )
1156
1163
return sinA, cosA
1157
1164
end
1158
- T = complex (float (eltype (A)))
1159
- X = exp! (T .(im .* A))
1160
- Y = exp! (T .(.- im .* A))
1165
+ M = im .* float .(A)
1166
+ Mneg = - M
1167
+ X = exp_maybe_inplace (M)
1168
+ Y = exp_maybe_inplace (Mneg)
1169
+ _sincos (X, Y)
1170
+ end
1171
+ function _sincos (X:: StridedMatrix , Y:: StridedMatrix )
1161
1172
@inbounds for i in eachindex (X, Y)
1162
1173
x, y = X[i]/ 2 , Y[i]/ 2
1163
1174
X[i] = Complex (imag (x)- imag (y), real (y)- real (x))
1164
1175
Y[i] = x+ y
1165
1176
end
1166
1177
return X, Y
1167
1178
end
1179
+ function _sincos (X, Y)
1180
+ T = eltype (X)
1181
+ S = T (0.5 )* im .* (Y .- X)
1182
+ C = T (0.5 ) .* (X .+ Y)
1183
+ S, C
1184
+ end
1168
1185
1169
1186
"""
1170
1187
tan(A::AbstractMatrix)
@@ -1205,8 +1222,9 @@ function cosh(A::AbstractMatrix)
1205
1222
return copytri! (parent (cosh (Hermitian (A))), ' U' , true )
1206
1223
end
1207
1224
X = exp (A)
1208
- @. X = (X + $ exp! (float (- A))) / 2
1209
- return X
1225
+ negA = @. float (- A)
1226
+ Y = exp_maybe_inplace (negA)
1227
+ _broadcast!! ((x,y) -> (x + y)/ 2 , X, X, Y)
1210
1228
end
1211
1229
1212
1230
"""
@@ -1221,8 +1239,9 @@ function sinh(A::AbstractMatrix)
1221
1239
return copytri! (parent (sinh (Hermitian (A))), ' U' , true )
1222
1240
end
1223
1241
X = exp (A)
1224
- @. X = (X - $ exp! (float (- A))) / 2
1225
- return X
1242
+ negA = @. float (- A)
1243
+ Y = exp_maybe_inplace (negA)
1244
+ _broadcast!! ((x,y) -> (x - y)/ 2 , X, X, Y)
1226
1245
end
1227
1246
1228
1247
"""
@@ -1237,15 +1256,20 @@ function tanh(A::AbstractMatrix)
1237
1256
return copytri! (parent (tanh (Hermitian (A))), ' U' , true )
1238
1257
end
1239
1258
X = exp (A)
1240
- Y = exp! (float .(.- A))
1259
+ negA = @. float (- A)
1260
+ Y = exp_maybe_inplace (negA)
1261
+ X′, Y′ = _subadd!! (X, Y)
1262
+ return X′ / Y′
1263
+ end
1264
+ function _subadd!! (X:: StridedMatrix , Y:: StridedMatrix )
1241
1265
@inbounds for i in eachindex (X, Y)
1242
1266
x, y = X[i], Y[i]
1243
1267
X[i] = x - y
1244
1268
Y[i] = x + y
1245
1269
end
1246
- X /= Y
1247
- return X
1270
+ return X, Y
1248
1271
end
1272
+ _subadd!! (X, Y) = X - Y, X + Y
1249
1273
1250
1274
"""
1251
1275
acos(A::AbstractMatrix)
0 commit comments