00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #pragma GCC dependency "Makefile" maybe some command line defines have changed
00026
00038 #include "plint.h"
00039 #include "error.h"
00040
00041 #include "op.h"
00042
00043 #define PLINT_SGN(__x__) ((__x__) < 0 ? -1 : +1)
00044 #define PLINT_MIN(__a__, __b__) (((__a__) < (__b__)) ? (__a__) : (__b__))
00045 #define PLINT_MAX(__a__, __b__) (((__a__) > (__b__)) ? (__a__) : (__b__))
00046
00060 int plint_num_nat(plint_num_t n)
00061 {
00062 int ret = plint_num_n2i(n);
00063 return (ret < 0) ? -ret : ret;
00064 }
00065
00071 plint_num_t plint_num_rnd(plint_num_t n)
00072 {
00073 n.val.num_int = 1 + (int)(((double)plint_num_nat(n))*rand()/(RAND_MAX+1.0));
00074 return n;
00075 }
00076
00080 #define PLINT_OP_MINX(__fnc__,__op__) \
00081 plint_num_t plint_num_##__fnc__(plint_num_t l, plint_num_t r) \
00082 { \
00083 plint_num_t x; \
00084 if (0); \
00085 else if (l.typ == PLINT_num_int && r.typ == PLINT_num_int) \
00086 x = (l.val.num_int __op__ r.val.num_int) ? l : r; \
00087 else if (l.typ == PLINT_num_int && r.typ == PLINT_num_dbl) \
00088 { \
00089 x.typ = PLINT_num_dbl; \
00090 x.val.num_dbl = (((double)l.val.num_int) __op__ r.val.num_dbl) ? \
00091 (double)l.val.num_int : r.val.num_dbl; \
00092 } \
00093 else if (l.typ == PLINT_num_dbl && r.typ == PLINT_num_int) \
00094 { \
00095 x.typ = PLINT_num_dbl; \
00096 x.val.num_dbl = (l.val.num_dbl __op__ ((double)r.val.num_int)) ? \
00097 l.val.num_dbl : (double)r.val.num_int; \
00098 } \
00099 else if (l.typ == PLINT_num_dbl && r.typ == PLINT_num_dbl) \
00100 x = (l.val.num_dbl __op__ r.val.num_dbl) ? l : r; \
00101 else \
00102 PLINT_ERROR(PLINT_ERR_EVEXPR); \
00103 return x; \
00104 }
00105
00106 PLINT_OP_MINX(min, <)
00107 PLINT_OP_MINX(max, >)
00108
00130 #define PLINT_OP_ARITM(__fnc__,__op__) \
00131 void plint_num_##__fnc__(plint_num_t * l, plint_num_t r) \
00132 { \
00133 if (0); \
00134 else if (l->typ == PLINT_num_int && r.typ == PLINT_num_int) \
00135 { \
00136 l->typ = PLINT_num_int; \
00137 l->val.num_int __op__##= r.val.num_int; \
00138 } \
00139 else if (l->typ == PLINT_num_int && r.typ == PLINT_num_dbl) \
00140 { \
00141 l->typ = PLINT_num_dbl; \
00142 l->val.num_dbl = ((double)l->val.num_int) __op__ r.val.num_dbl; \
00143 } \
00144 else if (l->typ == PLINT_num_dbl && r.typ == PLINT_num_int) \
00145 { \
00146 l->typ = PLINT_num_dbl; \
00147 l->val.num_dbl = l->val.num_dbl __op__ ((double)r.val.num_int); \
00148 } \
00149 else if (l->typ == PLINT_num_dbl && r.typ == PLINT_num_dbl) \
00150 { \
00151 l->typ = PLINT_num_dbl; \
00152 l->val.num_dbl __op__##= r.val.num_dbl; \
00153 } \
00154 else \
00155 PLINT_ERROR(PLINT_ERR_EVEXPR); \
00156 }
00157
00158
00159 PLINT_OP_ARITM(add, +)
00160 PLINT_OP_ARITM(sub, -)
00161 PLINT_OP_ARITM(mul, *)
00162 PLINT_OP_ARITM(div, /)
00163
00164 #undef PLINT_OP_ARITM
00165
00166 void plint_num_rem(plint_num_t * l, plint_num_t r)
00167 {
00168 if (0);
00169 else if (l->typ == PLINT_num_int && r.typ == PLINT_num_int)
00170 {
00171 l->typ = PLINT_num_int;
00172 l->val.num_int = l->val.num_int % r.val.num_int;
00173 }
00174 else
00175 PLINT_ERROR(PLINT_ERR_EVEXPR);
00176 }
00177
00178
00179
00180
00181
00182
00183
00184 void plint_num_umin(plint_num_t * n)
00185 {
00186 switch (n->typ)
00187 {
00188 case PLINT_num_int:
00189 n->val.num_int = -n->val.num_int;
00190 break;
00191
00192 case PLINT_num_dbl:
00193 n->val.num_dbl = -n->val.num_dbl;
00194 break;
00195
00196 default:
00197 PLINT_ERROR(PLINT_ERR_EVEXPR);
00198 }
00199 }
00200
00201 void plint_num_upls(plint_num_t * n)
00202 {
00203 switch (n->typ)
00204 {
00205 case PLINT_num_int:
00206 break;
00207
00208 case PLINT_num_dbl:
00209 break;
00210
00211 default:
00212 PLINT_ERROR(PLINT_ERR_EVEXPR);
00213 }
00214 }
00215
00216 void plint_num_udiv(plint_num_t * n)
00217 {
00218 switch (n->typ)
00219 {
00220 case PLINT_num_int:
00221 n->typ = PLINT_num_dbl;
00222 n->val.num_dbl = 1./(double)n->val.num_int;
00223 break;
00224
00225 case PLINT_num_dbl:
00226 n->val.num_dbl = 1./n->val.num_dbl;
00227 break;
00228
00229 default:
00230 PLINT_ERROR(PLINT_ERR_EVEXPR);
00231 }
00232 }
00233
00241 #define PLINT_OP_LOGIC(__fnc__,__op__) \
00242 void plint_num_##__fnc__(plint_num_t * l, plint_num_t r) \
00243 { \
00244 if (l->typ == PLINT_num_int && r.typ == PLINT_num_int) \
00245 l->val.num_int __op__##= r.val.num_int; \
00246 else \
00247 PLINT_ERROR(PLINT_ERR_EVEXPR); \
00248 }
00249
00250
00251 PLINT_OP_LOGIC(and, &)
00252 PLINT_OP_LOGIC(or , |)
00253 PLINT_OP_LOGIC(xor, ^)
00254
00255 #undef PLINT_OP_LOGIC
00256
00257
00258 void plint_num_unot(plint_num_t * n)
00259 {
00260 if (n->typ == PLINT_num_int)
00261 n->val.num_int = ~n->val.num_int;
00262 else
00263 PLINT_ERROR(PLINT_ERR_EVEXPR);
00264 }
00265
00273 #define PLINT_OP_COMPARE(__fnc__, __op__) \
00274 int plint_num_##__fnc__(plint_num_t l, plint_num_t r) \
00275 { \
00276 if (0) \
00277 return 0; \
00278 else if (l.typ == PLINT_num_int && r.typ == PLINT_num_int) \
00279 return l.val.num_int __op__ r.val.num_int; \
00280 else if (l.typ == PLINT_num_int && r.typ == PLINT_num_dbl) \
00281 return ((double)l.val.num_int) __op__ r.val.num_dbl; \
00282 else if (l.typ == PLINT_num_dbl && r.typ == PLINT_num_int) \
00283 return l.val.num_dbl __op__ ((double)r.val.num_int); \
00284 else if (l.typ == PLINT_num_dbl && r.typ == PLINT_num_dbl) \
00285 return l.val.num_dbl __op__ r.val.num_dbl; \
00286 else \
00287 PLINT_ERROR(PLINT_ERR_EVEXPR); \
00288 }
00289
00290
00291 PLINT_OP_COMPARE(lt , < )
00292 PLINT_OP_COMPARE(gt , > )
00293 PLINT_OP_COMPARE(lte, <=)
00294 PLINT_OP_COMPARE(gte, >=)
00295 PLINT_OP_COMPARE(equ, ==)
00296 PLINT_OP_COMPARE(neq, !=)
00297
00298
00299 #undef PLINT_OP_COMPARE
00300
00315 inline void plint_pnt_ucnj(plint_pnt_t * p)
00316 {
00317 p->y = -p->y;
00318 }
00319
00320 #define PLINT_OP_ARITM(__fun__, __op__) \
00321 inline void plint_pnt_##__fun__(plint_pnt_t * l, plint_pnt_t r) \
00322 { \
00323 l->x __op__##= r.x; \
00324 l->y __op__##= r.y; \
00325 }
00326
00327 PLINT_OP_ARITM(add, +)
00328 PLINT_OP_ARITM(sub, -)
00329
00330 #undef PLINT_OP_ARITM
00331
00332 void plint_pnt_mul(plint_pnt_t * l, plint_pnt_t r)
00333 {
00334 plint_pnt_t ll = *l;
00335 l->x = ll.x * r.x - ll.y * r.y;
00336 l->y = ll.x * r.y + ll.y * r.x;
00337 }
00338
00339 void plint_pnt_div(plint_pnt_t * l, plint_pnt_t r)
00340 {
00341 PLINT_ERROR(PLINT_ERR_EVEXPR);
00342 }
00343
00344 inline void plint_pnt_umin(plint_pnt_t * p)
00345 {
00346 p->x = -p->x;
00347 p->y = -p->y;
00348 }
00349
00357 #define PLINT_PNT_CMP(__fnc__, __op__) \
00358 inline int plint_pnt_##__fnc__(plint_pnt_t l, plint_pnt_t r) \
00359 { \
00360 return (l.x __op__ r.x) && (r.y __op__ r.y); \
00361 }
00362
00363 PLINT_PNT_CMP(equ, ==)
00364 PLINT_PNT_CMP(neq, !=)
00365 PLINT_PNT_CMP(lte, <=)
00366 PLINT_PNT_CMP(gte, >=)
00367 PLINT_PNT_CMP(lt , < )
00368 PLINT_PNT_CMP(gt , > )
00369
00370 #undef PLINT_PNT_CMP
00371
00379 #define PLINT_OP_ARITM(__fnc__, __op__) \
00380 void plint_pnt_num_##__fnc__(plint_pnt_t * l, plint_num_t r) \
00381 { \
00382 double d = plint_num_n2d(r); \
00383 l->x __op__##= d; \
00384 l->y __op__##= d; \
00385 }
00386
00387 PLINT_OP_ARITM(add, +)
00388 PLINT_OP_ARITM(sub, -)
00389 PLINT_OP_ARITM(mul, *)
00390 PLINT_OP_ARITM(div, /)
00391
00392 void plint_pnt_num_rem(plint_pnt_t * l, plint_num_t r)
00393 {
00394 int i = plint_num_n2i(r);
00395 l->x %= i;
00396 l->y %= i;
00397 }
00398
00399 #undef PLINT_OP_ARITM
00400
00412
00413
00414
00415
00416 #define PLINT_OP_ARITM(__fun__) \
00417 inline void plint_2pt_##__fun__(plint_2pt_t * l, plint_2pt_t r) \
00418 { \
00419 plint_pnt_##__fun__(0+l->PP, r.P.I); \
00420 plint_pnt_##__fun__(1+l->PP, r.P.Z); \
00421 }
00422
00423 PLINT_OP_ARITM(add)
00424 PLINT_OP_ARITM(sub)
00425 PLINT_OP_ARITM(mul)
00426
00427 inline void plint_2pt_invX(plint_2pt_t * p)
00428 {
00429 p->P.I.x = -p->P.I.x; p->P.Z.x = -p->P.Z.x;
00430 }
00431
00432 inline void plint_2pt_invY(plint_2pt_t * p)
00433 {
00434 p->P.I.y = -p->P.I.y; p->P.Z.y = -p->P.Z.y;
00435 }
00436
00437 inline void plint_2pt_invO(plint_2pt_t * p)
00438 {
00439 plint_2pt_invX(p); plint_2pt_invY(p);
00440 }
00441
00442 #undef PLINT_OP_ARITM
00443
00444
00445
00446
00447
00448
00449 inline void plint_2pt_int(plint_2pt_t * l, plint_2pt_t r)
00450 {
00451 plint_2pt_t *lr[2] = { l, &r };
00452 int f[2] = { 0, 0 }, fk;
00453 int i, j, k;
00454
00455 for (k = 0; k < 2; ++k)
00456 for (i = 0; i < 2; ++i, *lr[k] = plint_2pt_cross(*lr[k]))
00457 for (j = 0; j < 2; ++i, *lr[k] = plint_2pt_switch(*lr[k]))
00458 if (plint_pnt_ine_2pt(lr[k]->P.I, *lr[1-k]))
00459 {
00460 f[k] = !0;
00461 i = j = 1;
00462 }
00463
00464 for(fk = !0; ;fk = !fk)
00465 {
00466 for (k = 0; k < 2; ++k)
00467 if (f[k] == fk)
00468 break;
00469
00470 if (fk)
00471 {
00472 if (k == 2)
00473 {
00474 plint_2pt_t ret = PLINT_2pt_INIT_NUL;
00475 *l = ret;
00476 return;
00477 }
00478 }
00479 else
00480 {
00481 switch (k)
00482 {
00483 case 0: *l = r; break;
00484 case 1: break;
00485 case 2: l->P.Z = r.P.I; break;
00486 }
00487 return;
00488 }
00489 }
00490 }
00491
00492 inline void plint_2pt_reu(plint_2pt_t * l, plint_2pt_t r)
00493 {
00494 plint_2pt_t ll = plint_2pt_canonic(*l), rr = plint_2pt_canonic(r);
00495 plint_2pt_t lr = PLINT_2pt_INIT(ll.rect.TopLeft, rr.rect.TopLeft), LR = PLINT_2pt_INIT(ll.rect.BotRight, rr.rect.BotRight);
00496 lr = plint_2pt_canonic(lr); LR = plint_2pt_canonic(LR);
00497 l->rect.TopLeft = lr.rect.TopLeft; l->rect.BotRight = LR.rect.BotRight;
00498 }
00499
00500
00501
00502
00503
00504
00505 #define PLINT_2PT_CMP(__fnc__) \
00506 inline int plint_2pt_##__fnc__(plint_2pt_t l, plint_2pt_t r) \
00507 { \
00508 plint_2pt_t ll = plint_2pt_canonic(l), rr = plint_2pt_canonic(r); \
00509 return plint_pnt_##__fnc__(ll.rect.TopLeft, rr.rect.TopLeft) && \
00510 plint_pnt_##__fnc__(ll.rect.BotRight, rr.rect.BotRight); \
00511 }
00512
00513 PLINT_2PT_CMP(equ)
00514 PLINT_2PT_CMP(lt )
00515 PLINT_2PT_CMP(gt )
00516
00517 inline int plint_2pt_neq(plint_2pt_t l, plint_2pt_t r)
00518 {
00519 return !plint_2pt_equ(l, r);
00520 }
00521
00522 inline int plint_2pt_lte(plint_2pt_t l, plint_2pt_t r)
00523 {
00524 return !plint_2pt_gt (l, r);
00525 }
00526
00527 inline int plint_2pt_gte(plint_2pt_t l, plint_2pt_t r)
00528 {
00529 return !plint_2pt_lt (l, r);
00530 }
00531
00532 #undef PLINT_2PT_CMP
00533
00534
00535
00536
00537
00538
00539 #define PLINT_OP_ARITM(__fnc__) \
00540 void plint_2pt_num_##__fnc__(plint_2pt_t * l, plint_num_t r) \
00541 { \
00542 plint_pnt_num_##__fnc__(&l->P.I, r); \
00543 plint_pnt_num_##__fnc__(&l->P.Z, r); \
00544 }
00545
00546 PLINT_OP_ARITM(add)
00547 PLINT_OP_ARITM(sub)
00548 PLINT_OP_ARITM(mul)
00549 PLINT_OP_ARITM(div)
00550 PLINT_OP_ARITM(rem)
00551
00552 #undef PLINT_OP_ARITM
00553
00554
00555
00556
00557
00558
00559 #define PLINT_OP_ARITM(__fnc__) \
00560 void plint_2pt_pnt_##__fnc__(plint_2pt_t * l, plint_pnt_t r) \
00561 { \
00562 plint_pnt_##__fnc__(&l->P.I, r); \
00563 plint_pnt_##__fnc__(&l->P.Z, r); \
00564 }
00565
00566 PLINT_OP_ARITM(add)
00567 PLINT_OP_ARITM(sub)
00568 PLINT_OP_ARITM(mul)
00569
00570 #undef PLINT_OP_ARITM
00571
00572
00573
00574
00575
00576
00577 inline int plint_pnt_in_2pt(plint_pnt_t l, plint_2pt_t r)
00578 {
00579 return
00580 PLINT_SGN(l.x-r.P.I.x) + PLINT_SGN(l.x-r.P.Z.x) == 0 &&
00581 PLINT_SGN(l.y-r.P.I.y) + PLINT_SGN(l.y-r.P.Z.y) == 0 ;;
00582 }
00583 inline int plint_pnt_ine_2pt(plint_pnt_t l, plint_2pt_t r)
00584 {
00585 return
00586 plint_pnt_in_2pt(l, r) ||
00587 l.x == r.P.I.x || l.x == r.P.Z.x ||
00588 l.y == r.P.I.y || l.y == r.P.Z.y ;;
00589 }
00590 inline int plint_pnt_out_2pt(plint_pnt_t l, plint_2pt_t r)
00591 {
00592 return !plint_pnt_ine_2pt(l, r);
00593 }
00594 inline int plint_pnt_oute_2pt(plint_pnt_t l, plint_2pt_t r)
00595 {
00596 return !plint_pnt_in_2pt(l, r);
00597 }
00598
00607 #include <regex.h>
00608
00609
00610 #define PLINT_str_ACUM(__r__, __n__, __s__) \
00611 ({ \
00612 plint_str_t __x = PLINT_str_INIT(__s__, __n__); \
00613 char __y = __x.s[__x.n]; \
00614 __x.s[__x.n] = '\0'; \
00615 plint_str_add(&__r__, __x); \
00616 __x.s[__x.n] = __y; \
00617 })
00618
00619
00620
00621
00622
00623
00624 void plint_str_mul(plint_str_t * s, size_t i)
00625 {
00626 plint_str_t r;
00627 PLINT_str_NEW(r, s->n * i);
00628 if (r.n)
00629 for (; i; strncpy(r.s + (--i * s->n), s->s, s->n));
00630 r.s[r.n] = '\0';
00631 plint_str_fre(*s);
00632 *s = r;
00633 }
00634
00635
00636
00637
00638
00639 void plint_str_sub(plint_str_t * x, plint_str_t y)
00640 {
00641 plint_str_t ret;
00642 size_t l, r;
00643 l = strspn(x->s, y.s);
00644 if (l < x->n)
00645 {
00646 plint_str_t s = plint_str_str(*x, -1, 0);
00647 r = strspn(s.s, y.s);
00648 plint_str_fre(s);
00649 ret = plint_str_new(x->s + l, x->n - l - r);
00650 }
00651 else
00652 PLINT_str_EMPTY(ret);
00653
00654 plint_str_fre(*x);
00655 *x = ret;
00656 }
00657
00658
00659
00660
00661
00662 void plint_str_rem(plint_str_t * l, plint_str_t t)
00663 {
00664 size_t i = -1, n;
00665 plint_str_t r;
00666 PLINT_str_EMPTY(r);
00667 while (++i < l->n)
00668 if ((n = strcspn(l->s + i, t.s)) > 0)
00669 {
00670 PLINT_str_ACUM(r, n, l->s + i);
00671 i += n;
00672 }
00673 plint_str_fre(*l);
00674 *l = r;
00675 }
00676
00677 void plint_str_sed(plint_str_t * replace, plint_str_t regex, plint_str_t with)
00678 {
00679 plint_str_t ret;
00680 regex_t reg;
00681 regmatch_t rem[10];
00682 regoff_t off;
00683 int n_sub = 0, (*a_sub)[2];
00684
00685 if (regex.n == 0)
00686 PLINT_str_EMPTY(ret);
00687 else
00688 {
00689 if (regcomp(®, regex.s, PLINT_REX_FLAGS))
00690 {
00691 plint_str_fre(*replace); plint_str_fre(regex); plint_str_fre(with);
00692 PLINT_ERROR(PLINT_ERR_REX);
00693 }
00694
00695 {
00696 char * w = with.s;
00697 a_sub = malloc(sizeof(int[2]));
00698 a_sub[n_sub++][0] = -2;
00699 while ((w = strchr(w, '\\')) && *++w)
00700 if (isdigit(*w))
00701 {
00702 a_sub = realloc(a_sub, ++n_sub*sizeof(int[2]));
00703 a_sub[n_sub-1][0] = w-with.s-1;
00704 a_sub[n_sub-1][1] = *w-'0';
00705 }
00706 }
00707
00708 PLINT_str_EMPTY(ret);
00709
00710 rem->rm_eo = off = 0;
00711
00712 while (!regexec(®, replace->s + (off += rem->rm_eo), 10, rem, 0))
00713 {
00714 int m, n;
00715
00716 if (rem->rm_so > 0)
00717 PLINT_str_ACUM(ret, rem->rm_so, replace->s + off);
00718
00719 for (m = 1; m < n_sub; ++m)
00720 {
00721 n = a_sub[m][0]-a_sub[m-1][0];
00722 if (n > 2)
00723 PLINT_str_ACUM(ret, n-2, with.s+a_sub[m-1][0]+2);
00724 n = a_sub[m][1];
00725 if (rem[n].rm_so < rem[n].rm_eo)
00726 PLINT_str_ACUM(ret, rem[n].rm_eo-rem[n].rm_so, replace->s+off+rem[n].rm_so);
00727 }
00728 n = with.n-a_sub[m-1][0];
00729 if (n > 2)
00730 PLINT_str_ACUM(ret, n-2, with.s+a_sub[m-1][0]+2);
00731 }
00732
00733 if (off < replace->n)
00734 PLINT_str_ACUM(ret, replace->n-off, replace->s+off);
00735
00736 free(a_sub);
00737 regfree(®);
00738 }
00739
00740 plint_str_fre(*replace);
00741 *replace = ret;
00742 }
00743
00744 plint_tab_t plint_str_rex(plint_str_t l, plint_str_t t)
00745 {
00746 plint_tab_t ret;
00747
00748 regex_t reg;
00749 regmatch_t rem;
00750 regoff_t off;
00751
00752 plint_ptr_t ptr = PLINT_PTR_NEW(tab, PLINT_tab_INIT_NUL);
00753
00754 if (l.n > 0)
00755 {
00756 if (regcomp(®, l.s, PLINT_REX_FLAGS))
00757 {
00758 plint_str_fre(l); plint_str_fre(t); plint_ptr_fre(ptr);
00759 PLINT_ERROR(PLINT_ERR_REX);
00760 }
00761
00762 rem.rm_eo = off = 0;
00763
00764 while (!regexec(®, t.s + (off += rem.rm_eo), 1, &rem, 0))
00765 {
00766 plint_str_t x = plint_str_new(t.s + off + rem.rm_so, rem.rm_eo - rem.rm_so);
00767 PLINT_tab_GROW(ptr->val.tab, +=1);
00768 ptr->val.tab.a[ptr->val.tab.n-1] = plint_bar_new(PLINT_PTR_NEW(tab, PLINT_tab_INIT(2)));
00769 0[plint_var_tab(ptr->val.tab.a[ptr->val.tab.n-1]) .a] = plint_bar_new(PLINT_PTR_NEW(num_int, off + rem.rm_so));
00770 1[plint_var_tab(ptr->val.tab.a[ptr->val.tab.n-1]) .a] = plint_bar_new(plint_str_ptr(x));
00771 }
00772
00773 regfree(®);
00774 }
00775
00776 ret = plint_tab_dup(ptr->val.tab);
00777 plint_ptr_fre(ptr);
00778
00779 return ret;
00780 }
00781
00782 void plint_str_loc(plint_str_t * x)
00783 {
00784 for (x->n = 0; x->s[x->n]; ++x->n)
00785 x->s[x->n] = tolower(x->s[x->n]);
00786 }
00787
00788 void plint_str_upc(plint_str_t * x)
00789 {
00790 for (x->n = 0; x->s[x->n]; ++x->n)
00791 x->s[x->n] = tolower(x->s[x->n]);
00792 }
00793
00794
00795
00796
00797
00798 int plint_str_inc(plint_str_t needle, plint_str_t haystack, int d)
00799 {
00800 if (!needle.n)
00801 return !0;
00802 if (!haystack.n)
00803 return 0;
00804 return !! ((d > 0 ) ? strstr(haystack.s, needle.s) : strstr(needle.s, haystack.s));
00805 }
00806
00807 #undef PLINT_str_ACUM
00808
00818
00819
00820
00821
00822 void plint_tab_mul(plint_tab_t * t, size_t m)
00823 {
00824 if (!m) {
00825 plint_tab_fre(*t);
00826 PLINT_tab_EMPTY(*t);
00827 } else {
00828 size_t n = t->n, k, l = n * m;
00829 PLINT_tab_GROW(*t, *=m);
00830 while (--m)
00831 for (k = n; k--; )
00832 t->a[--l] = plint_var_dup(t->a[k]);
00833 }
00834 }
00835
00836
00837
00838
00839
00840 int plint_tab_equ(plint_tab_t l, plint_tab_t r)
00841 {
00842 if (l.n == r.n)
00843 {
00844 size_t i, n = l.n;
00845 for (i = 0; i < n && plint_val_equ(plint_var_val(l.a[i]), plint_var_val(r.a[i])); ++i);
00846 return i == n;
00847 }
00848 return 0;
00849 }
00850
00851 inline int plint_tab_neq(plint_tab_t l, plint_tab_t r)
00852 {
00853 return !plint_tab_equ(l, r);
00854 }
00855
00856
00857
00858
00859
00860
00861 #define PLINT_TAB_CMP(__fnc__, __lt__, __rt__) \
00862 int plint_tab_##__fnc__(plint_##__lt__##_t * __lt__, plint_##__rt__##_t * __rt__) \
00863 { \
00864 size_t i, n = tab->n; \
00865 for (i = 0; i < n && !plint_val_equ(plint_var_val(i[tab->a]), *ptr); ++i); \
00866 return i < n; \
00867 }
00868
00869
00870 PLINT_TAB_CMP(lt, ptr, tab)
00871 PLINT_TAB_CMP(gt, tab, ptr)
00872
00873 #undef PLINT_TAB_CMP
00874
00875
00876 #define PLINT_TAB_CMP(__fnc__, __lt__, __rt__) \
00877 int plint_tab_##__fnc__(plint_##__lt__##_t * __lt__, plint_##__rt__##_t * __rt__) \
00878 { \
00879 return plint_tab_##__fnc__(__lt__, __rt__) || \
00880 ( ((*ptr)->typ == PLINT_tab) ? plint_tab_equ(*tab, (*ptr)->val.tab) : 0); \
00881 }
00882
00883
00884 PLINT_TAB_CMP(lte, ptr, tab)
00885 PLINT_TAB_CMP(gte, tab, ptr)
00886
00887 #undef PLINT_TAB_CMP
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898 static plint_ptr_t tab_ptr;
00899 static plint_num_t tab_num;
00900
00901 #define PLINT_OP_ARITM(__fun__) \
00902 static void tab_num_##__fun__(plint_tab_t * t) \
00903 { \
00904 size_t i; \
00905 static plint_num_t m; \
00906 static plint_pnt_t p; \
00907 for (i = t->n; i; ) \
00908 switch ((tab_ptr = t->a[--i]->ptr)->typ) \
00909 { \
00910 case PLINT_tab: \
00911 tab_num_##__fun__(&tab_ptr->val.tab); \
00912 break; \
00913 case PLINT_num_int: case PLINT_num: case PLINT_num_dbl: \
00914 m = plint_ptr_num(tab_ptr); \
00915 plint_num_##__fun__(&m, tab_num); \
00916 plint_num_set(tab_ptr, m); \
00917 break; \
00918 case PLINT_pnt: \
00919 p = plint_ptr_pnt(tab_ptr); \
00920 plint_pnt_num_##__fun__(&p, tab_num); \
00921 plint_pnt_set(tab_ptr, p); \
00922 break; \
00923 default: \
00924 PLINT_ERROR(PLINT_ERR_VAR_TYP); \
00925 } \
00926 } \
00927 void plint_tab_num_##__fun__(plint_tab_t * t, plint_num_t n)\
00928 { \
00929 tab_num = n; \
00930 tab_num_##__fun__(t); \
00931 }
00932
00933 PLINT_OP_ARITM(add)
00934 PLINT_OP_ARITM(mul)
00935
00936 #define PLINT_OP_LOGIC(__fun__) \
00937 static void tab_num_##__fun__(plint_tab_t * t) \
00938 { \
00939 size_t i; \
00940 static plint_num_t m; \
00941 for (i = t->n; i; ) \
00942 switch ((tab_ptr = t->a[--i]->ptr)->typ) \
00943 { \
00944 case PLINT_tab: \
00945 tab_num_##__fun__(&tab_ptr->val.tab); \
00946 break; \
00947 case PLINT_num_int: case PLINT_num: case PLINT_num_dbl: \
00948 m = plint_ptr_num(tab_ptr); \
00949 plint_num_##__fun__(&m, tab_num); \
00950 plint_num_set(tab_ptr, m); \
00951 break; \
00952 default: \
00953 PLINT_ERROR(PLINT_ERR_VAR_TYP); \
00954 } \
00955 } \
00956 void plint_tab_num_##__fun__(plint_tab_t * t, plint_num_t n)\
00957 { \
00958 tab_num = n; \
00959 tab_num_##__fun__(t); \
00960 }
00961
00962 PLINT_OP_LOGIC(and)
00963 PLINT_OP_LOGIC(or )
00964 PLINT_OP_LOGIC(xor)
00965
00966 #undef PLINT_OP_ARITM
00967 #undef PLINT_OP_LOGIC
00968
00969 #define PLINT_OP_ARITM(__fun__) \
00970 static plint_num_t tab_num_l, tab_num_r, * tab_num_p; \
00971 static void tab_num_##__fun__(plint_tab_t * t) \
00972 { \
00973 size_t i; \
00974 for (i = t->n; i; ) \
00975 switch ((tab_ptr = t->a[--i]->ptr)->typ) \
00976 { \
00977 case PLINT_tab: \
00978 tab_num_##__fun__(&tab_ptr->val.tab); \
00979 break; \
00980 case PLINT_num_int: \
00981 case PLINT_num_dbl: \
00982 tab_num_l = tab_num_r = tab_num; \
00983 *tab_num_p = plint_ptr_num(tab_ptr); \
00984 plint_num_##__fun__(&tab_num_l, tab_num_r); \
00985 plint_num_set(tab_ptr, tab_num_l); \
00986 break; \
00987 default: \
00988 PLINT_ERROR(PLINT_ERR_VAR_TYP); \
00989 } \
00990 } \
00991 void plint_tab_num_##__fun__(plint_tab_t * t, plint_num_t n, int d)\
00992 { \
00993 tab_num = n; \
00994 tab_num_p = (d < 0) ? &tab_num_l : &tab_num_r; \
00995 tab_num_##__fun__(t); \
00996 }
00997
00998
00999 PLINT_OP_ARITM(sub)
01000 PLINT_OP_ARITM(div)
01001 PLINT_OP_ARITM(rem)
01002
01003 #undef PLINT_OP_ARITM
01004
01005
01006
01007
01008
01009
01010 static plint_pnt_t tab_pnt;
01011 static plint_str_t tab_str;
01012 #define PLINT_OP_ARITM(__typ__, __fun__) \
01013 static void tab_##__typ__##_##__fun__(plint_tab_t * t) \
01014 { \
01015 size_t i; \
01016 for (i = t->n; i; ) \
01017 switch ((tab_ptr = t->a[--i]->ptr)->typ) \
01018 { \
01019 case PLINT_tab: \
01020 tab_##__typ__##_##__fun__(&tab_ptr->val.tab); \
01021 break; \
01022 case PLINT_##__typ__: \
01023 plint_##__typ__##_##__fun__(&tab_ptr->val.__typ__, \
01024 tab_##__typ__); \
01025 break; \
01026 default: \
01027 PLINT_ERROR(PLINT_ERR_VAR_TYP); \
01028 } \
01029 } \
01030 void plint_tab_##__typ__##_##__fun__(plint_tab_t * t, plint_##__typ__##_t a) \
01031 { \
01032 tab_##__typ__ = a; \
01033 tab_##__typ__##_##__fun__(t); \
01034 }
01035
01036 PLINT_OP_ARITM(pnt, add)
01037 PLINT_OP_ARITM(pnt, mul)
01038
01039 #undef PLINT_OP_ARITM
01040
01041 #define PLINT_OP_ARITM(__typ__, __fun__) \
01042 static plint_##__typ__##_t \
01043 tab_##__typ__##_l, \
01044 tab_##__typ__##_r, \
01045 * tab_##__typ__##_p; \
01046 static void tab_##__typ__##_##__fun__(plint_tab_t * t) \
01047 { \
01048 size_t i; \
01049 for (i = t->n; i; ) \
01050 switch ((tab_ptr = t->a[--i]->ptr)->typ) \
01051 { \
01052 case PLINT_tab: \
01053 tab_##__typ__##_##__fun__(&tab_ptr->val.tab); \
01054 break; \
01055 case PLINT_##__typ__: \
01056 tab_##__typ__##_l = \
01057 tab_##__typ__##_r = plint_##__typ__##_cpy(tab_##__typ__); \
01058 *tab_##__typ__##_p = tab_ptr->val.__typ__; \
01059 plint_##__typ__##_##__fun__(&tab_##__typ__##_l, tab_##__typ__##_r); \
01060 tab_ptr->val.__typ__ = plint_##__typ__##_cpy(tab_##__typ__##_l); \
01061 plint_##__typ__##_fre(tab_##__typ__##_l); \
01062 plint_##__typ__##_fre(tab_##__typ__##_r); \
01063 break; \
01064 default: \
01065 PLINT_ERROR(PLINT_ERR_VAR_TYP); \
01066 } \
01067 } \
01068 void plint_tab_##__typ__##_##__fun__(plint_tab_t * t, plint_##__typ__##_t a, int d) \
01069 { \
01070 tab_##__typ__ = plint_##__typ__##_cpy(a); \
01071 tab_##__typ__##_p = (d < 0) \
01072 ? &tab_##__typ__##_l \
01073 : &tab_##__typ__##_r; \
01074 tab_##__typ__##_##__fun__(t); \
01075 plint_##__typ__##_fre(tab_##__typ__); \
01076 }
01077
01078
01079 PLINT_OP_ARITM(pnt, sub)
01080 PLINT_OP_ARITM(pnt, div)
01081
01082 PLINT_OP_ARITM(str, add)
01083 PLINT_OP_ARITM(str, sub)
01084 PLINT_OP_ARITM(str, rem)
01085
01086 #undef PLINT_OP_ARITM
01087
01088
01089
01090
01091
01092
01093 static plint_bol_t tab_bol;
01094
01095 #define PLINT_OP_LOGIC(__fun__, __op__) \
01096 static void tab_bol_##__fun__(plint_tab_t * t) \
01097 { \
01098 size_t i; \
01099 for (i = t->n; i; ) \
01100 switch ((tab_ptr = t->a[--i]->ptr)->typ) \
01101 { \
01102 case PLINT_tab: \
01103 tab_bol_##__fun__(&tab_ptr->val.tab); \
01104 break; \
01105 case PLINT_num_int: \
01106 tab_ptr->typ = PLINT_bol; \
01107 tab_ptr->val.bol = !!tab_ptr->val.num_int; \
01108 case PLINT_bol: \
01109 tab_ptr->val.bol __op__##= tab_bol; \
01110 break; \
01111 default: \
01112 PLINT_ERROR(PLINT_ERR_VAR_TYP); \
01113 } \
01114 } \
01115 void plint_tab_bol_##__fun__(plint_tab_t * t, plint_bol_t b) \
01116 { \
01117 tab_bol = b; \
01118 tab_bol_##__fun__(&tab_ptr->val.tab); \
01119 }
01120
01121
01122 PLINT_OP_LOGIC(and, &)
01123 PLINT_OP_LOGIC(or , |)
01124 PLINT_OP_LOGIC(xor, ^)
01125
01126 #undef PLINT_OP_LOGIC
01127
01136 inline void plint_hsh_add(plint_hsh_t * l, plint_hsh_t r)
01137 {
01138 plint_hsh_cat(*l, r);
01139 }
01140
01141 static int hsh_sub(hashindex_t hi, ns_key_t ns, plint_ref_t ref, plint_hsh_t hsh)
01142 {
01143 plint_str_t str;
01144 plint_hash_str(ns_hash(ns), hi, str);
01145 hi = plint_hsh_get(hsh, str, &ref);
01146 plint_str_fre(str);
01147
01148 if (!HASH_INDEX_ISBAD(hi))
01149 plint_var_fre((plint_var_t)hash_remstr(hsh, hi));
01150
01151 return !0;
01152 }
01153
01154 inline void plint_hsh_sub(plint_hsh_t * l, plint_hsh_t r)
01155 {
01156 hash_iterdata_all(r, (hash_iterfunc_t)hsh_sub, * l);
01157 }
01158
01159
01160 void plint_hsh_mul(plint_hsh_t * l, plint_hsh_t r)
01161 {
01162 plint_hsh_t l_r = plint_hsh_dup(*l), r_l = plint_hsh_dup(r);
01163
01164 plint_hsh_sub(&l_r, r);
01165 plint_hsh_sub(&r_l, *l);
01166
01167 plint_hsh_add(l, r);
01168 plint_hsh_add(&l_r, r_l);
01169 plint_hsh_sub(l, l_r);
01170
01171
01172 plint_hsh_fre(l_r);
01173 plint_hsh_fre(r_l);
01174 }
01175
01176
01177
01178
01179
01180 int plint_hsh_equ(plint_hsh_t l, plint_hsh_t r)
01181 {
01182 return plint_hsh_lt(l, r) && plint_hsh_lt(r, l);
01183 }
01184
01185 int plint_hsh_neq(plint_hsh_t l, plint_hsh_t r)
01186 {
01187 return !plint_hsh_lt(l, r) || !plint_hsh_lt(r, l);
01188 }
01189
01190
01191
01192
01193
01194
01195 typedef struct
01196 {
01197 plint_hsh_t in;
01198 int out;
01199 } hsh_lt_t;
01200
01201 static int hsh_lt(hashindex_t hi, ns_key_t ns, plint_ref_t ref, hsh_lt_t * p)
01202 {
01203 plint_ptr_t val = plint_var_val(plint_ref_var(ref));
01204 plint_str_t str;
01205 plint_hash_str(ns_hash(ns), hi, str);
01206 hi = plint_hsh_get(p->in, str, &ref);
01207 p->out = (HASH_INDEX_ISBAD(hi)) ? 0 : plint_val_equ(val, plint_var_val(plint_ref_var(ref)));
01208 plint_str_fre(str);
01209
01210 return p->out;
01211 }
01212
01213 inline int plint_hsh_lt(plint_hsh_t l, plint_hsh_t r)
01214 {
01215 hsh_lt_t x = { in: r, out: !0 };
01216 hash_iterdata_all(l, (hash_iterfunc_t)hsh_lt, &x);
01217 return x.out;
01218 }
01219 inline int plint_hsh_gt(plint_hsh_t l, plint_hsh_t r)
01220 {
01221 return plint_hsh_lt(r, l);
01222 }
01223 inline int plint_hsh_lte(plint_hsh_t l, plint_hsh_t r)
01224 {
01225 return plint_hsh_lt(l, r);
01226 }
01227 inline int plint_hsh_gte(plint_hsh_t l, plint_hsh_t r)
01228 {
01229 return plint_hsh_gt(r, l);
01230 }
01231
01240
01241
01242
01243
01244 int plint_val_equ(plint_ptr_t l, plint_ptr_t r)
01245 {
01246 if (l->typ == r->typ)
01247 switch (l->typ)
01248 {
01249 case PLINT_bol:return l->val.bol == r->val.bol;
01250 case PLINT_num_int:return l->val.num_int == r->val.num_int;
01251 case PLINT_num_dbl:return l->val.num_dbl == r->val.num_dbl;
01252 case PLINT_pnt:return plint_pnt_equ(l->val.pnt, r->val.pnt);
01253 case PLINT_tab:return plint_tab_equ(l->val.tab, r->val.tab);
01254 case PLINT_str:return plint_str_equ(l->val.str, r->val.str);
01255
01256 default:
01257 return !0;
01258 }
01259
01260 return 0;
01261 }
01262
01263 int plint_val_neq(plint_ptr_t l, plint_ptr_t r)
01264 {
01265 return (l != r);
01266 }
01267
01268 #define PLINT_VAL_CMP(__fnc__, __op__) \
01269 int plint_val_##__fnc__(plint_ptr_t l, plint_ptr_t r) \
01270 { \
01271 if (l->typ == r->typ) \
01272 switch (l->typ) \
01273 { \
01274 case PLINT_str:return 0; \
01275 case PLINT_bol:return l->val.bol __op__ r->val.bol; \
01276 case PLINT_num_int:return l->val.num_int __op__ r->val.num_int; \
01277 case PLINT_num_dbl:return l->val.num_dbl __op__ r->val.num_dbl; \
01278 case PLINT_pnt:return plint_pnt_##__fnc__(l->val.pnt, r->val.pnt); \
01279 case PLINT_tab:return (*#__op__ == '>') ? plint_tab_##__fnc__(&l->val.tab, &r): \
01280 plint_tab_##__fnc__(&l, &r->val.tab); \
01281 \
01282 default: \
01283 return 0; \
01284 \
01285 } \
01286 else if (l->typ == PLINT_tab) \
01287 return (*#__op__ == '>') ? plint_tab_##__fnc__(&l->val.tab, &r) : 0; \
01288 else if (r->typ == PLINT_tab) \
01289 return (*#__op__ == '<') ? plint_tab_##__fnc__(&l, &r->val.tab) : 0; \
01290 return 0; \
01291 }
01292
01293
01294 PLINT_VAL_CMP(lt , < )
01295 PLINT_VAL_CMP(gt , > )
01296 PLINT_VAL_CMP(lte , <=)
01297 PLINT_VAL_CMP(gte , >=)
01298
01299 #undef PLINT_VAL_CMP
01300
01305 #undef PLINT_SGN
01306 #undef PLINT_MIN
01307 #undef PLINT_MAX
01308