URL
https://opencores.org/ocsvn/forwardcom/forwardcom/trunk
Subversion Repositories forwardcom
[/] [forwardcom/] [libraries/] [sincosf.as] - Rev 117
Go to most recent revision | Compare with Previous | Blame | View Log
/********************************* sincosf.as ******************************** Author: Agner Fog* date created: 2020-04-29* Last modified: 2021-04-25* Version: 1.11* Project: ForwardCom library math.li* Description: sin, cos, and tan functions. Calculate in radians, single precision* The argument x can be a scalar or a vector* The return value will be a vector with the same length* C declaration: float sin(float x);* C declaration: float cos(float x);* C declaration: float tan(float x);* C declaration: struct {float s; float c;} sincos(float x);** This code is adapted from C++ vector class library www.github.com/vectorclass* Copyright 2020-2021 GNU General Public License http://www.gnu.org/licenses*****************************************************************************/// define constants% M_2_PI = 0.636619772367581343076 // 2./pi% P0sinf = -1.6666654611E-1% P1sinf = 8.3321608736E-3% P2sinf = -1.9515295891E-4% P0cosf = 4.166664568298827E-2% P1cosf = -1.388731625493765E-3% P2cosf = 2.443315711809948E-5% DP1F = 0.78515625 * 2.% DP2F = 2.4187564849853515625E-4 * 2.% DP3F = 3.77489497744594108E-8 * 2.code section execute align = 4public _sinf: function, reguse = 0, 0x1BFpublic _cosf: function, reguse = 0, 0x1BFpublic _sincosf: function, reguse = 0, 0x1BFpublic _tanf: function, reguse = 0, 0x1BF// common entry for sin and sincos functions_sinf function_sincosf:/* registers:v0 = xv1 = abs(x)v1 = quadrantv2 = x^2v3 = x^3v4 = x^4v5 = tempv5 = sinv6 = unused (vacant flag for calling function)v7 = cosv8 = abs(x) reduced modulo pi/2*/// Find quadrant:// 0 - pi/4 => 0// pi/4 - 3*pi/4 => 1// 3*pi/4 - 5*pi/4 => 2// 5*pi/4 - 7*pi/4 => 3// 7*pi/4 - 8*pi/4 => 4// reduce modulo pi/2, with extended precision//nopfloat v1 = clear_bit(v0, 31) // abs(x)float v5 = v1 * M_2_PIfloat v5 = round(v5, 0) // round to integer// x = ((xa - y * DP1) - y * DP2) - y * DP3;float v8 = v5 * (-DP1F) + v1float v8 = v5 * (-DP2F) + v8float v8 = v5 * (-DP3F) + v8float v3 = !(v5 > ((1 << 22) + 0.0)) // check for loss of precision and overflow, but not NANfloat v1 = v5 + ((1 << 23) + 0.0) // add magic number 2^23 to get integer into lowest bitfloat v8 = v3 ? v8 : 0 // zero if out of range. result will be -1, 0, or 1// Taylor expansion of sin and cos, valid for -pi/4 <= x <= pi/4// s = polynomial_2(x^2, P0sinf, P1sinf, P2sinf) * (x*x^2) + x;float v2 = v8 * v8 // x^2float v3 = v8 * v2 // x^3float v4 = v2 * v2 // x^4float v5 = replace(v8, P0sinf) // broadcast to same length as xfloat v5 = v2 * P1sinf + v5float v5 = v4 * P2sinf + v5float v5 = v5 * v3 + v8 // sin// c = polynomial_2(x2, P0cosf, P1cosf, P2cosf) * (x2*x2) + nmul_add(0.5f, x2, 1.0f);float v7 = replace(v8, P0cosf) // broadcast to same length as xfloat v7 = v2 * P1cosf + v7float v7 = v4 * P2cosf + v7float v3 = replace(v8, 1.0)float v3 = v2 * (-0.5) + v3 // 1 - 0.5*x^2float v7 = v7 * v4 + v3 // cos// swap sin and cos if odd quadrantfloat v3 = v1 ? v7 : v5 // sinfloat v4 = v1 ? v5 : v7 // cos// get sign of sinint32 v5 = v1 << 30 // get bit 1 into sign bit, x modulo pi/2 = 2 or 3int32 v5 ^= v0 // toggle with sign of original xint32 v5 = and(v5, 1 << 31) // isolate sign bitfloat v0 = v3 ^ v5 // apply sign bit to sin// get sign of cosint32 v1 = v1 + 1 // change sign when x modulo pi/2 = 1 or 2int32 v1 = v1 << 30 // get bit 1 into sign bitint32 v1 = and(v1, 1 << 31) // isolate sign bitfloat v1 = v4 ^ v1 // apply sign bit to cos// return sin in v0, cos in v1return_sinf end// cosine function_cosf functioncall _sincosffloat v0 = v1 // cos is in v1return_cosf end// tangent function_tanf functioncall _sincosffloat v0 = v0 / v1 // tan(x) = sin(x)/cos(x)return_tanf endcode end
Go to most recent revision | Compare with Previous | Blame | View Log
