**Document:** WG14 N1431

**Submitter:** Fred J. Tydeman (USA)

**Submission Date:** 2009-12-01

**Related documents:** N818, SC22WG14.8195, N1399,
N1419

**Subject:** Creation of complex value

Problem: (x + y*I) will NOT do the right thing if "I" is complex and "y" is NaN or infinity. It does work fine if "I" is imaginary. Users and library implementors have noticed this deficiency in the standard and have been surprised that there is no easy to use portable way to create a complex number that can be used in both assignment and static initialization.

WG14 paper N818 presented more details on why the problem exists as well as many possible solutions. Paper N1419 added a couple more possible solutions.

Since those papers, another solution has been found that uses
existing C99 features. It uses a union, type punning
(footnote 87 in N1401 in **6.5.2.3 Structure and union
members**, paragraph 3), the required representation and
alignment of complex (as per **6.2.5 Types**, paragraph
13), and **6.5.2.5 Compound literals**. The downside of
this usage is a union must be visible where ever this idea is
used, and an unnamed object is created (so, cannot be used
for initialization of static objects), rather than just two
assignments being done.

**Proposal number one.**

Add the following example to **6.5.2.5 Compound literals**
or to **6.5.2.3 Structure and union members**

EXAMPLE nn: A non-static complex object may be initialized from two real values via type punning:

#include <math.h> union fc2 { /* 6.5.2.3, paragraph 3, type punning */ float f[2]; /* 6.2.5, paragraph 13, layout of complex */ float _Complex fc; }; float _Complex fc0 = (union fc2){INFINITY, NAN}.fc; float _Complex fc1 = (union fc2){.f[0]=-0.f, .f[1]=1.f}.fc;

defines and initializes fc0 with the value /math infinity
symbol/ + *i*NAN, fc1 with the value -0.f + *i*,
Note: This usage does not allow for static initialization.

**Proposal number two.**

Thanks to Steve Adamczyk of EDG for the initial wording and for assurance that there is no implementation difficulty with doing this.

Since the rules for **6.5.2.5 compound literals** are
defined in terms of the rules in **6.7.8 initialization**,
both uses would fall out.

After paragraph 11 of **6.7.8 Initialization**, add a new
paragraph:

If the initializer for an object of complex type is brace-enclosed, the initializer list shall contain either a single expression, in which case the initialization is as described above for scalar types, or two expressions [footnote], in which case the first expression (after conversion to real type) shall initialize the real part of the complex value, and the second expression (after conversion to real type) shall initialize the imaginary part of the complex value.

Footnote: The "ambiguous" case (double complex[2]){x,y} is treated as (double complex[2]){{x,0},{y,0}}, not (double complex[2]){{x,y},{0,0}}.

Add a new example to **6.7.8 Initialization**:

EXAMPLE nn: The declarations:

#include <complex.h> #include <math.h> double complex dc0 = { 3 + 4*I }; /* one complex scalar value */ double complex dc1 = { INFINITY, NAN }; /* pair of real values */ double complex dc2 = { 1+2*I, 3+4*I }; /* as if {1, 3} or 1+3*I */ double complex dc3[] = {1, 2*I, 3+4*I, {5}, {6*I}, {7+8*I}, {9,10}}; /* as if: { {1,0}, {0,2}, {3,4}, {5,0}, {0,6}, {7,8}, {9,10} } */

show the use of one expression versus two expressions inside braces to initialize complex objects.

**Proposal number three.**

This has been shipping for several years from HP.

Add 3 new function-like macros to <complex.h> in section 7.3.9 Manipulation functions:

**7.3.9.x The CMPLX macros**

**Synopsis**

#include <complex.h> double complex CMPLX( double x, double y ); float complex CMPLXF( float x, float y ); long double complex CMPLXL( long double x, long double y );

**Description**

The function-like macros **CMPLX(x,y)**,
**CMPLXF(x,y)**, and **CMPLXL(x,y)** each expands to an
expression of the specified complex type, with real part
having the value of **x** (converted) and imaginary part
having the value of **y** (converted). Each macro can be
used for static initialization if and only if both **x**
and **y** could be used as static initializers for the
corresponding real type.

The macros act as if an implementation supports imaginary and the macros were defined as:

#define CMPLX(x,y) ((double)(x)+_Imaginary_I*(double)(y)) #define CMPLXF(x,y) ((float)(x)+_Imaginary_I*(float)(y)) #define CMPLXL(x,y) ((long double)(x)+_Imaginary_I*(long double)(y))

**Returns**

The **CMPLX** macros return the complex value **x** +
*i****y** created from a pair of real values,
**x** and **y**.

Add to the rationale in the section on complex:

x + y**I** will not create the expected value x +
*i*y if **I** is complex and "y" is a NaN or an
infinity; however, the expected value will be created if
**I** is imaginary. Because of this, the notation {x,y}
and/or CMPLX(x,y) as an initializer of a complex object was
added to C1x to allow a way to create a complex number from a
pair of real values.