aboutsummaryrefslogtreecommitdiff
path: root/ic-reals-6.3/math-lib/atan_R.c
blob: c79efab83c603c6b657e770bd8754f4699601978 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/*
 * Copyright (C) 2000, Imperial College
 *
 * This file is part of the Imperial College Exact Real Arithmetic Library.
 * See the copyright notice included in the distribution for conditions
 * of use.
 */

#include <stdio.h>
#include "real.h"
#include "real-impl.h"
#include "math-lib.h"

static TenXY *nextTensor(Real, Real, int);
static void atanInside();
static void atanPositive();
static void atanNegative();

Real
atan_R(Real x)
{
	Real u, v, w;
	Bool xLtEq1, xGtEqNeg1, xLtEq1_and_GtEqNeg1;
	static int doneInit = 0;

	if (!doneInit) {
		registerForceFunc(atanInside, "atanInside", 2);
		registerForceFunc(atanPositive, "atanPositive", 2);
		registerForceFunc(atanNegative, "atanNegative", 2);
		doneInit++;
	}

	xLtEq1 = ltEq_R_QInt(x, 1, 1);
	xGtEqNeg1 = gtEq_R_QInt(x, -1, 1);
	xLtEq1_and_GtEqNeg1 = and_B_B(xLtEq1, xGtEqNeg1);
		
	u = (Real) allocCls(atanInside, (void *) x);
	u->cls.tag.isSigned = TRUE;
	v = (Real) allocCls(atanPositive, (void *) x);
	v->cls.tag.isSigned = TRUE;
	w = (Real) allocCls(atanNegative, (void *) x);
	w->cls.tag.isSigned = TRUE;
	
#ifdef DAVINCI
		beginGraphUpdate();
		newEdgeToOnlyChild(u, x);
		newEdgeToOnlyChild(v, x);
		newEdgeToOnlyChild(w, x);
		endGraphUpdate();
#endif

	/*
	 * The order of the tests in the alt is not semantically
	 * significant. The tests are applied in order, so there is a
	 * very modest performance improvement by putting the -1,1 tests
	 * before the 999/1000,-999/1000 tests.  Also there is a very
	 * small win by doing the negative test before the positive test.
	 */
	return realIf(3,
		xLtEq1_and_GtEqNeg1,			u,
		gtEq_R_QInt(x, 999, 1000),		v,
		ltEq_R_QInt(x, -999, 1000),		w);
}

static TenXY *
nextTensor(Real x, Real y, int n)
{
    return (TenXY *) tensor_Int(x, y, 2*n+1, 1, -1, -(2*n+1),
					2*n+1, 2*n+1, 2*n+1, 2*n+1);
}

static void
atanInside()
{
	Cls *cls, *newCls;
	Real x;
	ClsData *data;
	void stdTensorCont();

	cls = (Cls *) POP;
	x = (Real) cls->userData;
	
	if ((data = (ClsData *) malloc(sizeof(ClsData))) == NULL)
		Error(FATAL, E_INT, "atan_R", "malloc failed");

	data->n = 1;
	data->x = x;
	data->nextTensor = nextTensor;

	newCls = allocCls(stdTensorCont, (void *) data);
	newCls->tag.isSigned = FALSE;

	cls->redirect = tensor_Int(x, (Real) newCls, 1, 1, 1, -1, 0, 1, 0, 1);

#ifdef DAVINCI
		beginGraphUpdate();
		newEdgeToOnlyChild(newCls, x);
		drawEqEdge(cls, cls->redirect);
		endGraphUpdate();
#endif
}

/*
 * This implements the identity:
 *   x > 0 implies atan(x) = atan(szero * x) + \pi/4
 */
static void
atanPositive()
{
  Cls *cls;
	Real x, y;

	cls = (Cls *) POP;
	x = (Real) cls->userData;
	
	y = atan_R(matrix_Int(x, 1, 1, -1, 1));
	cls->redirect = add_R_R(y, div_R_Int(Pi, 4));
}

/*
 * This implements the identity:
 *   x < 0 implies atan(x) = atan(szero * (sneg^(-1) * x) - \pi/4
 */
static void
atanNegative()
{
  Cls *cls;
	Real x, y;

	cls = (Cls *) POP;
	x = (Real) cls->userData;
	
	y = atan_R(matrix_Int(x, 1, -1, 1, 1));
	cls->redirect = sub_R_R(y, div_R_Int(Pi, 4));
}