25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis/*
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * CDDL HEADER START
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis *
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * The contents of this file are subject to the terms of the
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * Common Development and Distribution License (the "License").
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * You may not use this file except in compliance with the License.
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis *
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * or http://www.opensolaris.org/os/licensing.
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * See the License for the specific language governing permissions
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * and limitations under the License.
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis *
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * When distributing Covered Code, include this CDDL HEADER in each
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * If applicable, add the following below this CDDL HEADER, with the
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * fields enclosed by brackets "[]" replaced with your own identifying
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * information: Portions Copyright [yyyy] [name of copyright owner]
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis *
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * CDDL HEADER END
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis */
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis/*
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis */
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis/*
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * Use is subject to license terms.
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis */
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis/*
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * atan2l(y,x)
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis *
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * Method :
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * 1. Reduce y to positive by atan2(y,x)=-atan2(-y,x).
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * 2. Reduce x to positive by (if x and y are unexceptional):
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * ARG (x+iy) = arctan(y/x) ... if x > 0,
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * ARG (x+iy) = pi - arctan[y/(-x)] ... if x < 0,
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis *
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * Special cases:
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis *
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * ATAN2((anything), NaN ) is NaN;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * ATAN2(NAN , (anything) ) is NaN;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * ATAN2(+-0, +(anything but NaN)) is +-0 ;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * ATAN2(+-0, -(anything but NaN)) is +-PI ;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * ATAN2(+-(anything but 0 and NaN), 0) is +-PI/2;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * ATAN2(+-(anything but INF and NaN), +INF) is +-0 ;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * ATAN2(+-(anything but INF and NaN), -INF) is +-PI;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * ATAN2(+-INF,+INF ) is +-PI/4 ;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * ATAN2(+-INF,-INF ) is +-3PI/4;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * ATAN2(+-INF, (anything but,0,NaN, and INF)) is +-PI/2;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis *
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * Constants:
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * The hexadecimal values are the intended ones for the following constants.
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * The decimal values may be used, provided that the compiler will convert
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * from decimal to binary accurately enough to produce the hexadecimal values
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis * shown.
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis */
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis
ddc0e0b53c661f6e439e3b7072b3ef353eadb4afRichard Lowe#pragma weak __atan2l = atan2l
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis#include "libm.h"
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis#include "longdouble.h"
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtisstatic const long double
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis zero = 0.0L,
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis tiny = 1.0e-40L,
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis one = 1.0L,
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis half = 0.5L,
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis PI3o4 = 2.356194490192344928846982537459627163148L,
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis PIo4 = 0.785398163397448309615660845819875721049L,
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis PIo2 = 1.570796326794896619231321691639751442099L,
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis PI = 3.141592653589793238462643383279502884197L,
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis PI_lo = 8.671810130123781024797044026043351968762e-35L;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtislong double
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtisatan2l(long double y, long double x) {
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis long double t, z;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis int k, m, signy, signx;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis if (x != x || y != y)
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis return (x + y); /* return NaN if x or y is NAN */
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis signy = signbitl(y);
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis signx = signbitl(x);
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis if (x == one)
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis return (atanl(y));
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis m = signy + signx + signx;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis /* when y = 0 */
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis if (y == zero)
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis switch (m) {
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis case 0:
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis return (y); /* atan(+0,+anything) */
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis case 1:
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis return (y); /* atan(-0,+anything) */
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis case 2:
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis return (PI + tiny); /* atan(+0,-anything) */
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis case 3:
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis return (-PI - tiny); /* atan(-0,-anything) */
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis }
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis /* when x = 0 */
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis if (x == zero)
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis return (signy == 1 ? -PIo2 - tiny : PIo2 + tiny);
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis /* when x is INF */
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis if (!finitel(x)) {
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis if (!finitel(y)) {
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis switch (m) {
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis case 0:
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis return (PIo4 + tiny); /* atan(+INF,+INF) */
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis case 1:
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis return (-PIo4 - tiny); /* atan(-INF,+INF) */
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis case 2:
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis return (PI3o4 + tiny); /* atan(+INF,-INF) */
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis case 3:
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis return (-PI3o4 - tiny); /* atan(-INF,-INF) */
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis }
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis } else {
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis switch (m) {
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis case 0:
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis return (zero); /* atan(+...,+INF) */
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis case 1:
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis return (-zero); /* atan(-...,+INF) */
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis case 2:
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis return (PI + tiny); /* atan(+...,-INF) */
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis case 3:
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis return (-PI - tiny); /* atan(-...,-INF) */
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis }
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis }
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis }
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis /* when y is INF */
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis if (!finitel(y))
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis return (signy == 1 ? -PIo2 - tiny : PIo2 + tiny);
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis /* compute y/x */
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis x = fabsl(x);
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis y = fabsl(y);
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis t = PI_lo;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis k = (ilogbl(y) - ilogbl(x));
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis if (k > 120)
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis z = PIo2 + half * t;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis else if (m > 1 && k < -120)
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis z = zero;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis else
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis z = atanl(y / x);
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis switch (m) {
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis case 0:
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis return (z); /* atan(+,+) */
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis case 1:
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis return (-z); /* atan(-,+) */
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis case 2:
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis return (PI - (z - t)); /* atan(+,-) */
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis case 3:
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis return ((z - t) - PI); /* atan(-,-) */
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis }
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis /* NOTREACHED */
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis return 0.0L;
25c28e83beb90e7c80452a7c818c5e6f73a07dc8Piotr Jasiukajtis}