source: git/Singular/dyn_modules/interval/interval.cc @ 12c0b9

fieker-DuValspielwiese
Last change on this file since 12c0b9 was 12c0b9, checked in by Hans Schoenemann <hannes@…>, 7 years ago
fix: wrong assume: result type is not set at the start
  • Property mode set to 100644
File size: 29.4 KB
Line 
1#include "kernel/mod2.h"
2#include "Singular/blackbox.h"
3#include "Singular/dyn_modules/interval/interval.h"
4#include "Singular/ipshell.h" // for iiCheckTypes
5#include "Singular/links/ssiLink.h"
6#include "Singular/mod_lib.h"
7
8/*
9 * CONSTRUCTORS & DESTRUCTORS
10 */
11
12/* interval */
13
14interval::interval(ring r = currRing)
15{
16    lower = n_Init(0, r->cf);
17    upper = n_Init(0, r->cf);
18    R = r;
19    R->ref++;
20}
21
22interval::interval(number a, ring r = currRing)
23{
24    // dangerous: check if a is in coefs r->cf
25    lower = a;
26    upper = n_Copy(a, r->cf);
27    R = r;
28    R->ref++;
29}
30
31interval::interval(number a, number b, ring r = currRing)
32{
33    lower = a;
34    upper = b;
35    R = r;
36    R->ref++;
37}
38
39interval::interval(interval *I)
40{
41    lower = n_Copy(I->lower, I->R->cf);
42    upper = n_Copy(I->upper, I->R->cf);
43    R = I->R;
44    R->ref++;
45}
46
47interval::~interval()
48{
49    n_Delete(&lower, R->cf);
50    n_Delete(&upper, R->cf);
51    R->ref--;
52}
53
54interval& interval::setRing(ring r)
55{
56    if (R != r)
57    {
58        if (R->cf != r->cf)
59        {
60            nMapFunc fun = n_SetMap(R->cf, r->cf);
61            number lo = fun(lower, R->cf, r->cf),
62                up = fun(upper, R->cf, r->cf);
63            n_Delete(&lower, R->cf);
64            n_Delete(&upper, R->cf);
65            lower = lo;
66            upper = up;
67        }
68        R->ref--;
69        r->ref++;
70        R = r;
71    }
72
73    return *this;
74}
75
76/* box */
77
78box::box()
79{
80    R = currRing;
81    int i, n = R->N;
82    intervals = (interval**) omAlloc0(n * sizeof(interval*));
83    if (intervals != NULL)
84    {
85        for (i = 0; i < n; i++)
86        {
87            intervals[i] = new interval();
88        }
89    }
90    R->ref++;
91}
92
93box::box(box* B)
94{
95    R = B->R;
96    int i, n = R->N;
97    intervals = (interval**) omAlloc0(n * sizeof(interval*));
98    if (intervals != NULL)
99    {
100        for (i = 0; i < n; i++)
101        {
102            intervals[i] = new interval(B->intervals[i]);
103        }
104    }
105    R->ref++;
106}
107
108box::~box()
109{
110    int i, n = R->N;
111    for (i = 0; i < n; i++)
112    {
113        delete intervals[i];
114    }
115    omFree((void**) intervals);
116    R->ref--;
117}
118
119// does not copy
120box& box::setInterval(int i, interval *I)
121{
122    if (0 <= i && i < R->N)
123    {
124        delete intervals[i];
125        intervals[i] = I;
126    }
127    return *this;
128}
129
130/*
131 * TYPE IDs
132 */
133
134static int intervalID;
135static int boxID;
136
137/*
138 * INTERVAL FUNCTIONS
139 */
140
141static void* interval_Init(blackbox*)
142{
143    return (void*) new interval();
144}
145
146// convert interval to string
147static char* interval_String(blackbox*, void *d)
148{
149    if (d == NULL)
150    {
151        // invalid object
152        return omStrDup("[?]");
153    }
154    else
155    {
156        interval* i = (interval*) d;
157
158        // use n_Write since nothing better (?) exists
159        StringSetS("[");
160        n_Write(i->lower, i->R->cf);
161        StringAppendS(", ");
162        n_Write(i->upper, i->R->cf);
163        StringAppendS("]");
164
165        return StringEndS();
166    }
167}
168
169static void* interval_Copy(blackbox*, void *d)
170{
171    return (void*) new interval((interval*) d);
172}
173
174// destroy interval
175static void interval_Destroy(blackbox*, void *d)
176{
177    if (d != NULL)
178        delete (interval*) d;
179}
180
181// assigning values to intervals
182static BOOLEAN interval_Assign(leftv result, leftv args)
183{
184    interval *RES;
185
186    /*
187     * Allow assignments of the form
188     *  I = a,
189     *  I = a, b,
190     *  I = J
191     * where a, b numbers or ints and J interval
192     */
193
194    if (args->Typ() == intervalID)
195    {
196        RES = new interval((interval*) args->CopyD());
197    }
198    else
199    {
200        number n1, n2;
201
202        if (args->Typ() == INT_CMD)
203        {
204            n1 = nInit((int)(long) args->Data());
205        }
206        else if (args->Typ() == NUMBER_CMD)
207        {
208            n1 = (number) args->CopyD();
209        }
210        else
211        {
212            WerrorS("Input not supported: first argument not int or number");
213            return TRUE;
214        }
215
216        // check if second argument exists
217        if (args->Typ() == intervalID)
218        {
219            RES = new interval(n1, n2);
220        }
221        else if (args->next == NULL)
222        {
223            RES = new interval(n1);
224        }
225        else
226        {
227            if (args->next->Typ() == INT_CMD)
228            {
229                n2 = nInit((int)(long) args->next->Data());
230            }
231            else if (args->next->Typ() == NUMBER_CMD)
232            {
233                n2 = (number) args->next->CopyD();
234            }
235            else
236            {
237                WerrorS("Input not supported: second argument not int or number");
238                return TRUE;
239            }
240
241            RES = new interval(n1, n2);
242        }
243    }
244
245    // destroy data of result if it exists
246    if (result->Data() != NULL)
247    {
248        delete (interval*) result->Data();
249    }
250
251    if (result->rtyp == IDHDL)
252    {
253        IDDATA((idhdl)result->data) = (char*) RES;
254    }
255    else
256    {
257        result->rtyp = intervalID;
258        result->data = (void*) RES;
259    }
260
261    args->CleanUp();
262    return FALSE;
263}
264
265static BOOLEAN length(leftv result, leftv arg)
266{
267    if (arg != NULL && arg->Typ() == intervalID)
268    {
269        interval *I = (interval*) arg->Data();
270        result->rtyp = NUMBER_CMD;
271        result->data = (void*) n_Sub(I->upper, I->lower, I->R->cf);
272        arg->CleanUp();
273        return FALSE;
274    }
275
276    WerrorS("syntax: length(<interval>)");
277    return TRUE;
278}
279
280// interval -> interval procedures
281
282static interval* intervalScalarMultiply(number a, interval *I)
283{
284    // must assume a is in ring I->R
285    number lo, up;
286    if (nGreaterZero(a))
287    {
288        lo = n_Mult(a, I->lower, I->R->cf);
289        up = n_Mult(a, I->upper, I->R->cf);
290    }
291    else
292    {
293        lo = n_Mult(a, I->upper, I->R->cf);
294        up = n_Mult(a, I->lower, I->R->cf);
295    }
296
297    n_Normalize(lo, I->R->cf);
298    n_Normalize(up, I->R->cf);
299
300    return new interval(lo, up, I->R);
301}
302
303static interval* intervalMultiply(interval *I, interval *J)
304{
305    number lo, up;
306    number nums[4];
307    nums[0] = n_Mult(I->lower, J->lower, I->R->cf);
308    nums[1] = n_Mult(I->lower, J->upper, I->R->cf);
309    nums[2] = n_Mult(I->upper, J->lower, I->R->cf);
310    nums[3] = n_Mult(I->upper, J->upper, I->R->cf);
311
312    int i, imax = 0, imin = 0;
313    for (i = 1; i < 4; i++)
314    {
315        if (n_Greater(nums[i], nums[imax], I->R->cf))
316        {
317            imax = i;
318        }
319        if (n_Greater(nums[imin], nums[i], I->R->cf))
320        {
321            imin = i;
322        }
323    }
324
325    lo = n_Copy(nums[imin], I->R->cf);
326    up = n_Copy(nums[imax], I->R->cf);
327
328    // delete products
329    for (i = 0; i < 4; i++)
330    {
331        n_Delete(&nums[i], I->R->cf);
332    }
333
334    n_Normalize(lo, I->R->cf);
335    n_Normalize(up, I->R->cf);
336
337    return new interval(lo, up, I->R);
338}
339
340static interval* intervalAdd(interval *I, interval *J)
341{
342    number lo = n_Add(I->lower, J->lower, I->R->cf),
343           up = n_Add(I->upper, J->upper, I->R->cf);
344
345    n_Normalize(lo, I->R->cf);
346    n_Normalize(up, I->R->cf);
347
348    return new interval(lo, up);
349}
350
351static interval* intervalSubtract(interval *I, interval *J)
352{
353    number lo = n_Sub(I->lower, J->upper, I->R->cf),
354           up = n_Sub(I->upper, J->lower, I->R->cf);
355
356    n_Normalize(lo, I->R->cf);
357    n_Normalize(up, I->R->cf);
358
359    return new interval(lo, up, I->R);
360}
361
362static bool intervalEqual(interval *I, interval *J)
363{
364    assume(I->R == J->R);
365    return n_Equal(I->lower, J->lower, I->R->cf)
366        && n_Equal(I->upper, J->upper, I->R->cf);
367}
368
369// ckeck if zero is contained in an interval
370static bool intervalContainsZero(interval *I)
371{
372    number n = n_Mult(I->lower, I->upper, I->R->cf);
373    bool result = !n_GreaterZero(n, I->R->cf);
374    // delete helper number
375    n_Delete(&n, I->R->cf);
376
377    return result;
378}
379
380static interval* intervalPower(interval *I, int p)
381{
382    if (p == 0)
383    {
384        return new interval(n_Init(1,I->R->cf), I->R);
385    }
386
387    // no initialisation required (?)
388    number lo, up;
389
390    n_Power(I->lower, p, &lo, I->R->cf);
391    n_Power(I->upper, p, &up, I->R->cf);
392
393    // should work now
394    if (p % 2 == 1)
395    {
396        return new interval(lo, up, I->R);
397    }
398    else
399    {
400        // perform pointer swap if necessary
401        number tmp;
402        if (n_Greater(lo, up, I->R->cf))
403        {
404            tmp = up;
405            up = lo;
406            lo = tmp;
407        }
408
409        if (intervalContainsZero(I))
410        {
411            n_Delete(&lo, I->R->cf);
412            lo = n_Init(0, I->R->cf);
413        }
414        return new interval(lo, up, I->R);
415    }
416}
417
418/*
419 * BINARY OPERATIONS:
420 * Cases handled:
421 *      I + J,
422 *
423 *      I - J,
424 *
425 *      a * J,
426 *      I * a,
427 *      I * J,
428 *
429 *      a / J,
430 *      I / a,
431 *      I / J
432 *
433 *      I ^ n,
434 *
435 *      I == J
436 *
437 *  where I, J, interval, a, b int or number, n int
438 */
439
440static BOOLEAN interval_Op2(int op, leftv result, leftv i1, leftv i2)
441{
442    interval *RES;
443
444    switch(op)
445    {
446        case '+':
447        {
448            if (i1->Typ() != intervalID || i2->Typ() != intervalID)
449            {
450                WerrorS("syntax: <interval> + <interval>");
451                return TRUE;
452            }
453            interval *I1, *I2;
454            I1 = (interval*) i1->Data();
455            I2 = (interval*) i2->Data();
456            if (I1->R != I2->R)
457            {
458                WerrorS("adding intervals defined in different rings not supported");
459                return TRUE;
460            }
461
462            RES = intervalAdd(I1, I2);
463            break;
464        }
465        case '-':
466        {
467            if (i1->Typ() != intervalID || i2->Typ() != intervalID)
468            {
469                WerrorS("syntax: <interval> - <interval>");
470                return TRUE;
471            }
472            interval *I1, *I2;
473            I1 = (interval*) i1->Data();
474            I2 = (interval*) i2->Data();
475            if (I1->R != I2->R)
476            {
477                WerrorS("subtracting intervals defined in different rings not supported");
478                return TRUE;
479            }
480
481            RES = intervalSubtract(I1, I2);
482            break;
483        }
484        case '*':
485        {
486            if (i1->Typ() == i2->Typ())
487            {
488                // both must be intervals
489                interval *I1, *I2;
490                I1 = (interval*) i1->Data();
491                I2 = (interval*) i2->Data();
492                if (I1->R != I2->R)
493                {
494                    WerrorS("multiplying intervals defined in different rings not supported");
495                    return TRUE;
496                }
497
498                RES = intervalMultiply(I1, I2);
499            }
500            else
501            {
502                // one arg is scalar, one is interval
503                // give new names to reduce to one case
504                leftv iscalar, iinterv;
505                if (i1->Typ() != intervalID)
506                {
507                    // i1 is scalar
508                    iscalar = i1;
509                    iinterv = i2;
510                }
511                else
512                {
513                    // i2 is scalar
514                    iscalar = i2;
515                    iinterv = i1;
516                }
517                number n;
518
519                switch (iscalar->Typ())
520                {
521                    case INT_CMD:
522                        { n = nInit((int)(long) iscalar->Data()); break; }
523                    case NUMBER_CMD:
524                        { n = (number) iscalar->CopyD(); break; }
525                    default:
526                        { WerrorS("first argument not int/number/interval"); return TRUE; }
527                }
528
529                interval *I = (interval*) iinterv->Data();
530
531                RES = intervalScalarMultiply(n, I);
532                // n no longer needed, delete it
533                nDelete(&n);
534            }
535
536            break;
537        }
538        case '/':
539        {
540            if(i2->Typ() == intervalID)
541            {
542                interval *I2;
543                I2 = (interval*) i2->Data();
544
545                // make sure I2 is invertible
546                if (intervalContainsZero(I2))
547                {
548                    WerrorS("second interval contains zero");
549                    return TRUE;
550                }
551
552                number invlo, invup;
553                invlo = n_Invers(I2->lower, I2->R->cf);
554                invup = n_Invers(I2->upper, I2->R->cf);
555
556                // inverse interval
557                interval *I2inv = new interval(invup, invlo, I2->R);
558
559                if (i1->Typ() == intervalID)
560                {
561                    interval *I1 = (interval*) i1->Data();
562                    if (I1->R != I2->R)
563                    {
564                        WerrorS("dividing intervals from different rings not supported");
565                        delete I2inv;
566                        return TRUE;
567                    }
568                    RES = intervalMultiply(I1, I2inv);
569                }
570                else
571                {
572                    // i1 is not an interval
573                    number n;
574                    switch (i1->Typ())
575                    {
576                        case INT_CMD:
577                        {
578                            n = nInit((int)(long) i1->Data());
579                            break;
580                        }
581                        case NUMBER_CMD:
582                        {
583                            n = nCopy((number) i1->Data());
584                            break;
585                        }
586                        default:
587                        {
588                            WerrorS("first argument not int/number/interval");
589                            delete I2inv;
590                            return TRUE;
591                        }
592                    }
593                    RES = intervalScalarMultiply(n, I2inv);
594                    nDelete(&n);
595                }
596
597                delete I2inv;
598                break;
599            }
600            else
601            {
602                // i2 is not an interval
603                interval *I1 = (interval*) i1->Data();
604                number n;
605                switch(i2->Typ())
606                {
607                    case INT_CMD:
608                        { n = nInit((int)(long) i2->Data()); break; }
609                    case NUMBER_CMD:
610                        { n = nCopy((number) i2->Data()); break; }
611                    default:
612                    {
613                        WerrorS("second argument not int/number/interval");
614                        return TRUE;
615                    }
616                }
617                // handle zero to prevent memory leak (?)
618                if (nIsZero(n))
619                {
620                    WerrorS("<interval>/0 not supported");
621                    return TRUE;
622                }
623
624                number nInv = nInvers(n);
625                nDelete(&n);
626                RES = intervalScalarMultiply(nInv, I1);
627                nDelete(&nInv);
628
629                break;
630            }
631
632            break;
633        }
634        case '^':
635        {
636            if (i1->Typ() != intervalID || i2->Typ() != INT_CMD)
637            {
638                WerrorS("syntax: <interval> ^ <int>");
639                return TRUE;
640            }
641            int p = (int)(long) i2->Data();
642            if (p < 0)
643            {
644                WerrorS("<interval> ^ n not implemented for n < 0");
645                return TRUE;
646            }
647            interval *I = (interval*) i1->Data();
648
649            RES = intervalPower(I, p);
650            break;
651        }
652        case EQUAL_EQUAL:
653        {
654            if (i1->Typ() != intervalID || i2->Typ() != intervalID)
655            {
656                WerrorS("syntax: <interval> == <interval>");
657                return TRUE;
658            }
659            interval *I1, *I2;
660            I1 = (interval*) i1->Data();
661            I2 = (interval*) i2->Data();
662
663            result->rtyp = INT_CMD;
664            result->data = (void*) intervalEqual(I1, I2);
665            i1->CleanUp();
666            i2->CleanUp();
667            return FALSE;
668        }
669        case '[':
670        {
671            if (i1->Typ() != intervalID || i2->Typ() != INT_CMD)
672            {
673                WerrorS("syntax: <interval>[<int>]");
674                return TRUE;
675            }
676
677            interval *I = (interval*) i1->Data();
678            int n = (int)(long) i2->Data();
679
680            number out;
681            if (n == 1)
682            {
683                out = nCopy(I->lower);
684            }
685            else if (n == 2)
686            {
687                out = nCopy(I->upper);
688            }
689            else
690            {
691                WerrorS("Allowed indices are 1 and 2");
692                return TRUE;
693            }
694
695            // delete number in result
696            if (result != NULL && result->Data() != NULL)
697            {
698                number r = (number) result->Data();
699                nDelete(&r);
700            }
701
702            result->rtyp = NUMBER_CMD;
703            result->data = (void*) out;
704            i1->CleanUp();
705            i2->CleanUp();
706            return FALSE;
707        }
708        default:
709        {
710            // use default error
711            return blackboxDefaultOp2(op, result, i1, i2);
712        }
713    }
714
715    // destroy data of result if it exists
716    if (result->Data() != NULL)
717    {
718        delete (interval*) result->Data();
719    }
720
721    result->rtyp = intervalID;
722    result->data = (void*) RES;
723    i1->CleanUp();
724    i2->CleanUp();
725    return FALSE;
726}
727
728static BOOLEAN interval_serialize(blackbox*, void *d, si_link f)
729{
730    /*
731     * Format: "interval" setring number number
732     */
733    interval *I = (interval*) d;
734
735    sleftv l, lo, up;
736    memset(&l, 0, sizeof(l));
737    memset(&lo, 0, sizeof(lo));
738    memset(&up, 0, sizeof(up));
739
740    l.rtyp = STRING_CMD;
741    l.data = (void*) "interval";
742
743    lo.rtyp = NUMBER_CMD;
744    lo.data = (void*) I->lower;
745
746    up.rtyp = NUMBER_CMD;
747    up.data = (void*) I->upper;
748
749    f->m->Write(f, &l);
750
751    ring R = I->R;
752
753    f->m->SetRing(f, R, TRUE);
754    f->m->Write(f, &lo);
755    f->m->Write(f, &up);
756
757    // no idea
758    if (R != currRing)
759        f->m->SetRing(f, currRing, FALSE);
760
761    return FALSE;
762}
763
764static BOOLEAN interval_deserialize(blackbox**, void **d, si_link f)
765{
766    leftv l;
767
768    l = f->m->Read(f);
769    l->next = f->m->Read(f);
770
771    number lo = (number) l->CopyD(),
772           up = (number) l->next->CopyD();
773
774    l->CleanUp();
775
776    *d = (void*) new interval(lo, up);
777    return FALSE;
778}
779
780/*
781 * BOX FUNCTIONS
782 */
783
784static void* box_Init(blackbox*)
785{
786    return (void*) new box();
787}
788
789static void* box_Copy(blackbox*, void *d)
790{
791    return (void*) new box((box*) d);
792}
793
794static void box_Destroy(blackbox*, void *d)
795{
796    if (d != NULL)
797        delete (box*) d;
798}
799
800static char* box_String(blackbox*, void *d)
801{
802    blackbox *b_i = getBlackboxStuff(intervalID);
803    box *B = (box*) d;
804    int i, n = B->R->N;
805
806    if (B == NULL || B->intervals == NULL)
807    {
808        return omStrDup("ooo");
809    }
810
811    StringSetS(interval_String(b_i, (void*) B->intervals[0]));
812
813    for (i = 1; i < n; i++)
814    {
815        // interpret box as Cartesian product, hence use " x "
816        StringAppendS(" x ");
817        StringAppendS(interval_String(b_i, (void*) B->intervals[i]));
818    }
819    return StringEndS();
820}
821
822// assigning values to intervals
823static BOOLEAN box_Assign(leftv result, leftv args)
824{
825    box *RES;
826
827    /*
828     * Allow assignments of the form
829     *
830     *      B = C,
831     *      B = l,
832     *
833     * where B, C boxes, l list of intervals
834     */
835
836    if (args->Typ() == boxID)
837    {
838        box *B = (box*) args->Data();
839        RES = new box(B);
840    }
841    else if (args->Typ() == LIST_CMD)
842    {
843        RES = new box();
844        lists l = (lists) args->Data();
845
846        int i, m = lSize(l), n = currRing->N;
847        // minimum
848        int M = m > n ? n : m;
849
850        for (i = 0; i <= M; i++)
851        {
852            if (l->m[i].Typ() != intervalID)
853            {
854                WerrorS("list contains non-intervals");
855                delete RES;
856                args->CleanUp();
857                return TRUE;
858            }
859            RES->setInterval(i, (interval*) l->m[i].CopyD());
860
861            // make sure rings of boxes and their intervals are consistent
862            // this is important for serialization
863            RES->intervals[i]->setRing(RES->R);
864        }
865    }
866    else
867    {
868        WerrorS("Input not supported: first argument not box, list, or interval");
869        return TRUE;
870    }
871
872    // destroy data of result if it exists
873    if (result != NULL && result->Data() != NULL)
874    {
875        delete (box*) result->Data();
876    }
877
878    if (result->rtyp == IDHDL)
879    {
880        IDDATA((idhdl)result->data) = (char*) RES;
881    }
882    else
883    {
884        result->rtyp = boxID;
885        result->data = (void*) RES;
886    }
887    args->CleanUp();
888
889    return FALSE;
890}
891
892static BOOLEAN box_Op2(int op, leftv result, leftv b1, leftv b2)
893{
894    if (b1 == NULL || b1->Typ() != boxID)
895    {
896        Werror("first argument is not box but type(%d), second is type(%d)",
897            b1->Typ(), b2->Typ());
898        return TRUE;
899    }
900
901    box *B1 = (box*) b1->Data();
902    int n = B1->R->N;
903
904    box *RES;
905    switch(op)
906    {
907        case '[':
908        {
909            if (b2 == NULL || b2->Typ() != INT_CMD)
910            {
911                WerrorS("second argument not int");
912                return TRUE;
913            }
914            if (result->Data() != NULL)
915            {
916                delete (interval*) result->Data();
917            }
918
919            int i = (int)(long) b2->Data();
920
921            if (i < 1 || i > n)
922            {
923                WerrorS("index out of bounds");
924                return TRUE;
925            }
926
927            // delete data of result
928            if (result->Data() != NULL)
929            {
930                delete (interval*) result->Data();
931            }
932
933            result->rtyp = intervalID;
934            result->data = (void*) new interval(B1->intervals[i-1]);
935            b1->CleanUp();
936            b2->CleanUp();
937            return FALSE;
938        }
939        case '-':
940        {
941            if (b2 == NULL || b2->Typ() != boxID)
942            {
943                WerrorS("second argument not box");
944                return TRUE;
945            }
946
947            box *B2 = (box*) b2->Data();
948            // maybe try to skip this initialisation
949            // copying def of box() results in segfault?
950            if (B1->R != B2->R)
951            {
952                WerrorS("subtracting boxes from different rings not supported");
953                return TRUE;
954            }
955            RES = new box();
956            int i;
957            for (i = 0; i < n; i++)
958            {
959                RES->setInterval(i, intervalSubtract(B1->intervals[i], B2->intervals[i]));
960            }
961
962            if (result->Data() != NULL)
963            {
964                delete (box*) result->Data();
965            }
966
967            result->rtyp = boxID;
968            result->data = (void*) RES;
969            b1->CleanUp();
970            b2->CleanUp();
971            return FALSE;
972        }
973        case EQUAL_EQUAL:
974        {
975            if (b2 == NULL || b2->Typ() != boxID)
976            {
977                WerrorS("second argument not box");
978            }
979            box *B2 = (box*) b2->Data();
980            int i;
981            bool res = true;
982            for (i = 0; i < n; i++)
983            {
984                if (!intervalEqual(B1->intervals[i], B2->intervals[i]))
985                {
986                    res = false;
987                    break;
988                }
989            }
990
991            result->rtyp = INT_CMD;
992            result->data = (void*) res;
993            b1->CleanUp();
994            b2->CleanUp();
995            return FALSE;
996        }
997        default:
998            return blackboxDefaultOp2(op, result, b1, b2);
999    }
1000}
1001
1002static BOOLEAN box_OpM(int op, leftv result, leftv args)
1003{
1004    leftv a = args;
1005    switch(op)
1006    {
1007        case INTERSECT_CMD:
1008        {
1009            if (args->Typ() != boxID)
1010            {
1011                WerrorS("can only intersect boxes");
1012                return TRUE;
1013            }
1014            box *B = (box*) args->Data();
1015            int i, n = B->R->N;
1016            number lowerb[n], upperb[n];
1017
1018            // do not copy, use same pointers, copy at the end
1019            for (i = 0; i < n; i++)
1020            {
1021                lowerb[i] = B->intervals[i]->lower;
1022                upperb[i] = B->intervals[i]->upper;
1023            }
1024
1025            args = args->next;
1026            while(args != NULL)
1027            {
1028                if (args->Typ() != boxID)
1029                {
1030                    WerrorS("can only intersect boxes");
1031                    return TRUE;
1032                }
1033
1034                B = (box*) args->Data();
1035                for (i = 0; i < n; i++)
1036                {
1037                    if (nGreater(B->intervals[i]->lower, lowerb[i]))
1038                    {
1039                        lowerb[i] = B->intervals[i]->lower;
1040                    }
1041                    if (nGreater(upperb[i], B->intervals[i]->upper))
1042                    {
1043                        upperb[i] = B->intervals[i]->upper;
1044                    }
1045
1046                    if (nGreater(lowerb[i], upperb[i]))
1047                    {
1048                        result->rtyp = INT_CMD;
1049                        result->data = (void*) (-1);
1050                        a->CleanUp();
1051                        return FALSE;
1052                    }
1053                }
1054                args = args->next;
1055            }
1056
1057            // now copy the numbers
1058            box *RES = new box();
1059            for (i = 0; i < n; i++)
1060            {
1061                RES->setInterval(i, new interval(nCopy(lowerb[i]), nCopy(upperb[i])));
1062            }
1063
1064            result->rtyp = boxID;
1065            result->data = (void*) RES;
1066            a->CleanUp();
1067            return FALSE;
1068        }
1069        default:
1070            return blackboxDefaultOpM(op, result, args);
1071    }
1072}
1073
1074static BOOLEAN box_serialize(blackbox*, void *d, si_link f)
1075{
1076    /*
1077     * Format: "box" setring intervals[1] .. intervals[N]
1078     */
1079    box *B = (box*) d;
1080    int N = B->R->N, i;
1081    sleftv l, iv;
1082    memset(&l, 0, sizeof(l));
1083    memset(&iv, 0, sizeof(iv));
1084
1085    l.rtyp = STRING_CMD;
1086    l.data = (void*) "box";
1087
1088    f->m->Write(f, &l);
1089
1090    f->m->SetRing(f, B->R, TRUE);
1091
1092    iv.rtyp = intervalID;
1093    for (i = 0; i < N; i++)
1094    {
1095        iv.data = (void*) B->intervals[i];
1096        f->m->Write(f, &iv);
1097    }
1098
1099    if (currRing != B->R)
1100        f->m->SetRing(f, currRing, FALSE);
1101
1102    return FALSE;
1103}
1104
1105static BOOLEAN box_deserialize(blackbox**, void **d, si_link f)
1106{
1107    leftv l;
1108
1109    // read once to set ring
1110    l = f->m->Read(f);
1111
1112    ring R = currRing;
1113    int i, N = R->N;
1114    box *B = new box();
1115
1116    B->setInterval(0, (interval*) l->CopyD());
1117    l->CleanUp();
1118
1119    for (i = 1; i < N; i++)
1120    {
1121        l = f->m->Read(f);
1122        B->setInterval(0, (interval*) l->CopyD());
1123        l->CleanUp();
1124    }
1125
1126    *d = (void*) B;
1127    return FALSE;
1128}
1129
1130static BOOLEAN boxSet(leftv result, leftv args)
1131{
1132    // check for proper types
1133    const short t[] = {3, (short) boxID, INT_CMD, (short) intervalID};
1134    if (!iiCheckTypes(args, t, 1))
1135    {
1136        return TRUE;
1137    }
1138    box *B = (box*) args->Data();
1139    int n = B->R->N,
1140        i = (int)(long) args->next->Data();
1141    interval *I = (interval*) args->next->next->Data();
1142
1143    if (i < 1 || i > n)
1144    {
1145        WerrorS("index out of range");
1146        return TRUE;
1147    }
1148
1149    box *RES = new box(B);
1150
1151    RES->setInterval(i-1, new interval(I));
1152    // ensure consistency
1153    RES->intervals[i-1]->setRing(RES->R);
1154
1155    result->rtyp = boxID;
1156    result->data = (void*) RES;
1157    args->CleanUp();
1158    return FALSE;
1159}
1160
1161/*
1162 * POLY FUNCTIONS
1163 */
1164
1165static BOOLEAN evalPolyAtBox(leftv result, leftv args)
1166{
1167    const short t[] = {2, POLY_CMD, (short) boxID};
1168    if (!iiCheckTypes(args, t, 1))
1169    {
1170        return TRUE;
1171    }
1172
1173    poly p = (poly) args->Data();
1174    box *B = (box*) args->next->Data();
1175    int i, pot, n = B->R->N;
1176
1177    interval *tmp, *tmpPot, *tmpMonom, *RES = new interval();
1178
1179    while(p != NULL)
1180    {
1181        tmpMonom = new interval(nInit(1));
1182
1183        for (i = 1; i <= n; i++)
1184        {
1185            pot = pGetExp(p, i);
1186
1187            tmpPot = intervalPower(B->intervals[i-1], pot);
1188            tmp = intervalMultiply(tmpMonom, tmpPot);
1189
1190            delete tmpMonom;
1191            delete tmpPot;
1192
1193            tmpMonom = tmp;
1194        }
1195
1196        tmp = intervalScalarMultiply(p->coef, tmpMonom);
1197        delete tmpMonom;
1198        tmpMonom = tmp;
1199
1200        tmp = intervalAdd(RES, tmpMonom);
1201        delete RES;
1202        delete tmpMonom;
1203
1204        RES = tmp;
1205
1206        p = p->next;
1207    }
1208
1209    if (result->Data() != NULL)
1210    {
1211        delete (box*) result->Data();
1212    }
1213
1214    result->rtyp = intervalID;
1215    result->data = (void*) RES;
1216    args->CleanUp();
1217    return FALSE;
1218}
1219
1220/*
1221 * INIT MODULE
1222 */
1223
1224extern "C" int SI_MOD_INIT(interval)(SModulFunctions* psModulFunctions)
1225{
1226    blackbox *b_iv = (blackbox*) omAlloc0(sizeof(blackbox)),
1227             *b_bx = (blackbox*) omAlloc0(sizeof(blackbox));
1228
1229    b_iv->blackbox_Init        = interval_Init;
1230    b_iv->blackbox_Copy        = interval_Copy;
1231    b_iv->blackbox_destroy     = interval_Destroy;
1232    b_iv->blackbox_String      = interval_String;
1233    b_iv->blackbox_Assign      = interval_Assign;
1234    b_iv->blackbox_Op2         = interval_Op2;
1235    b_iv->blackbox_serialize   = interval_serialize;
1236    b_iv->blackbox_deserialize = interval_deserialize;
1237
1238    intervalID = setBlackboxStuff(b_iv, "interval");
1239
1240    b_bx->blackbox_Init        = box_Init;
1241    b_bx->blackbox_Copy        = box_Copy;
1242    b_bx->blackbox_destroy     = box_Destroy;
1243    b_bx->blackbox_String      = box_String;
1244    b_bx->blackbox_Assign      = box_Assign;
1245    b_bx->blackbox_Op2         = box_Op2;
1246    b_bx->blackbox_OpM         = box_OpM;
1247    b_bx->blackbox_serialize   = box_serialize;
1248    b_bx->blackbox_deserialize = box_deserialize;
1249
1250    boxID = setBlackboxStuff(b_bx, "box");
1251
1252    // add additional functions
1253    psModulFunctions->iiAddCproc("interval.so", "length", FALSE, length);
1254    psModulFunctions->iiAddCproc("interval.so", "boxSet", FALSE, boxSet);
1255    psModulFunctions->iiAddCproc("interval.so", "evalPolyAtBox", FALSE,
1256        evalPolyAtBox);
1257
1258    // TODO add help strings
1259
1260    return MAX_TOK;
1261}
1262
1263// vim: spell spelllang=en
Note: See TracBrowser for help on using the repository browser.