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