/* Copyright 2005 Castle Technology Ltd
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#pragma force_top_level
#pragma include_only_once

/* complex.h: ISO 'C' (9899:2018) library header, sections 7.3 and G.6 */
/* Copyright (C) Acorn Computers Ltd. 2005 */
/* version 1.01 */

/*
 * The header <complex.h> defines macros and declares functions that support
 * complex arithmetic. Each synopsis specifies a family of functions
 * consistinc of a principal function with one or more double complex
 * parameters and a double complex or double return value; and other
 * functions with the same name but with f and l suffixes which are
 * corresponding functions with float and long double parameters and return
 * value.
 *
 * This implementation supports Annex G of ISO/IEC 9899:1999, which adds
 * imaginary types, and defines "I" to be _Imaginary_I rather than
 * _Complex_I.
 */

#ifndef __complex_h
#define __complex_h

#ifdef __cplusplus
#  include <complex++.h>
#else

#undef imaginary
#undef complex
#undef I
#define imaginary    _Imaginary
#define complex      _Complex
   /* a program may undefine and perhaps then redefine the macros complex, */
   /* imaginary, and I. */

#define _Imaginary_I ___i
   /* a constant expression of type const float _Imaginary, with the value */
   /* of the imaginary unit. */
#define _Complex_I   (0.0F+___i)
   /* a constant expression of type const float _Complex, with the value */
   /* of the imaginary unit. */

#define I            _Imaginary_I
   /* I is imaginary. On an implementation without imaginary types, I */
   /* would expand to _Complex_I. */

/* #pragma STDC CX_LIMITED_RANGE ON|OFF|DEFAULT */
   /* The usual mathmatical formulas for complex multiply, divide and */
   /* absolute value are problematic because of their treatment of */
   /* infinities and because of undue overflow and underflow. The */
   /* CX_LIMITED_RANGE pragma can be used to inform the implementation */
   /* that (where the state is "on") the usual mathmatical formulas are */
   /* acceptable. The pragma can occur either outside external */
   /* declarations or preceding all explicit declarations and statements */
   /* inside a compound statement. When outside external declarations, the */
   /* pragma takes effect from its occurrence until another */
   /* CX_LIMITED_RANGE pragma is encountered, or until the end of the */
   /* translation unit. When inside a compound statement, the pragma takes */
   /* effect from its occurrence until another CX_LIMITED_RANGE pragma is */
   /* encountered (including within a nested compound statement), or until */
   /* the end of the compound statement; at the end of a compound */
   /*  statement the state for the pragma is restored to its condition */
   /* just before the compound statement. If this pragma is used in any */
   /* other context, the behaviour is undefined. The default state for */
   /* this pragma is "off". */

double complex cacos(double complex /*z*/);
float complex cacosf(float complex /*z*/);
long double complex cacosl(long double complex /*z*/);
   /* computes the complex arc cosine of z, with branch cuts outside the */
   /* interval [-1,+1] along the real axis. */
   /* Returns: the complex arc cosine value, in the range of a strip */
   /*          mathematically unbounded along the imaginary axis and in */
   /*          the interval [0,Pi] along the real axis. */
double complex casin(double complex /*z*/);
float complex casinf(float complex /*z*/);
long double complex casinl(long double complex /*z*/);
   /* computes the complex arc sine of z, with branch cuts outside the */
   /* interval [-1,+1] along the real axis. */
   /* Returns: the complex arc sine value, in the range of a strip */
   /*          mathematically unbounded along the imaginary axis and in */
   /*          the interval [-Pi/2,+Pi/2] along the real axis. */
double complex catan(double complex /*z*/);
float complex catanf(float complex /*z*/);
long double complex catanl(long double complex /*z*/);
   /* computes the complex arc tangent of z, with branch cuts outside the */
   /* interval [-i,+i] along the imaginary axis. */
   /* Returns: the complex arc tangent value, in the range of a strip */
   /*          mathematically unbounded along the imaginary axis and in */
   /*          the interval [-Pi/2,+Pi/2] along the real axis. */
double complex ccos(double complex /*z*/);
float complex ccosf(float complex /*z*/);
long double complex ccosl(long double complex /*z*/);
   /* computes the complex cosine of z. */
   /* Returns: the complex cosine value. */
double complex csin(double complex /*z*/);
float complex csinf(float complex /*z*/);
long double complex csinl(long double complex /*z*/);
   /* computes the complex sine of z. */
   /* Returns: the complex sine value. */
double complex ctan(double complex /*z*/);
float complex ctanf(float complex /*z*/);
long double complex ctanl(long double complex /*z*/);
   /* computes the complex tangent of z. */
   /* Returns: the complex tangent value. */

double complex cacosh(double complex /*z*/);
float complex cacoshf(float complex /*z*/);
long double complex cacoshl(long double complex /*z*/);
   /* computes the complex arc hyperbolic cosine of z, with a branch cut */
   /* at values less than 1 along the real axis. */
   /* Returns: the complex arc hyperbolic cosine value, in the range of a */
   /*          half-strip of non-negative values along the real axis and */
   /*          in the interval [-i*Pi,+i*Pi] along the imaginary axis. */
double complex casinh(double complex /*z*/);
float complex casinhf(float complex /*z*/);
long double complex casinhl(long double complex /*z*/);
   /* computes the complex arc hyperbolic sine of z, with branch cuts */
   /* outside the interval [-i,+i] along the imaginary axis. */
   /* Returns: the complex arc hyperbolic sine value, in the range of a */
   /*          strip mathematically unbounded along the real axis and in */
   /*          the interval [-i*Pi/2,+i*Pi/2] along the imaginary axis. */
double complex catanh(double complex /*z*/);
float complex catanhf(float complex /*z*/);
long double complex catanhl(long double complex /*z*/);
   /* computes the complex arc hyperbolic tangent of z, with branch cuts */
   /* outside the interval [-1,+1] along the real axis. */
   /* Returns: the complex arc hyperbolic tangent value, in the range of a */
   /*          strip mathematically unbounded along the real axis and in */
   /*          the interval [-i*Pi/2,+i*Pi/2] along the imaginary axis. */
double complex ccosh(double complex /*z*/);
float complex ccoshf(float complex /*z*/);
long double complex ccoshl(long double complex /*z*/);
   /* computes the complex hyperbolic cosine of z. */
   /* Returns: the complex hyperbolic cosine value. */
double complex csinh(double complex /*z*/);
float complex csinhf(float complex /*z*/);
long double complex csinhl(long double complex /*z*/);
   /* computes the complex hyperbolic sine of z. */
   /* Returns: the complex hyperbolic sine value. */
double complex ctanh(double complex /*z*/);
float complex ctanhf(float complex /*z*/);
long double complex ctanhl(long double complex /*z*/);
   /* computes the complex hyperbolic tangent of z. */
   /* Returns: the complex hyperbolic tangent value. */

double complex cexp(double complex /*z*/);
float complex cexpf(float complex /*z*/);
long double complex cexpl(long double complex /*z*/);
   /* computes the complex base-e exponential of z. */
   /* Returns: the complex base-e exponential value */
double complex clog(double complex /*z*/);
float complex clogf(float complex /*z*/);
long double complex clogl(long double complex /*z*/);
   /* computes the complex natural (base-e) logarithm of z, with a branch */
   /* cut along the negative real axis. */
   /* Returns: the complex natural logarithm value, in the range of a */
   /*          strip mathematically unbounded along the real axis and in */
   /*          the interval [-i*Pi,+i*Pi] along the imaginary axis. */

double cabs(double complex /*z*/);
float cabsf(float complex /*z*/);
long double cabsl(long double complex /*z*/);
   /* computes the complex absolute value (also called norm, modulus, or */
   /* magnitude) of z. */
   /* Returns: the complex absolute value */
double complex cpow(double complex /*x*/, double complex /*y*/);
float complex cpowf(float complex /*x*/, float complex /*y*/);
long double complex cpowl(long double complex /*x*/, long double complex /*y*/);
   /* computes the complex power function x^y, with a branch cut for the */
   /* first parameter along the negative real axis. */
   /* Returns: the complex power function value */
double complex csqrt(double complex /*z*/);
float complex csqrtf(float complex /*z*/);
long double complex csqrtl(long double complex /*z*/);
   /* computes the complex square root of z, with a branch cut along the */
   /* negative real axis. */
   /* Returns: the complex square root value, in the range of the right */
   /*          half-plane (including the imaginary axis). */

double carg(double complex /*z*/);
float cargf(float complex /*z*/);
long double cargl(long double complex /*z*/);
   /* computes the argument (also called phase angle) of z, with a branch */
   /* cut along the negative real axis. */
   /* Returns: the value of the argument in the interval [-Pi,+Pi] */
double cimag(double complex /*z*/);
float cimagf(float complex /*z*/);
long double cimagl(long double complex /*z*/);
#define cimag(z) ((void) sizeof cimag(z), (double _Imaginary)(z)/_Imaginary_I)
#define cimagf(z) ((void) sizeof cimagf(z), (float _Imaginary)(z)/_Imaginary_I)
#define cimagl(z) ((void) sizeof cimagl(z), (long double _Imaginary)(z)/_Imaginary_I)
   /* computes the imaginary part of z. */
   /* Returns: the imaginary part value (as a real) */
#define CMPLX(x,y)  (double _Complex)((double)(x) + ___i * (double)(y))
#define CMPLXF(x,y) (float _Complex)((float)(x) + ___i * (float)(y))
#define CMPLXL(x,y) (long double _Complex)((long double)(x) + ___i * (long double)(y))
   /* an expression suitable for use as an initialiser for an object with */
   /* static or thread storage duration, with the complex value x + iy */
double complex conj(double complex /*z*/);
float complex conjf(float complex /*z*/);
long double complex conjl(long double complex /*z*/);
#define conj(z) ((void) sizeof conj(z), __conj (double _Complex)(z))
#define conjf(z) ((void) sizeof conjf(z), __conj (float _Complex)(z))
#define conjl(z) ((void) sizeof conjl(z), __conj (long double _Complex)(z))
   /* computes the complex conjugate of z, by reversing the sign of its */
   /* imaginary part. */
   /* Returns: the complex conjugate value */
double complex cproj(double complex /*z*/);
float complex cprojf(float complex /*z*/);
long double complex cprojl(long double complex /*z*/);
   /* computes a projection of z onto the Riemann sphere: z projects to z */
   /* except that all complex infinities (even those with one infinite */
   /* part and one NaN part) project to positive infinity on the real */
   /* axis. If z has an infinite part, then cproj(z) is equivalent to */
   /*          INFINITY + I * copysign(0.0, cimag(z))           */
   /* Returns: the value of the projection onto the Riemann sphere */
double creal(double complex /*z*/);
float crealf(float complex /*z*/);
long double creall(long double complex /*z*/);
#define creal(z) ((void) sizeof creal(z), (double)(z))
#define crealf(z) ((void) sizeof crealf(z), (float)(z))
#define creall(z) ((void) sizeof creall(z), (long double)(z))
   /* computes the real part of z. */
   /* Returns: the real part value */

#endif /* __cplusplus */

#endif

/* end of complex.h */
