Path: csiph.com!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail From: Tim Rentsch Newsgroups: comp.lang.c Subject: Re: CMPLX vs a+bi values Date: Wed, 27 Jan 2021 07:30:04 -0800 Organization: A noiseless patient Spider Lines: 73 Message-ID: <86o8hal7nn.fsf@linuxsc.com> References: Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Injection-Info: reader02.eternal-september.org; posting-host="a3a7a3546220eb2a4a7cfe4d4683198c"; logging-data="13758"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX198Tm5lkYT1n5YYvyTET/xDaoVXJ/tHuM4=" User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.4 (gnu/linux) Cancel-Lock: sha1:BwtgRUAtjOrb7r1sowJwdLZEpuk= sha1:Yinr0dJQno7BmEHvPncnFG26kbI= Xref: csiph.com comp.lang.c:158648 beej@beej.us (Beej) writes: > Time for another esoteric question! > > ---------- > > #include > > double complex a = CMPLX(1, 2); > double complex b = 1 + 2*I; > > ---------- > > They compare equal, of course. [..discussion of possible > differences..] Normally I would prefer to avoid either form. If what you care about is complex values in ordinary code (ie, in statements or initializers for non-static locals), you can use something like this: typedef double _Complex Z; typedef union { double xy[2]; Z z; } Union_xy_Z; #define COMPLEX(x,y) ( (Union_xy_Z){ .xy[0]=(x), .xy[1]=(y) }.z ) Z minus_one_example_a(){ Z i = COMPLEX( 0, 1 ); return i*i; } This COMPLEX macro does not need any header, and works in both C99 and C11 (provided of course _Complex is supported). It does have a drawback, in that it cannot be used in initializers at the top level (what the C standard calls "external definitions"). However, we can define a macro that gives a value of a pointer to a complex: #define A_COMPLEX(x,y) ( (Z*) &COMPLEX( x, y ) ) static const Z *const pI = A_COMPLEX( 0, 1 ); Z minus_one_example_b(){ return *pI * *pI; } Note that the variable 'pI' need not be declared 'const' (for either or both of the two 'const' modifiers in the declaration). The A_COMPLEX macro works for external definitions, but because of how compound literals are defined A_COMPLEX does not work for 'static' declarations inside a function. So if we really need a function-local static, an explicit intermediate object can be used to do that: Z minus_one_example_c(){ static Union_xy_Z xy_I = {{ 0, 1 }}; Z *const pI = & xy_I.z; return *pI * *pI; } The expression '*pI' can be used to update as well as read the function-local static object xy_I.z. All the above is required by the C standard to work in C. Furthermore, because the two components of a complex are stored directly, rather than being combined using multiplication or addition, losing the sign of a (floating) negative zero shouldn't ever happen.