sincos.c raw

   1  /* origin: FreeBSD /usr/src/lib/msun/src/s_sin.c */
   2  /*
   3   * ====================================================
   4   * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
   5   *
   6   * Developed at SunPro, a Sun Microsystems, Inc. business.
   7   * Permission to use, copy, modify, and distribute this
   8   * software is freely granted, provided that this notice
   9   * is preserved.
  10   * ====================================================
  11   */
  12  
  13  #define _GNU_SOURCE
  14  #include "libm.h"
  15  
  16  void sincos(double x, double *sin, double *cos)
  17  {
  18  	double y[2], s, c;
  19  	uint32_t ix;
  20  	unsigned n;
  21  
  22  	GET_HIGH_WORD(ix, x);
  23  	ix &= 0x7fffffff;
  24  
  25  	/* |x| ~< pi/4 */
  26  	if (ix <= 0x3fe921fb) {
  27  		/* if |x| < 2**-27 * sqrt(2) */
  28  		if (ix < 0x3e46a09e) {
  29  			/* raise inexact if x!=0 and underflow if subnormal */
  30  			FORCE_EVAL(ix < 0x00100000 ? x/0x1p120f : x+0x1p120f);
  31  			*sin = x;
  32  			*cos = 1.0;
  33  			return;
  34  		}
  35  		*sin = __sin(x, 0.0, 0);
  36  		*cos = __cos(x, 0.0);
  37  		return;
  38  	}
  39  
  40  	/* sincos(Inf or NaN) is NaN */
  41  	if (ix >= 0x7ff00000) {
  42  		*sin = *cos = x - x;
  43  		return;
  44  	}
  45  
  46  	/* argument reduction needed */
  47  	n = __rem_pio2(x, y);
  48  	s = __sin(y[0], y[1], 1);
  49  	c = __cos(y[0], y[1]);
  50  	switch (n&3) {
  51  	case 0:
  52  		*sin = s;
  53  		*cos = c;
  54  		break;
  55  	case 1:
  56  		*sin = c;
  57  		*cos = -s;
  58  		break;
  59  	case 2:
  60  		*sin = -s;
  61  		*cos = -c;
  62  		break;
  63  	case 3:
  64  	default:
  65  		*sin = -c;
  66  		*cos = s;
  67  		break;
  68  	}
  69  }
  70