00001 /* 00002 * SpanDSP - a series of DSP components for telephony 00003 * 00004 * arctan2.h - A quick rough approximate arc tan 00005 * 00006 * Written by Steve Underwood <steveu@coppice.org> 00007 * 00008 * Copyright (C) 2003 Steve Underwood 00009 * 00010 * All rights reserved. 00011 * 00012 * This program is free software; you can redistribute it and/or modify 00013 * it under the terms of the GNU Lesser General Public License version 2.1, 00014 * as published by the Free Software Foundation. 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU Lesser General Public License for more details. 00020 * 00021 * You should have received a copy of the GNU Lesser General Public 00022 * License along with this program; if not, write to the Free Software 00023 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00024 * 00025 * $Id: arctan2.h,v 1.13 2008/05/29 13:04:19 steveu Exp $ 00026 */ 00027 00028 /*! \file */ 00029 00030 #if !defined(_SPANDSP_ARCTAN2_H_) 00031 #define _SPANDSP_ARCTAN2_H_ 00032 00033 /*! \page arctan2_page Fast approximate four quadrant arc-tangent 00034 \section arctan2_page_sec_1 What does it do? 00035 This module provides a fast approximate 4-quadrant arc tangent function, 00036 based on something at dspguru.com. The worst case error is about 4.07 degrees. 00037 This is fine for many "where am I" type evaluations in comms. work. 00038 00039 \section arctan2_page_sec_2 How does it work? 00040 ???. 00041 */ 00042 00043 #if defined(__cplusplus) 00044 extern "C" 00045 { 00046 #endif 00047 00048 /* This returns its answer as a signed 32 bit integer phase value. */ 00049 static __inline__ int32_t arctan2(float y, float x) 00050 { 00051 float abs_y; 00052 float angle; 00053 00054 if (x == 0.0f || y == 0.0f) 00055 return 0; 00056 00057 abs_y = fabsf(y); 00058 00059 /* If we are in quadrant II or III, flip things around */ 00060 if (x < 0.0f) 00061 angle = 3.0f - (x + abs_y)/(abs_y - x); 00062 else 00063 angle = 1.0f - (x - abs_y)/(abs_y + x); 00064 angle *= 536870912.0f; 00065 00066 /* If we are in quadrant III or IV, negate to return an 00067 answer in the range +-pi */ 00068 if (y < 0.0f) 00069 angle = -angle; 00070 return (int32_t) angle; 00071 } 00072 /*- End of function --------------------------------------------------------*/ 00073 00074 #if 0 00075 /* This returns its answer in radians, in the range +-pi. */ 00076 static __inline__ float arctan2f(float y, float x) 00077 { 00078 float angle; 00079 float fx; 00080 float fy; 00081 00082 if (x == 0.0f || y == 0.0f) 00083 return 0; 00084 fx = fabsf(x); 00085 fy = fabsf(y); 00086 /* Deal with the octants */ 00087 /* N.B. 0.28125 == (1/4 + 1/32) */ 00088 if (fy > fx) 00089 angle = 3.1415926f/2.0f - fx*fy/(y*y + 0.28125f*x*x); 00090 else 00091 angle = fy*fx/(x*x + 0.28125f*y*y); 00092 00093 /* Deal with the quadrants, to bring the final answer to the range +-pi */ 00094 if (x < 0.0f) 00095 angle = 3.1415926f - angle; 00096 if (y < 0.0f) 00097 angle = -angle; 00098 return angle; 00099 } 00100 /*- End of function --------------------------------------------------------*/ 00101 #endif 00102 00103 #if defined(__cplusplus) 00104 } 00105 #endif 00106 00107 #endif 00108 /*- End of file ------------------------------------------------------------*/