11#include " complex_numbers.h"
22
33#include < cmath>
4+ #include < sstream>
45
56#ifdef EXERCISM_TEST_SUITE
67#include < catch2/catch.hpp>
@@ -22,12 +23,35 @@ using complex_numbers::Complex;
2223
2324// Define a margin to use for float comparisons. Catch does not compute a good
2425// epsilon for float values near 0.
25- static const double eps = 0.005 ;
26+ static constexpr double eps = 0.005 ;
2627
27- // Helper function for comparing Complex numbers with approximate float values.
28- static void require_approx_equal (const Complex& lhs, const Complex& rhs) {
29- REQUIRE_THAT (lhs.real (), Catch::Matchers::WithinAbs (rhs.real (), eps));
30- REQUIRE_THAT (lhs.imag (), Catch::Matchers::WithinAbs (rhs.imag (), eps));
28+ // Custom Catch2 matcher for approximate equality of Complex numbers
29+ class ComplexApproxMatcher : public Catch ::MatcherBase<Complex> {
30+ public:
31+ ComplexApproxMatcher (const Complex& expected, double epsilon)
32+ : expected{expected}, epsilon{epsilon} {}
33+
34+ bool match (const Complex& actual) const override {
35+ return std::abs (actual.real () - expected.real ()) <= epsilon &&
36+ std::abs (actual.imag () - expected.imag ()) <= epsilon;
37+ }
38+
39+ std::string describe () const override {
40+ std::ostringstream ss;
41+ ss << " is approximately equal to (" << expected.real () << " , "
42+ << expected.imag () << " i) with epsilon " << epsilon;
43+ return ss.str ();
44+ }
45+
46+ private:
47+ Complex expected;
48+ double epsilon;
49+ };
50+
51+ // Helper function to create the matcher
52+ inline ComplexApproxMatcher ComplexWithinAbs (const Complex& expected,
53+ double epsilon) {
54+ return ComplexApproxMatcher{expected, epsilon};
3155}
3256
3357TEST_CASE (" Real part -> Real part of a purely real number" ,
@@ -78,47 +102,47 @@ TEST_CASE("Imaginary unit", "[a39b7fd6-6527-492f-8c34-609d2c913879]") {
78102 const Complex c1{0.0 , 1.0 };
79103 const Complex c2{0.0 , 1.0 };
80104
81- require_approx_equal ( Complex ( -1.0 , 0.0 ), c1 * c2 );
105+ REQUIRE_THAT (c1 * c2, ComplexWithinAbs (Complex{ -1.0 , 0.0 }, eps) );
82106}
83107
84108TEST_CASE (" Arithmetic -> Addition -> Add purely real numbers" ,
85109 " [9a2c8de9-f068-4f6f-b41c-82232cc6c33e]" ) {
86110 const Complex c1{1.0 , 0.0 };
87111 const Complex c2{2.0 , 0.0 };
88112
89- require_approx_equal ( Complex ( 3.0 , 0.0 ), c1 + c2 );
113+ REQUIRE_THAT (c1 + c2, ComplexWithinAbs (Complex{ 3.0 , 0.0 }, eps) );
90114}
91115
92116TEST_CASE (" Arithmetic -> Addition -> Add purely imaginary numbers" ,
93117 " [657c55e1-b14b-4ba7-bd5c-19db22b7d659]" ) {
94118 const Complex c1{0.0 , 1.0 };
95119 const Complex c2{0.0 , 2.0 };
96120
97- require_approx_equal ( Complex ( 0.0 , 3.0 ), c1 + c2 );
121+ REQUIRE_THAT (c1 + c2, ComplexWithinAbs (Complex{ 0.0 , 3.0 }, eps) );
98122}
99123
100124TEST_CASE (" Arithmetic -> Addition -> Add numbers with real and imaginary part" ,
101125 " [4e1395f5-572b-4ce8-bfa9-9a63056888da]" ) {
102126 const Complex c1{1.0 , 2.0 };
103127 const Complex c2{3.0 , 4.0 };
104128
105- require_approx_equal ( Complex ( 4.0 , 6.0 ), c1 + c2 );
129+ REQUIRE_THAT (c1 + c2, ComplexWithinAbs (Complex{ 4.0 , 6.0 }, eps) );
106130}
107131
108132TEST_CASE (" Arithmetic -> Subtraction -> Subtract purely real numbers" ,
109133 " [1155dc45-e4f7-44b8-af34-a91aa431475d]" ) {
110134 const Complex c1{1.0 , 0.0 };
111135 const Complex c2{2.0 , 0.0 };
112136
113- require_approx_equal ( Complex ( -1.0 , 0.0 ), c1 - c2 );
137+ REQUIRE_THAT (c1 - c2, ComplexWithinAbs (Complex{ -1.0 , 0.0 }, eps) );
114138}
115139
116140TEST_CASE (" Arithmetic -> Subtraction -> Subtract purely imaginary numbers" ,
117141 " [f95e9da8-acd5-4da4-ac7c-c861b02f774b]" ) {
118142 const Complex c1{0.0 , 1.0 };
119143 const Complex c2{0.0 , 2.0 };
120144
121- require_approx_equal ( Complex ( 0.0 , -1.0 ), c1 - c2 );
145+ REQUIRE_THAT (c1 - c2, ComplexWithinAbs (Complex{ 0.0 , -1.0 }, eps) );
122146}
123147
124148TEST_CASE (
@@ -129,23 +153,23 @@ TEST_CASE(
129153 const Complex c1{1.0 , 2.0 };
130154 const Complex c2{3.0 , 4.0 };
131155
132- require_approx_equal ( Complex ( -2.0 , -2.0 ), c1 - c2 );
156+ REQUIRE_THAT (c1 - c2, ComplexWithinAbs (Complex{ -2.0 , -2.0 }, eps) );
133157}
134158
135159TEST_CASE (" Arithmetic -> Multiplication -> Multiply purely real numbers" ,
136160 " [8a0366c0-9e16-431f-9fd7-40ac46ff4ec4]" ) {
137161 const Complex c1{1.0 , 0.0 };
138162 const Complex c2{2.0 , 0.0 };
139163
140- require_approx_equal ( Complex ( 2.0 , 0.0 ), c1 * c2 );
164+ REQUIRE_THAT (c1 * c2, ComplexWithinAbs (Complex{ 2.0 , 0.0 }, eps) );
141165}
142166
143167TEST_CASE (" Arithmetic -> Multiplication -> Multiply purely imaginary numbers" ,
144168 " [e560ed2b-0b80-4b4f-90f2-63cefc911aaf]" ) {
145169 const Complex c1{0.0 , 1.0 };
146170 const Complex c2{0.0 , 2.0 };
147171
148- require_approx_equal ( Complex ( -2.0 , 0.0 ), c1 * c2 );
172+ REQUIRE_THAT (c1 * c2, ComplexWithinAbs (Complex{ -2.0 , 0.0 }, eps) );
149173}
150174
151175TEST_CASE (
@@ -156,23 +180,23 @@ TEST_CASE(
156180 const Complex c1{1.0 , 2.0 };
157181 const Complex c2{3.0 , 4.0 };
158182
159- require_approx_equal ( Complex ( -5.0 , 10.0 ), c1 * c2 );
183+ REQUIRE_THAT (c1 * c2, ComplexWithinAbs (Complex{ -5.0 , 10.0 }, eps) );
160184}
161185
162186TEST_CASE (" Arithmetic -> Division -> Divide purely real numbers" ,
163187 " [b0571ddb-9045-412b-9c15-cd1d816d36c1]" ) {
164188 const Complex c1{1.0 , 0.0 };
165189 const Complex c2{2.0 , 0.0 };
166190
167- require_approx_equal ( Complex ( 0.5 , 0.0 ), c1 / c2 );
191+ REQUIRE_THAT (c1 / c2, ComplexWithinAbs (Complex{ 0.5 , 0.0 }, eps) );
168192}
169193
170194TEST_CASE (" Arithmetic -> Division -> Divide purely imaginary numbers" ,
171195 " [5bb4c7e4-9934-4237-93cc-5780764fdbdd]" ) {
172196 const Complex c1{0.0 , 1.0 };
173197 const Complex c2{0.0 , 2.0 };
174198
175- require_approx_equal ( Complex ( 0.5 , 0.0 ), c1 / c2 );
199+ REQUIRE_THAT (c1 / c2, ComplexWithinAbs (Complex{ 0.5 , 0.0 }, eps) );
176200}
177201
178202TEST_CASE (
@@ -181,7 +205,7 @@ TEST_CASE(
181205 const Complex c1{1.0 , 2.0 };
182206 const Complex c2{3.0 , 4.0 };
183207
184- require_approx_equal ( Complex ( 0.44 , 0.08 ), c1 / c2 );
208+ REQUIRE_THAT (c1 / c2, ComplexWithinAbs (Complex{ 0.44 , 0.08 }, eps) );
185209}
186210
187211TEST_CASE (" Absolute value -> Absolute value of a positive purely real number" ,
@@ -230,43 +254,43 @@ TEST_CASE("Complex conjugate -> Conjugate a purely real number",
230254 " [fb2d0792-e55a-4484-9443-df1eddfc84a2]" ) {
231255 const Complex c{5.0 , 0.0 };
232256
233- require_approx_equal ( Complex ( 5.0 , 0.0 ), c. conj ( ));
257+ REQUIRE_THAT (c. conj (), ComplexWithinAbs (Complex{ 5.0 , 0.0 }, eps ));
234258}
235259
236260TEST_CASE (" Complex conjugate -> Conjugate a purely imaginary number" ,
237261 " [e37fe7ac-a968-4694-a460-66cb605f8691]" ) {
238262 const Complex c{0.0 , 5.0 };
239263
240- require_approx_equal ( Complex ( 0.0 , -5.0 ), c. conj ( ));
264+ REQUIRE_THAT (c. conj (), ComplexWithinAbs (Complex{ 0.0 , -5.0 }, eps ));
241265}
242266
243267TEST_CASE (
244268 " Complex conjugate -> Conjugate a number with real and imaginary part" ,
245269 " [f7704498-d0be-4192-aaf5-a1f3a7f43e68]" ) {
246270 const Complex c{1.0 , 1.0 };
247271
248- require_approx_equal ( Complex ( 1.0 , -1.0 ), c. conj ( ));
272+ REQUIRE_THAT (c. conj (), ComplexWithinAbs (Complex{ 1.0 , -1.0 }, eps ));
249273}
250274
251275TEST_CASE (" Complex exponential function -> Euler's identity/formula" ,
252276 " [6d96d4c6-2edb-445b-94a2-7de6d4caaf60]" ) {
253277 const Complex c{0.0 , M_PI};
254278
255- require_approx_equal ( Complex ( -1.0 , 0.0 ), c. exp ( ));
279+ REQUIRE_THAT (c. exp (), ComplexWithinAbs (Complex{ -1.0 , 0.0 }, eps ));
256280}
257281
258282TEST_CASE (" Complex exponential function -> Exponential of 0" ,
259283 " [2d2c05a0-4038-4427-a24d-72f6624aa45f]" ) {
260284 const Complex c{0.0 , 0.0 };
261285
262- require_approx_equal ( Complex ( 1.0 , 0.0 ), c. exp ( ));
286+ REQUIRE_THAT (c. exp (), ComplexWithinAbs (Complex{ 1.0 , 0.0 }, eps ));
263287}
264288
265289TEST_CASE (" Complex exponential function -> Exponential of a purely real number" ,
266290 " [ed87f1bd-b187-45d6-8ece-7e331232c809]" ) {
267291 const Complex c{1.0 , 0.0 };
268292
269- require_approx_equal ( Complex (M_E, 0.0 ), c. exp ( ));
293+ REQUIRE_THAT (c. exp (), ComplexWithinAbs ( Complex (M_E, 0.0 ), eps ));
270294}
271295
272296// Extra Credit
@@ -277,7 +301,7 @@ TEST_CASE(
277301 " [08eedacc-5a95-44fc-8789-1547b27a8702]" ) {
278302 const Complex c{std::log (2.0 ), M_PI};
279303
280- require_approx_equal ( Complex ( -2.0 , 0.0 ), c. exp ( ));
304+ REQUIRE_THAT (c. exp (), ComplexWithinAbs (Complex{ -2.0 , 0.0 }, eps ));
281305}
282306
283307TEST_CASE (
@@ -287,7 +311,7 @@ TEST_CASE(
287311 " [d2de4375-7537-479a-aa0e-d474f4f09859]" ) {
288312 const Complex c{std::log (2.0 ) / 2.0 , M_PI / 4.0 };
289313
290- require_approx_equal ( Complex ( 1.0 , 1.0 ), c. exp ( ));
314+ REQUIRE_THAT (c. exp (), ComplexWithinAbs (Complex{ 1.0 , 1.0 }, eps ));
291315}
292316
293317TEST_CASE (
@@ -297,7 +321,7 @@ TEST_CASE(
297321 " [06d793bf-73bd-4b02-b015-3030b2c952ec]" ) {
298322 const Complex c{1.0 , 2.0 };
299323
300- require_approx_equal ( Complex ( 6.0 , 2.0 ), c + 5.0 );
324+ REQUIRE_THAT (c + 5.0 , ComplexWithinAbs (Complex{ 6.0 , 2.0 }, eps) );
301325}
302326
303327TEST_CASE (
@@ -307,7 +331,7 @@ TEST_CASE(
307331 " [d77dbbdf-b8df-43f6-a58d-3acb96765328]" ) {
308332 const Complex c{1.0 , 2.0 };
309333
310- require_approx_equal ( Complex ( 6.0 , 2.0 ), 5.0 + c );
334+ REQUIRE_THAT ( 5.0 + c, ComplexWithinAbs (Complex{ 6.0 , 2.0 }, eps) );
311335}
312336
313337TEST_CASE (
@@ -317,7 +341,7 @@ TEST_CASE(
317341 " [20432c8e-8960-4c40-ba83-c9d910ff0a0f]" ) {
318342 const Complex c{5.0 , 7.0 };
319343
320- require_approx_equal ( Complex ( 1.0 , 7.0 ), c - 4.0 );
344+ REQUIRE_THAT (c - 4.0 , ComplexWithinAbs (Complex{ 1.0 , 7.0 }, eps) );
321345}
322346
323347TEST_CASE (
@@ -327,7 +351,7 @@ TEST_CASE(
327351 " [b4b38c85-e1bf-437d-b04d-49bba6e55000]" ) {
328352 const Complex c{5.0 , 7.0 };
329353
330- require_approx_equal ( Complex ( -1.0 , -7.0 ), 4.0 - c );
354+ REQUIRE_THAT ( 4.0 - c, ComplexWithinAbs (Complex{ -1.0 , -7.0 }, eps) );
331355}
332356
333357TEST_CASE (
@@ -337,7 +361,7 @@ TEST_CASE(
337361 " [dabe1c8c-b8f4-44dd-879d-37d77c4d06bd]" ) {
338362 const Complex c{2.0 , 5.0 };
339363
340- require_approx_equal ( Complex ( 10.0 , 25.0 ), c * 5.0 );
364+ REQUIRE_THAT (c * 5.0 , ComplexWithinAbs (Complex{ 10.0 , 25.0 }, eps) );
341365}
342366
343367TEST_CASE (
@@ -347,7 +371,7 @@ TEST_CASE(
347371 " [6c81b8c8-9851-46f0-9de5-d96d314c3a28]" ) {
348372 const Complex c{2.0 , 5.0 };
349373
350- require_approx_equal ( Complex ( 10.0 , 25.0 ), 5.0 * c );
374+ REQUIRE_THAT ( 5.0 * c, ComplexWithinAbs (Complex{ 10.0 , 25.0 }, eps) );
351375}
352376
353377TEST_CASE (
@@ -357,7 +381,7 @@ TEST_CASE(
357381 " [8a400f75-710e-4d0c-bcb4-5e5a00c78aa0]" ) {
358382 const Complex c{10.0 , 100.0 };
359383
360- require_approx_equal ( Complex ( 1 .0 , 10.0 ), c / 10.0 );
384+ REQUIRE_THAT (c / 10 .0 , ComplexWithinAbs (Complex{ 1.0 , 10.0 }, eps) );
361385}
362386
363387TEST_CASE (
@@ -367,7 +391,7 @@ TEST_CASE(
367391 " [9a867d1b-d736-4c41-a41e-90bd148e9d5e]" ) {
368392 const Complex c{1.0 , 1.0 };
369393
370- require_approx_equal ( Complex ( 2.5 , -2.5 ), 5.0 / c );
394+ REQUIRE_THAT ( 5.0 / c, ComplexWithinAbs (Complex{ 2.5 , -2.5 }, eps) );
371395}
372396
373397#endif
0 commit comments