aboutsummaryrefslogtreecommitdiff
path: root/ic-reals-6.3/real-impl.h~
blob: 4d202aa8ae34f8677118015dfd1428a632983809 (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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
/*
 * 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.
 */

#ifdef DAVINCI
#define DAVINCI 1
#else
#define DAVINCI 0
#endif

/*
 * There are three choices for tracing.
 * TRACE=0, off
 * TRACE=1, on
 * TRACE=traceOn, software controlled.
 *
 * The default, if not set when compiled (-DTRACE=<val>), is off.
 */
#ifndef TRACE
#define TRACE 0
#endif

void debugTrace(int);   /* this function just sets traceOn to the argument */
extern int traceOn;

/*
 * The following are used in the routine
 * Error(fatal_flag, error_type, proc, fmt, arg... )
 *
 * When FATAL is used (rather than !FATAL), Error exists after
 * printing a message.
 */
#define FATAL   1

/*
 * Error types, E_SYS for system errors (eg opening files) and E_INT
 * for internal errors not involving system calls.
 */
#define E_SYS   1
#define E_INT   2
void Error(int fatal_flag, int error_type, char *proc, char *fmt, ...);
 
/*
 * Macros and utilities not meant for the user.
 */
#ifndef MAX
#define MAX(a,b) ((a) >= (b) ? (a) : (b))
#endif

#ifndef MIN
#define MIN(a,b) ((a) <= (b) ? (a) : (b))
#endif

#ifdef USED_FOR_GMP_2
/*
 * This is a little hack to avoid assignment and storage allocation
 * within gmp. This just swaps the fields describing an mpz_t and
 * that way we can multiply two matrices and put the result in the
 * first matrix without allocating temporary storage every time.
 */
#define MPZ_SWAP(a,b) \
    ({mpz_t localz; \
      localz[0] = (a)[0]; \
      (a)[0] = (b)[0]; \
      (b)[0] = localz[0];})
#endif

#define MPZ_SWAP(a,b)	mpz_swap(a,b)

/*
 * This macro evaluates its argument more that once. It is applied to the output
 * of some GMP comparison functions. Some comparisons return {-1,0,1} while
 * others only specify a negative, zero or positive value. The former is
 * slightly better since we can use a case statement. For the latter
 * functions we wrap them in SIGN so we can uniformly use case statements.
 */
#define MPZ_SIGN(x) ((x > 0) ? 1 : ((x < 0) ? -1 : 0))
#define MAXINT  0x7fffffff

/*
 * These are available for temporary storage. But one must
 * be careful. They are used in the matrix multiplication operations
 * amongst other places.
 */
extern mpz_t tmpa_z, tmpb_z, tmpc_z, tmpd_z, tmpe_z, tmpf_z;

/*
 * The constant zero as a big integer
 */
extern mpz_t zero_z;

extern Matrix bigTmpMat;
extern Tensor bigTmpTen;

extern int debug;

void canonVector(Vector);
int normalizeVector(Vector);
int normalizeMatrix(Matrix);
int normalizeTensor(Tensor);

void absorb_DigsX_Into_DigsX(DigsX *);
void absorb_DigsX_Into_MatX(MatX *);
void absorb_DigsX_Into_TenXY_X(TenXY *);
void absorb_DigsX_Into_TenXY_Y(TenXY *);
void reduceDigsXList(DigsX *);

/*
 *
 * The entire computation is driven by a stack of frames which define
 * the work to be done.  The stack grows upward with sp pointing to the
 * top of the stack.
 */
#ifndef STACK_SIZE
#define STACK_SIZE 8000
#endif

extern unsigned *stack;
extern unsigned *stackBound;
extern unsigned *sp;

#define NEED_STACK(n) \
	({if ((sp + n) >= stackBound) \
		Error(FATAL, E_INT, "push", "stack overflow");})

#define PUSH(x)		(*++sp = (unsigned) x)
#define POP			(*sp--)

#if DAVINCI == 1
void highlightTOS();

#define PUSH_4(func, dst, a, b) \
	push_4((unsigned) (func), (unsigned) (dst), (unsigned) (a), (unsigned) (b))

#define PUSH_3(func, dst, a) \
	push_3((unsigned) (func), (unsigned) (dst), (unsigned) (a))

#define PUSH_2(func, dst) \
	push_2((unsigned) (func), (unsigned) (dst))

/*
 * This uses the GNU inline extension.  Could be done with macros but
 * inlines are nicer.
 */
static inline void
push_4(unsigned func, unsigned dst, unsigned a, unsigned b)
{
	NEED_STACK(4);
	PUSH(b);
	PUSH(a);
	PUSH(dst);
	PUSH(func);
	highlightTOS();
}

static inline void
push_3(unsigned func, unsigned dst, unsigned a)
{
	NEED_STACK(3);
	PUSH(a);
	PUSH(dst);
	PUSH(func);
	highlightTOS();
}

static inline void
push_2(unsigned func, unsigned dst)
{
	NEED_STACK(2);
	PUSH(dst);
	PUSH(func);
	highlightTOS();
}

#else
#define PUSH_4(func, dst, a, b) \
	({NEED_STACK(4); \
	PUSH(b); \
	PUSH(a); \
	PUSH(dst); \
	PUSH(func);})
#define PUSH_3(func, dst, a) \
	({NEED_STACK(3); \
	PUSH(a); \
	PUSH(dst); \
	PUSH(func);})
#define PUSH_2(func, dst) \
	({NEED_STACK(2); \
	PUSH(dst); \
	PUSH(func);})
#endif

/*
 * this is used to force blocking when reading responses from
 * daVinci.
 */
#define BLOCK 1

/*
 * The following constant is the default number of digits forced from
 * an LFT as demanded by predicates and when the epsilon-delta analysis
 * doesn't tell us useful information.
 */
#ifndef DEFAULT_FORCE_COUNT
#define DEFAULT_FORCE_COUNT 1
#endif

Vec *allocVec();
DigsX *allocDigsX();
MatX *allocMatX();
TenXY *allocTenXY();

SignX *allocSignX(Real, int);
Cls *allocCls(void (*)(), void *);

/*
 * This is the type of a function for emitting a digit from a vector, matrix
 * or tensor. So "edf" means "emit digit function". The argument type is given
 * as a (void *) rather than LFT because there are occasions when it is applied
 * to things other than LFTs, for example in the square root of a rational.
 */
typedef bool (*edf)(void *, Digit *);
int emitDigits(DigsX *, edf, void *, int);

void newDigsX(DigsX *);

void multVectorPairTimesVector(Vector, Vector, Vector);
void multVectorPairTimesMatrix(Vector, Vector, Matrix);
void multVectorPairTimesSmallMatrix(Vector, Vector, SmallMatrix);
void makeSmallMatrixFromDigits(SmallMatrix, DigsX *);
void makeMatrixFromDigits(Matrix, DigsX *);

/*
 * Now we define the ``prototypes'' for all the functions available
 * to applications.
 */
Digit intToDigit(int);
char *digitToString(Digit);
char *signToString(Sign);
char *comparisonToString(Comparison);

/*
 * For debugging purposes we provide a facility to map a force method to
 * a descriptor which gives a printable string for the method, 
 * the number of arguments expected by the method and, in the case when the
 * consumer is an element in the heap with 2 arguments, a constant indicating
 * whether the information is coming from the x or y argument.
 */
#define ARG_X 0
#define ARG_Y 1
#define ARG_NEITHER 2

typedef struct {
	void (*func)();
	char *funcName;
	int nArgs;
	int argXOrY;
} ForceFuncDesc;

ForceFuncDesc *getDescForForceFunc(void (*)());

void registerForceFunc(void (*)(), char *, int);

extern int nodeId;

extern int defaultForceCount;
extern int forceDecUpperBound;
extern int stackSize;