@@ -131,44 +131,66 @@ bvt boolbvt::convert_floatbv_op(const ieee_float_op_exprt &expr)
131
131
sub_width > 0 && width % sub_width == 0 ,
132
132
" width of a complex subtype must be positive and evenly divide the "
133
133
" width of the complex expression" );
134
+ DATA_INVARIANT (
135
+ sub_width * 2 == width, " a complex type consists of exactly two parts" );
136
+
137
+ bvt lhs_real{lhs_as_bv.begin (), lhs_as_bv.begin () + sub_width};
138
+ bvt rhs_real{rhs_as_bv.begin (), rhs_as_bv.begin () + sub_width};
134
139
135
- std::size_t size=width/sub_width;
136
- bvt result_bv;
137
- result_bv.resize (width);
140
+ bvt lhs_imag{lhs_as_bv.begin () + sub_width, lhs_as_bv.end ()};
141
+ bvt rhs_imag{rhs_as_bv.begin () + sub_width, rhs_as_bv.end ()};
138
142
139
- for (std::size_t i=0 ; i<size; i++)
143
+ bvt result_real, result_imag;
144
+
145
+ if (expr.id () == ID_floatbv_plus || expr.id () == ID_floatbv_minus)
146
+ {
147
+ result_real = float_utils.add_sub (
148
+ lhs_real, rhs_real, expr.id () == ID_floatbv_minus);
149
+ result_imag = float_utils.add_sub (
150
+ lhs_imag, rhs_imag, expr.id () == ID_floatbv_minus);
151
+ }
152
+ else if (expr.id () == ID_floatbv_mult)
153
+ {
154
+ // Could be optimised to just three multiplications with more additions
155
+ // instead, but then we'd have to worry about the impact of possible
156
+ // overflows. So we use the naive approach for now:
157
+ result_real = float_utils.add_sub (
158
+ float_utils.mul (lhs_real, rhs_real),
159
+ float_utils.mul (lhs_imag, rhs_imag),
160
+ true );
161
+ result_imag = float_utils.add_sub (
162
+ float_utils.mul (lhs_real, rhs_imag),
163
+ float_utils.mul (lhs_imag, rhs_real),
164
+ false );
165
+ }
166
+ else if (expr.id () == ID_floatbv_div)
140
167
{
141
- bvt lhs_sub_bv, rhs_sub_bv, sub_result_bv;
142
-
143
- lhs_sub_bv.assign (
144
- lhs_as_bv.begin () + i * sub_width,
145
- lhs_as_bv.begin () + (i + 1 ) * sub_width);
146
- rhs_sub_bv.assign (
147
- rhs_as_bv.begin () + i * sub_width,
148
- rhs_as_bv.begin () + (i + 1 ) * sub_width);
149
-
150
- if (expr.id ()==ID_floatbv_plus)
151
- sub_result_bv = float_utils.add_sub (lhs_sub_bv, rhs_sub_bv, false );
152
- else if (expr.id ()==ID_floatbv_minus)
153
- sub_result_bv = float_utils.add_sub (lhs_sub_bv, rhs_sub_bv, true );
154
- else if (expr.id ()==ID_floatbv_mult)
155
- sub_result_bv = float_utils.mul (lhs_sub_bv, rhs_sub_bv);
156
- else if (expr.id ()==ID_floatbv_div)
157
- sub_result_bv = float_utils.div (lhs_sub_bv, rhs_sub_bv);
158
- else
159
- UNREACHABLE;
160
-
161
- INVARIANT (
162
- sub_result_bv.size () == sub_width,
163
- " we constructed a new complex of the right size" );
164
- INVARIANT (
165
- i * sub_width + sub_width - 1 < result_bv.size (),
166
- " the sub-bitvector fits into the result bitvector" );
167
- std::copy (
168
- sub_result_bv.begin (),
169
- sub_result_bv.end (),
170
- result_bv.begin () + i * sub_width);
168
+ bvt numerator_real = float_utils.add_sub (
169
+ float_utils.mul (lhs_real, rhs_real),
170
+ float_utils.mul (lhs_imag, rhs_imag),
171
+ false );
172
+ bvt numerator_imag = float_utils.add_sub (
173
+ float_utils.mul (lhs_imag, rhs_real),
174
+ float_utils.mul (lhs_real, rhs_imag),
175
+ true );
176
+
177
+ bvt denominator = float_utils.add_sub (
178
+ float_utils.mul (rhs_real, rhs_real),
179
+ float_utils.mul (rhs_imag, rhs_imag),
180
+ false );
181
+
182
+ result_real = float_utils.div (numerator_real, denominator);
183
+ result_imag = float_utils.div (numerator_imag, denominator);
171
184
}
185
+ else
186
+ UNREACHABLE;
187
+
188
+ bvt result_bv = std::move (result_real);
189
+ result_bv.reserve (width);
190
+ result_bv.insert (
191
+ result_bv.end (),
192
+ std::make_move_iterator (result_imag.begin ()),
193
+ std::make_move_iterator (result_imag.end ()));
172
194
173
195
return result_bv;
174
196
}
0 commit comments