From 5d069df45240102db3fd1b6bafbcffc79353f347 Mon Sep 17 00:00:00 2001 From: Michael Tautschnig Date: Thu, 11 Jul 2024 10:38:40 +0000 Subject: [PATCH] Fix multiplication and division of complex numbers Multiplication and division of complex numbers are not just pointwise applications of those operations. Fixes: #8375 --- regression/cbmc/complex2/main.c | 15 ++++ regression/cbmc/complex2/test.desc | 8 ++ src/solvers/flattening/boolbv_floatbv_op.cpp | 90 ++++++++++++-------- 3 files changed, 79 insertions(+), 34 deletions(-) create mode 100644 regression/cbmc/complex2/main.c create mode 100644 regression/cbmc/complex2/test.desc diff --git a/regression/cbmc/complex2/main.c b/regression/cbmc/complex2/main.c new file mode 100644 index 00000000000..d7d128319ff --- /dev/null +++ b/regression/cbmc/complex2/main.c @@ -0,0 +1,15 @@ +#include + +int main() +{ + char choice; + float re = choice ? 1.3f : 2.1f; // a non-constant well-behaved float + float complex z1 = I + re; + float complex z2 = z1 * z1; + float complex expected = 2 * I * re + re * re - 1; // (a+i)^2 = 2ai + a^2 - 1 + float complex actual = + re * re + I; // (a1 + b1*i)*(a2 + b2*i) = (a1*a2 + b1*b2*i) + __CPROVER_assert(z2 == expected, "right"); + __CPROVER_assert(z2 == actual, "wrong"); + return 0; +} diff --git a/regression/cbmc/complex2/test.desc b/regression/cbmc/complex2/test.desc new file mode 100644 index 00000000000..9efefbc7362 --- /dev/null +++ b/regression/cbmc/complex2/test.desc @@ -0,0 +1,8 @@ +CORE +main.c + +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- +^warning: ignoring diff --git a/src/solvers/flattening/boolbv_floatbv_op.cpp b/src/solvers/flattening/boolbv_floatbv_op.cpp index e42479573f5..7a18e0ca5f4 100644 --- a/src/solvers/flattening/boolbv_floatbv_op.cpp +++ b/src/solvers/flattening/boolbv_floatbv_op.cpp @@ -131,44 +131,66 @@ bvt boolbvt::convert_floatbv_op(const ieee_float_op_exprt &expr) sub_width > 0 && width % sub_width == 0, "width of a complex subtype must be positive and evenly divide the " "width of the complex expression"); + DATA_INVARIANT( + sub_width * 2 == width, "a complex type consists of exactly two parts"); + + bvt lhs_real{lhs_as_bv.begin(), lhs_as_bv.begin() + sub_width}; + bvt rhs_real{rhs_as_bv.begin(), rhs_as_bv.begin() + sub_width}; - std::size_t size=width/sub_width; - bvt result_bv; - result_bv.resize(width); + bvt lhs_imag{lhs_as_bv.begin() + sub_width, lhs_as_bv.end()}; + bvt rhs_imag{rhs_as_bv.begin() + sub_width, rhs_as_bv.end()}; - for(std::size_t i=0; i