@@ -1125,3 +1125,190 @@ function complex(A::AbstractArray{T}) where T
1125
1125
end
1126
1126
convert (AbstractArray{typeof (complex (zero (T)))}, A)
1127
1127
end
1128
+
1129
+ const ComplexFloat = Complex{<: AbstractFloat }
1130
+
1131
+ # # Multi-word floating-point for `Complex`
1132
+
1133
+ complex_twiceprec (real:: Tw , imag:: Tw ) where {Tw<: TwicePrecision{<:AbstractFloat} } =
1134
+ TwicePrecision (
1135
+ complex (real. hi, imag. hi),
1136
+ complex (real. lo, imag. lo),
1137
+ )
1138
+
1139
+ real (c:: TwicePrecision{<:ComplexFloat} ) =
1140
+ TwicePrecision (real (c. hi), real (c. lo))
1141
+
1142
+ imag (c:: TwicePrecision{<:ComplexFloat} ) =
1143
+ TwicePrecision (imag (c. hi), imag (c. lo))
1144
+
1145
+ # +
1146
+
1147
+ function + (x:: TwicePrecision{<:AbstractFloat} , y:: ComplexFloat )
1148
+ y_re = real (y)
1149
+ y_im = imag (y)
1150
+ sum = x + y_re
1151
+ TwicePrecision (complex (sum. hi, y_im), complex (sum. lo))
1152
+ end
1153
+
1154
+ function + (
1155
+ x:: TwicePrecision{<:ComplexFloat} ,
1156
+ y:: Union{AbstractFloat,TwicePrecision{<:AbstractFloat}} ,
1157
+ )
1158
+ x_re = real (x)
1159
+ x_im = imag (x)
1160
+ sum = x_re + y
1161
+ complex_twiceprec (sum, x_im)
1162
+ end
1163
+
1164
+ + (x:: TwicePrecision{T} , y:: T ) where {T<: ComplexFloat } =
1165
+ TwicePrecision (mw_operate (+ , Tuple (x), (y,))... )
1166
+
1167
+ + (x:: TwicePrecision{<:AbstractFloat} , y:: TwicePrecision{<:ComplexFloat} ) =
1168
+ y + x
1169
+
1170
+ + (x:: Tw , y:: Tw ) where {Tw<: TwicePrecision{<:ComplexFloat} } =
1171
+ TwicePrecision (mw_operate (+ , Tuple (x), Tuple (y))... )
1172
+
1173
+ # -
1174
+
1175
+ - (x:: TwicePrecision{<:AbstractFloat} , y:: ComplexFloat ) =
1176
+ x + - y
1177
+
1178
+ - (x:: TwicePrecision{<:ComplexFloat} , y:: Union{AbstractFloat,ComplexFloat} ) =
1179
+ x + - y
1180
+
1181
+ - (
1182
+ x:: TwicePrecision{<:ComplexFloat} ,
1183
+ y:: TwicePrecision{<:Union{AbstractFloat,ComplexFloat}} ,
1184
+ ) =
1185
+ x + - y
1186
+
1187
+ - (x:: TwicePrecision{<:ComplexFloat} , y:: TwicePrecision{<:AbstractFloat} ) =
1188
+ x + - y
1189
+
1190
+ # *
1191
+
1192
+ function * (x:: TwicePrecision{<:AbstractFloat} , y:: ComplexFloat )
1193
+ y_re = real (y)
1194
+ y_im = imag (y)
1195
+ res_re = x * y_re
1196
+ res_im = x * y_im
1197
+ complex_twiceprec (res_re, res_im)
1198
+ end
1199
+
1200
+ function * (
1201
+ x:: TwicePrecision{<:ComplexFloat} ,
1202
+ y:: Union{AbstractFloat,TwicePrecision{<:AbstractFloat}} ,
1203
+ )
1204
+ x_re = real (x)
1205
+ x_im = imag (x)
1206
+ res_re = x_re * y
1207
+ res_im = x_im * y
1208
+ complex_twiceprec (res_re, res_im)
1209
+ end
1210
+
1211
+ function * (x:: Tw , y:: Union{T,Tw} ) where {T<: ComplexFloat ,Tw<: TwicePrecision{T} }
1212
+ # TODO : evaluate whether it makes sense to write custom code, with
1213
+ # separate methods for `*(x::Tw, y::T)` and `*(x::Tw, y::Tw)`.
1214
+
1215
+ # TODO : try preventing some overflows and underflows?
1216
+
1217
+ # TODO : for `*(x::Tw, y::T)`: evaluate whether it makes sense to
1218
+ # use Algorithm 3 from the paper "Accurate Complex Multiplication
1219
+ # in Floating-Point Arithmetic", https://hal.science/hal-02001080v2
1220
+ # The algorithm must first be adapted to return double-word results
1221
+ # as explained in the same paper.
1222
+
1223
+ x_re = real (x)
1224
+ x_im = imag (x)
1225
+ y_re = real (y)
1226
+ y_im = imag (y)
1227
+ res_re = x_re* y_re - x_im* y_im
1228
+ res_im = x_im* y_re + x_re* y_im
1229
+ complex_twiceprec (res_re, res_im)
1230
+ end
1231
+
1232
+ * (x:: TwicePrecision{<:AbstractFloat} , y:: TwicePrecision{<:ComplexFloat} ) =
1233
+ y * x
1234
+
1235
+ # abs2
1236
+
1237
+ function abs2 (x:: TwicePrecision{<:ComplexFloat} )
1238
+ # TODO : evaluate whether it makes sense to write custom code
1239
+
1240
+ # TODO : try preventing some overflows and underflows?
1241
+
1242
+ re = real (x)
1243
+ im = imag (x)
1244
+ re* re + im* im
1245
+ end
1246
+
1247
+ # /
1248
+
1249
+ function div_complex_twiceprec_impl (
1250
+ x:: Union{AbstractFloat,TwicePrecision{<:AbstractFloat}} ,
1251
+ y,
1252
+ )
1253
+ # TODO : use the inverse of abs2 instead for better performance?
1254
+ a = abs2 (y)
1255
+
1256
+ y_re = real (y)
1257
+ y_im = imag (y)
1258
+ res_re = x* y_re/ a
1259
+ res_im = - x* y_im/ a
1260
+ complex_twiceprec (res_re, res_im)
1261
+ end
1262
+
1263
+ function div_complex_twiceprec_impl (
1264
+ x:: Union{ComplexFloat,TwicePrecision{<:ComplexFloat}} ,
1265
+ y,
1266
+ )
1267
+ # TODO : use the inverse of abs2 instead for better performance?
1268
+ a = abs2 (y)
1269
+
1270
+ x_re = real (x)
1271
+ x_im = imag (x)
1272
+ y_re = real (y)
1273
+ y_im = imag (y)
1274
+ res_re = (x_re* y_re + x_im* y_im) / a
1275
+ res_im = (x_im* y_re - x_re* y_im) / a
1276
+ complex_twiceprec (res_re, res_im)
1277
+ end
1278
+
1279
+ / (
1280
+ x:: TwicePrecision{<:AbstractFloat} ,
1281
+ y:: Union{ComplexFloat,TwicePrecision{<:ComplexFloat}} ,
1282
+ ) =
1283
+ # TODO : evaluate whether it makes sense to write custom code
1284
+ # TODO : try preventing some overflows and underflows?
1285
+ div_complex_twiceprec_impl (x, y)
1286
+
1287
+ / (
1288
+ x:: AbstractFloat ,
1289
+ y:: TwicePrecision{<:ComplexFloat} ,
1290
+ ) =
1291
+ # TODO : evaluate whether it makes sense to write custom code
1292
+ # TODO : try preventing some overflows and underflows?
1293
+ div_complex_twiceprec_impl (x, y)
1294
+
1295
+ function / (
1296
+ x:: TwicePrecision{<:ComplexFloat} ,
1297
+ y:: Union{AbstractFloat,TwicePrecision{<:AbstractFloat}} ,
1298
+ )
1299
+ x_re = real (x)
1300
+ x_im = imag (x)
1301
+ res_re = x_re / y
1302
+ res_im = x_im / y
1303
+ complex_twiceprec (res_re, res_im)
1304
+ end
1305
+
1306
+ / (x:: Tw , y:: Union{T,Tw} ) where {T<: ComplexFloat ,Tw<: TwicePrecision{T} } =
1307
+ # TODO : evaluate whether it makes sense to write custom code
1308
+ # TODO : try preventing some overflows and underflows?
1309
+ div_complex_twiceprec_impl (x, y)
1310
+
1311
+ / (x:: ComplexFloat , y:: TwicePrecision{<:ComplexFloat} ) =
1312
+ # TODO : evaluate whether it makes sense to write custom code
1313
+ # TODO : try preventing some overflows and underflows?
1314
+ div_complex_twiceprec_impl (x, y)
0 commit comments