1 /*
2 * Eukleides version 1.5.4
3 * Copyright (c) Christian Obrecht 2004-2010
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <math.h>
23 #include "error.h"
24 #include "symbol.h"
25 #include "core.h"
26 #include "utils.h"
27 #include "parser.tab.h"
28
not(void)29 void not(void)
30 {
31 PSHn(!pop_param().addr);
32 }
33
and(void)34 void and(void)
35 {
36 int a, b;
37
38 a = pop_param().addr;
39 b = pop_param().addr;
40 PSHn(a && b);
41 }
42
or(void)43 void or(void)
44 {
45 int a, b;
46
47 a = pop_param().addr;
48 b = pop_param().addr;
49 PSHn(a || b);
50 }
51
ternary(void)52 void ternary(void)
53 {
54 double x, y;
55 int z;
56 x = POPn;
57 y = POPn;
58 z = pop_param().addr;
59 PSHn(z ? y : x);
60 }
61
num_eq(void)62 void num_eq(void)
63 {
64 PSHn(EQL(POPn, POPn));
65 }
66
num_neq(void)67 void num_neq(void)
68 {
69 PSHn(NEQL(POPn, POPn));
70 }
71
num_lt(void)72 void num_lt(void)
73 {
74 PSHn(POPn > POPn);
75 }
76
num_leq(void)77 void num_leq(void)
78 {
79 PSHn(POPn >= POPn);
80 }
81
num_gt(void)82 void num_gt(void)
83 {
84 PSHn(POPn < POPn);
85 }
86
num_geq(void)87 void num_geq(void)
88 {
89 PSHn(POPn <= POPn);
90 }
91
pnt_eq(void)92 void pnt_eq(void)
93 {
94 _point *A, *B;
95
96 B = POP(_point);
97 A = POP(_point);
98 PSHn(EQL(A->x, B->x) && EQL(A->y, B->y));
99 }
100
pnt_neq(void)101 void pnt_neq(void)
102 {
103 _point *A, *B;
104
105 B = POP(_point);
106 A = POP(_point);
107 PSHn(NEQL(A->x, B->x) || NEQL(A->y, B->y));
108 }
109
collinear_points(void)110 void collinear_points(void)
111 {
112 _point *A, *B, *C;
113
114 C = POP(_point);
115 B = POP(_point);
116 A = POP(_point);
117 PSHn(ZERO(det2(B->x-A->x, B->y-A->y, C->x-A->x, C->y-A->y)));
118 }
119
vec_eq(void)120 void vec_eq(void)
121 {
122 _vector *u, *v;
123
124 v = POP(_vector);
125 u = POP(_vector);
126 PSHn(EQL(u->x, v->x) && EQL(u->y, v->y));
127 }
128
vec_neq(void)129 void vec_neq(void)
130 {
131 _vector *u, *v;
132
133 v = POP(_vector);
134 u = POP(_vector);
135 PSHn(NEQL(u->x, v->x) || NEQL(u->y, v->y));
136 }
137
collinear_vectors(void)138 void collinear_vectors(void)
139 {
140 _vector *u, *v;
141
142 v = POP(_vector);
143 u = POP(_vector);
144 PSHn(ZERO(det2(u->x, u->y, v->x, v->y)));
145 }
146
elem_eq(_set * s1,_set * s2)147 int elem_eq(_set *s1, _set *s2)
148 {
149 if (s1 == NULL && s2 == NULL) return 1;
150 if (s1 == NULL || s2 == NULL) return 0;
151 if (NEQL(s1->p->x, s2->p->x) || NEQL(s1->p->y, s2->p->y)) return 0;
152 return elem_eq(s1->next, s2->next);
153 }
154
set_eq(void)155 void set_eq(void)
156 {
157 _set *s1, *s2;
158
159 s2 = POP(_set);
160 s1 = POP(_set);
161 PSHn(elem_eq(s1, s2));
162 }
163
set_neq(void)164 void set_neq(void)
165 {
166 _set *s1, *s2;
167
168 s2 = POP(_set);
169 s1 = POP(_set);
170 PSHn(!elem_eq(s1, s2));
171 }
172
is_empty(void)173 void is_empty(void)
174 {
175 PSHn(POP(_set) == NULL);
176 }
177
elem_on_path(_point * A,double x,double y,_set * s)178 int elem_on_path(_point *A, double x, double y, _set *s)
179 {
180 double u, v;
181
182 if (s->next == NULL) return 0;
183 s = s->next;
184 u = s->p->x-A->x;
185 v = s->p->y-A->y;
186 if (ZERO(det2(x, y, u, v)) && u*x+v*y <= 0) return 1;
187 return elem_on_path(A, u, v, s);
188 }
189
on_path(void)190 void on_path(void)
191 {
192 _set *s;
193 _point *A;
194
195 s = POP(_set);
196 A = POP(_point);
197 if (s == NULL) PSHn(0);
198 else if (s->next == NULL) PSHn(EQL(A->x, s->p->x) && EQL(A->y, s->p->y));
199 else PSHn(elem_on_path(A, s->p->x-A->x, s->p->y-A->y, s));
200 }
201
elem_in_set(_point * A,_set * s)202 int elem_in_set(_point *A, _set *s)
203 {
204 if (s == NULL) return 0;
205 if (EQL(A->x, s->p->x) && EQL(A->y, s->p->y)) return 1;
206 return elem_in_set(A, s->next);
207 }
208
in_set(void)209 void in_set(void)
210 {
211 _set *s;
212 _point *A;
213
214 s = POP(_set);
215 A = POP(_point);
216 PSHn(elem_in_set(A, s));
217 }
218
lin_eq(void)219 void lin_eq(void)
220 {
221 _line *l1, *l2;
222 double u, v;
223
224 l2 = POP(_line);
225 l1 = POP(_line);
226 u = l2->x - l1->x;
227 v = l2->y - l1->y;
228 PSHn(ZERO(det2(u, v, Cos(l1->a), Sin(l1->a)))
229 && ZERO(det2(u, v, Cos(l2->a), Sin(l2->a))));
230 }
231
lin_neq(void)232 void lin_neq(void)
233 {
234 _line *l1, *l2;
235 double u, v;
236
237 l2 = POP(_line);
238 l1 = POP(_line);
239 u = l2->x - l1->x;
240 v = l2->y - l1->y;
241 PSHn(NEQL(det2(u, v, Cos(l1->a), Sin(l1->a)), 0)
242 || NEQL(det2(u, v, Cos(l2->a), Sin(l2->a)), 0));
243 }
244
on_line(void)245 void on_line(void)
246 {
247 _line *l;
248 _point *A;
249
250 l = POP(_line);
251 A = POP(_point);
252 PSHn(ZERO(det2(l->x-A->x, l->y-A->y, Cos(l->a), Sin(l->a))));
253 }
254
delta(double a,double b,double m)255 double delta(double a, double b, double m)
256 {
257 return fmod(fabs(a - b), m);
258 }
259
parallel_lines(void)260 void parallel_lines(void)
261 {
262 _line *l1, *l2;
263
264 l2 = POP(_line);
265 l1 = POP(_line);
266 PSHn(ZERO(delta(l1->a, l2->a, 180)));
267 }
268
perpendicular_lines(void)269 void perpendicular_lines(void)
270 {
271 _line *l1, *l2;
272
273 l2 = POP(_line);
274 l1 = POP(_line);
275 PSHn(EQL(delta(l1->a, l2->a, 180), 90));
276 }
277
cir_eq(void)278 void cir_eq(void)
279 {
280 _circle *c1, *c2;
281
282 c2 = POP(_circle);
283 c1 = POP(_circle);
284 PSHn(EQL(c1->x, c2->x) && EQL(c1->y, c2->y) && EQL(c1->r, c2->r));
285 }
286
cir_neq(void)287 void cir_neq(void)
288 {
289 _circle *c1, *c2;
290
291 c2 = POP(_circle);
292 c1 = POP(_circle);
293 PSHn(NEQL(c1->x, c2->x) || NEQL(c1->y, c2->y) || NEQL(c1->r, c2->r));
294 }
295
on_circle(void)296 void on_circle(void)
297 {
298 _circle *c;
299 _point *A;
300
301 c = POP(_circle);
302 A = POP(_point);
303 PSHn(EQL(hypot(c->x-A->x, c->y-A->y), c->r));
304 }
305
con_eq(void)306 void con_eq(void)
307 {
308 _conic *c1, *c2;
309
310 c2 = POP(_conic);
311 c1 = POP(_conic);
312 PSHn(c1->type == c2->type
313 && EQL(c1->x, c2->x) && EQL(c1->y, c2->y)
314 && EQL(c1->a, c2->a) && EQL(c1->b, c2->b)
315 && ZERO(delta(c1->d, c2->d, c1->type == PARABOLA ? 360 : 180)));
316 }
317
con_neq(void)318 void con_neq(void)
319 {
320 _conic *c1, *c2;
321
322 c2 = POP(_conic);
323 c1 = POP(_conic);
324 PSHn(c1->type != c2->type
325 || NEQL(c1->x, c2->x) || NEQL(c1->y, c2->y)
326 || NEQL(c1->a, c2->a) || NEQL(c1->b, c2->b)
327 || NEQL(delta(c1->d, c2->d, c1->type == PARABOLA ? 360 : 180), 0));
328 }
329
on_conic(void)330 void on_conic(void)
331 {
332 _conic *C;
333 _point *A;
334 double c, s, x, y, u, v;
335
336 C = POP(_conic);
337 A = POP(_point);
338 c = Cos(C->d);
339 s = Sin(C->d);
340 x = A->x - C->x;
341 y = A->y - C->y;
342 u = c*x + s*y;
343 v = -s*x + c*y;
344 switch (C->type) {
345 case ELLIPSE:
346 PSHn(EQL(u*u/(C->a*C->a) + v*v/(C->b*C->b), 1));
347 break;
348 case HYPERBOLA:
349 PSHn(EQL(u*u/(C->a*C->a) - v*v/(C->b*C->b), 1));
350 break;
351 case PARABOLA:
352 PSHn(EQL(C->a*(2*u + C->a), v*v));
353 break;
354 }
355 }
356
is_ellipse(void)357 void is_ellipse(void)
358 {
359 PSHn((POP(_conic))->type == ELLIPSE);
360 }
361
is_hyperbola(void)362 void is_hyperbola(void)
363 {
364 PSHn((POP(_conic))->type == HYPERBOLA);
365 }
366
is_parabola(void)367 void is_parabola(void)
368 {
369 PSHn((POP(_conic))->type == PARABOLA);
370 }
371
is_isosceles(void)372 void is_isosceles(void)
373 {
374 _point *A, *B, *C;
375
376 C = POP(_point);
377 B = POP(_point);
378 A = POP(_point);
379 PSHn(EQL(distance(C, A), distance(C, B)));
380 }
381
is_equilateral(void)382 void is_equilateral(void)
383 {
384 _point *A, *B, *C;
385 double c;
386
387 C = POP(_point);
388 B = POP(_point);
389 A = POP(_point);
390 c = distance(A, B);
391 PSHn(EQL(c, distance(B, C)) && EQL(c, distance(C, A)));
392 }
393
is_right(void)394 void is_right(void)
395 {
396 _point *A, *B, *C;
397 double a, b, c;
398
399 C = POP(_point);
400 B = POP(_point);
401 A = POP(_point);
402 a = distance(B, C);
403 b = distance(C, A);
404 c = distance(A, B);
405 PSHn(EQL(b*b, a*a + c*c));
406 }
407
is_parallelogram(void)408 void is_parallelogram(void)
409 {
410 _point *A, *B, *C, *D;
411
412 D = POP(_point);
413 C = POP(_point);
414 B = POP(_point);
415 A = POP(_point);
416 PSHn(EQL(A->x+C->x, B->x+D->x) && EQL(A->y+C->y, B->y+D->y));
417 }
418
is_rectangle(void)419 void is_rectangle(void)
420 {
421 _point *A, *B, *C, *D;
422 double a, b;
423
424 D = POP(_point);
425 C = POP(_point);
426 B = POP(_point);
427 A = POP(_point);
428 a = distance(A, C);
429 b = distance(B, D);
430 PSHn(EQL(A->x+C->x, B->x+D->x) && EQL(A->y+C->y, B->y+D->y) && EQL(a, b));
431 }
432
is_square(void)433 void is_square(void)
434 {
435 _point *A, *B, *C, *D;
436 double a, b, c, d;
437
438 D = POP(_point);
439 C = POP(_point);
440 B = POP(_point);
441 A = POP(_point);
442 a = distance(A, C);
443 b = distance(B, D);
444 c = distance(A, B);
445 d = distance(A, D);
446 PSHn(EQL(A->x+C->x, B->x+D->x) && EQL(A->y+C->y, B->y+D->y)
447 && EQL(a, b) && EQL(c, d));
448 }
449
eps_output(void)450 void eps_output(void)
451 {
452 #ifdef __eukleides__
453 PSHn(1);
454 #else
455 PSHn(0);
456 #endif
457 }
458
pstricks_output(void)459 void pstricks_output(void)
460 {
461 #ifdef __euktopst__
462 PSHn(1);
463 #else
464 PSHn(0);
465 #endif
466 }
467
display_output(void)468 void display_output(void)
469 {
470 #ifdef __geukleides__
471 PSHn(1);
472 #else
473 PSHn(0);
474 #endif
475 }
476
for_test(void)477 void for_test(void)
478 {
479 double c, s, e;
480
481 c = POPn;
482 s = POPn;
483 e = POPn;
484
485 PSHn(s);
486 if ((c > e && s > 0) || (c < e && s < 0))
487 PSHn(0);
488 else
489 PSHn(1);
490 }
491