C/carg
< C
Funkcja wykorzystuje atan2
Kod źródłowy
edytujglibc
edytujW bibliotece glibc (GNU C Library)[1] jest zdefiniowana w pliku carg.c[2]:
// glibc/math/carg.c
/* Compute argument of complex double value.
Copyright (C) 1997-2015 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <complex.h>
#include <math.h>
double
__carg (__complex__ double x)
{
return __atan2 (__imag__ x, __real__ x);
}
weak_alias (__carg, carg)
#ifdef NO_LONG_DOUBLE
strong_alias (__carg, __cargl)
weak_alias (__carg, cargl)
#endif
libm
edytuj// http://www.opensource.apple.com/source/Libm/Libm-92/complex.c
/*
* Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* The contents of this file constitute Original Code as defined in and
* are subject to the Apple Public Source License Version 1.1 (the
* "License"). You may not use this file except in compliance with the
* License. Please obtain a copy of the License at
* http://www.apple.com/publicsource and read it before using this file.
*
* This Original Code and all software distributed under the License are
* distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
* License for the specific language governing rights and limitations
* under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
/****************************************************************************
** File: complex.c
**
** Contains: C source code for implementations of floating-point
** (double) complex functions defined in header file
** "complex.h" for PowerPC Macintoshes in native mode.
** Transcendental function algorithms are based on the
** paper "Branch Cuts for Complex Elementary Functions"
** by W. Kahan, May 17, 1987, and on Pascal and C source
** code for the SANE 80-/96-bit extended type by Kenton
** Hanson and Paul Finlayson, respectively.
**
**
** Written by: Jon Okada, SANEitation Engineer, ext. 4-4838
**
** Copyright: c 1987-1993 by Apple Computer, Inc., all rights reserved.
**
** Change History (most recent first):
****************************************************************************/
/****************************************************************************
double carg(double complex z) returns the argument (in radians) of its
complex argument z. The algorithm is from Kahan's paper.
The argument of a complex number z = x + i*y is defined as atan2(y,x)
for finite x and y.
CONSTANTS: FPKPI2 = pi/2.0 to double precision
FPKPI = pi to double precision
Calls: fpclassify, copysign, fabs, atan
****************************************************************************/
double carg ( double complex z )
{
double a,b,argr;
int clre,clim;
a = Real(z);
b = Imag(z);
clre = fpclassify(a);
clim = fpclassify(b);
if ((clre == FP_ZERO) && (clim == FP_ZERO)) { /* zero real and imag parts */
a = copysign(1.0, a);
}
if ((clre == FP_INFINITE) && (clim == FP_INFINITE)) { /* both parts INF */
a = copysign(1.0, a);
b = copysign(1.0, b);
}
if (fabs(b) > fabs(a)) /* |imag| > |real| */
argr = copysign(M_PI_2, b) - atan(a/b);
else {
if (a < 0.0) /* |real| >= |imag| */
argr = copysign(M_PI, b) + atan(b/a);
else
argr = atan(b/a);
}
return argr;
}
Przykład
edytuj// gcc c.c -lm -Wall
// a.out
// the return value is the range of [-pi, pi].
// from http://en.cppreference.com/w/c/numeric/complex/carg
#include <stdio.h>
#include <math.h> // M_PI; needs -lm also
#include <complex.h>
static double TwoPi=2.0*M_PI;
double c_arg(complex double z)
{
double arg;
arg = carg(z);
if (arg<0.0) arg+= TwoPi ;
return arg;
}
double c_turn(complex double z)
{
double arg;
arg = c_arg(z);
return arg/TwoPi;
}
int info(double complex z)
{
printf("phase angle of %.1f%+.4fi is %.16f radians = %0.16f turns\n", creal(z), cimag(z), c_arg(z), c_turn(z));
return 0;
}
int main(void)
{
info( 1.0+0.0*I);
//
info( 1.0+1.0*I);
//
info( 0.0+1.0*I);
//
info(-1.0+1.0*I);
//
info(-1.0+0.0*I);
info(-1.0-0.0*I);// or CMPLX(-1, -0.0) (the other side of the cut)
//
info( 0.0-1.0*I);
info( 1.0-1.0*I);
//
info( 1.0-0.0001*I);
info( 1.0-0.0*I);
//
info( 0.0+0.0*I);
return 0;
}
Wynik :
phase angle of 1.0+0.0000i is 0.0000000000000000 radians = 0.0000000000000000 turns phase angle of 1.0+1.0000i is 0.7853981633974483 radians = 0.1250000000000000 turns phase angle of 0.0+1.0000i is 1.5707963267948966 radians = 0.2500000000000000 turns phase angle of -1.0+1.0000i is 2.3561944901923448 radians = 0.3750000000000000 turns phase angle of -1.0+0.0000i is 3.1415926535897931 radians = 0.5000000000000000 turns phase angle of -1.0-0.0000i is 3.1415926535897931 radians = 0.5000000000000000 turns phase angle of 0.0-1.0000i is 4.7123889803846897 radians = 0.7500000000000000 turns phase angle of 1.0-1.0000i is 5.4977871437821380 radians = 0.8750000000000000 turns phase angle of 1.0-0.0001i is 6.2830853071799195 radians = 0.9999840845057438 turns phase angle of 1.0-0.0000i is -0.0000000000000000 radians = -0.0000000000000000 turns phase angle of 0.0+0.0000i is 0.0000000000000000 radians = 0.0000000000000000 turns
Drugi przykład : obliczamy iMax punktów zespolonych położonych na kole o promieniu r. Nastęþnie sprawdzamy carg
/*
gcc c.c -Wall
./a.out
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <complex.h>// floor
double TwoPi=2.0*M_PI;
double GiveTurn(double complex z)
{
double argument;
argument = carg(z); // argument in radians from -pi to pi
if ( argument < -M_PI) printf("for z = %f; %f carg argument underflow = %f \n", creal(z), cimag(z), argument);
if ( argument > M_PI) printf("for z = %f; %f carg argument overflow = %f \n", creal(z), cimag(z), argument);
while (argument<0.0)
argument = TwoPi + argument ; // argument in radians from 0 to 2*pi
return (argument/TwoPi) ; // argument in turns from 0.0 to 1.0
}
int main(){
int iMax = 30;
int i;
double dt = 1.0/iMax;
double t; // angle in turns
double a; // angle in radians
double tt ; // angle in turns
double r = 18.0;
double x;
double y;
double arg;
for (i=0; i<=iMax; i++){
t = i*dt;
a = 2.0*t*M_PI; // angle in turns from 0 to 1.0
// from polar to Rectangular form of complex number z = x+y*I
x = r* cos(a);
y = r * sin(a);
//
arg = carg(x+y*I);
tt = GiveTurn(x+y*I);
printf ("i = %d t = %f tt = %f a = %f carg = %f z = %f ; %f\n", i, t, tt, a, arg, x,y );
}
return 0;
}
Wynik:
./a.out i = 0 t = 0.000000 tt = 0.000000 a = 0.000000 carg = 0.000000 z = 18.000000 ; 0.000000 i = 1 t = 0.033333 tt = 0.033333 a = 0.209440 carg = 0.209440 z = 17.606657 ; 3.742410 i = 2 t = 0.066667 tt = 0.066667 a = 0.418879 carg = 0.418879 z = 16.443818 ; 7.321260 i = 3 t = 0.100000 tt = 0.100000 a = 0.628319 carg = 0.628319 z = 14.562306 ; 10.580135 i = 4 t = 0.133333 tt = 0.133333 a = 0.837758 carg = 0.837758 z = 12.044351 ; 13.376607 i = 5 t = 0.166667 tt = 0.166667 a = 1.047198 carg = 1.047198 z = 9.000000 ; 15.588457 i = 6 t = 0.200000 tt = 0.200000 a = 1.256637 carg = 1.256637 z = 5.562306 ; 17.119017 i = 7 t = 0.233333 tt = 0.233333 a = 1.466077 carg = 1.466077 z = 1.881512 ; 17.901394 i = 8 t = 0.266667 tt = 0.266667 a = 1.675516 carg = 1.675516 z = -1.881512 ; 17.901394 i = 9 t = 0.300000 tt = 0.300000 a = 1.884956 carg = 1.884956 z = -5.562306 ; 17.119017 i = 10 t = 0.333333 tt = 0.333333 a = 2.094395 carg = 2.094395 z = -9.000000 ; 15.588457 i = 11 t = 0.366667 tt = 0.366667 a = 2.303835 carg = 2.303835 z = -12.044351 ; 13.376607 i = 12 t = 0.400000 tt = 0.400000 a = 2.513274 carg = 2.513274 z = -14.562306 ; 10.580135 i = 13 t = 0.433333 tt = 0.433333 a = 2.722714 carg = 2.722714 z = -16.443818 ; 7.321260 i = 14 t = 0.466667 tt = 0.466667 a = 2.932153 carg = 2.932153 z = -17.606657 ; 3.742410 i = 15 t = 0.500000 tt = 0.500000 a = 3.141593 carg = 3.141593 z = -18.000000 ; 0.000000 i = 16 t = 0.533333 tt = 0.533333 a = 3.351032 carg = -2.932153 z = -17.606657 ; -3.742410 i = 17 t = 0.566667 tt = 0.566667 a = 3.560472 carg = -2.722714 z = -16.443818 ; -7.321260 i = 18 t = 0.600000 tt = 0.600000 a = 3.769911 carg = -2.513274 z = -14.562306 ; -10.580135 i = 19 t = 0.633333 tt = 0.633333 a = 3.979351 carg = -2.303835 z = -12.044351 ; -13.376607 i = 20 t = 0.666667 tt = 0.666667 a = 4.188790 carg = -2.094395 z = -9.000000 ; -15.588457 i = 21 t = 0.700000 tt = 0.700000 a = 4.398230 carg = -1.884956 z = -5.562306 ; -17.119017 i = 22 t = 0.733333 tt = 0.733333 a = 4.607669 carg = -1.675516 z = -1.881512 ; -17.901394 i = 23 t = 0.766667 tt = 0.766667 a = 4.817109 carg = -1.466077 z = 1.881512 ; -17.901394 i = 24 t = 0.800000 tt = 0.800000 a = 5.026548 carg = -1.256637 z = 5.562306 ; -17.119017 i = 25 t = 0.833333 tt = 0.833333 a = 5.235988 carg = -1.047198 z = 9.000000 ; -15.588457 i = 26 t = 0.866667 tt = 0.866667 a = 5.445427 carg = -0.837758 z = 12.044351 ; -13.376607 i = 27 t = 0.900000 tt = 0.900000 a = 5.654867 carg = -0.628319 z = 14.562306 ; -10.580135 i = 28 t = 0.933333 tt = 0.933333 a = 5.864306 carg = -0.418879 z = 16.443818 ; -7.321260 i = 29 t = 0.966667 tt = 0.966667 a = 6.073746 carg = -0.209440 z = 17.606657 ; -3.742410 i = 30 t = 1.000000 tt = 1.000000 a = 6.283185 carg = -0.000000 z = 18.000000 ; -0.000000