/* * $OpenXM: OpenXM_contrib2/asir2018/builtin/itvnum.c,v 1.1 2018/09/19 05:45:06 noro Exp $ */ #include "ca.h" #include "parse.h" #include "version.h" #if !defined(ANDROID) #include "../plot/ifplot.h" #endif #if defined(INTERVAL) static void Pitv(NODE, Obj *); static void Pitvd(NODE, Obj *); static void Pitvbf(NODE, Obj *); static void Pinf(NODE, Obj *); static void Psup(NODE, Obj *); static void Pmid(NODE, Obj *); static void Pabsitv(NODE, Obj *); static void Pdisjitv(NODE, Obj *); static void Pinitv(NODE, Obj *); static void Pcup(NODE, Obj *); static void Pcap(NODE, Obj *); static void Pwidth(NODE, Obj *); static void Pdistance(NODE, Obj *); static void Pitvversion(Q *); void miditvp(Itv,Num *); void absitvp(Itv,Num *); int initvd(Num,IntervalDouble); int initvp(Num,Itv); int itvinitvp(Itv,Itv); #endif static void Pprintmode(NODE, Obj *); /* plot time check func */ static void ccalc(double **, struct canvas *, int); static void Pifcheck(NODE, Obj *); #if defined(__osf__) && 0 int end; #endif struct ftab interval_tab[] = { {"printmode",Pprintmode,1}, #if defined(INTERVAL) {"itvd",Pitvd,-2}, {"intvald",Pitvd,-2}, {"itv",Pitv,-2}, {"intval",Pitv,-2}, {"itvbf",Pitvbf,-2}, {"intvalbf",Pitvbf,-2}, {"inf",Pinf,1}, {"sup",Psup,1}, {"absintval",Pabsitv,1}, {"disintval",Pdisjitv,2}, {"inintval",Pinitv,2}, {"cup",Pcup,2}, {"cap",Pcap,2}, {"mid",Pmid,1}, {"width",Pwidth,1}, {"diam",Pwidth,1}, {"distance",Pdistance,2}, {"iversion",Pitvversion,0}, /* plot time check */ {"ifcheck",Pifcheck,-7}, #endif {0,0,0}, }; #if defined(INTERVAL) /* plot time check */ static void Pifcheck(NODE arg, Obj *rp) { Q m2,p2,s_id; NODE defrange; LIST xrange,yrange,range[2],list,geom; VL vl,vl0; V v[2],av[2]; int ri,i,j,sign; P poly; P var; NODE n,n0; Obj t; struct canvas *can; MAT m; pointer **mb; double **tabe, *px, *px1, *px2; Q one; int width, height, ix, iy; int id; STOQ(-2,m2); STOQ(2,p2); STOQ(1,one); MKNODE(n,p2,0); MKNODE(defrange,m2,n); poly = 0; vl = 0; geom = 0; ri = 0; v[0] = v[1] = 0; for ( ; arg; arg = NEXT(arg) ){ switch ( OID(BDY(arg)) ) { case O_P: poly = (P)BDY(arg); get_vars_recursive((Obj)poly,&vl); for(vl0=vl,i=0;vl0;vl0=NEXT(vl0)){ if(vl0->v->attr==(pointer)V_IND){ if(i>=2){ error("ifplot : invalid argument"); } else { v[i++]=vl0->v; } } } break; case O_LIST: list = (LIST)BDY(arg); if ( OID(BDY(BDY(list))) == O_P ) if ( ri > 1 ) error("ifplot : invalid argument"); else range[ri++] = list; else geom = list; break; default: error("ifplot : invalid argument"); break; } } if ( !poly ) error("ifplot : invalid argument"); switch ( ri ) { case 0: if ( !v[1] ) error("ifplot : please specify all variables"); MKV(v[0],var); MKNODE(n,var,defrange); MKLIST(xrange,n); MKV(v[1],var); MKNODE(n,var,defrange); MKLIST(yrange,n); break; case 1: if ( !v[1] ) error("ifplot : please specify all variables"); av[0] = VR((P)BDY(BDY(range[0]))); if ( v[0] == av[0] ) { xrange = range[0]; MKV(v[1],var); MKNODE(n,var,defrange); MKLIST(yrange,n); } else if ( v[1] == av[0] ) { MKV(v[0],var); MKNODE(n,var,defrange); MKLIST(xrange,n); yrange = range[0]; } else error("ifplot : invalid argument"); break; case 2: av[0] = VR((P)BDY(BDY(range[0]))); av[1] = VR((P)BDY(BDY(range[1]))); if ( ((v[0] == av[0]) && (!v[1] || v[1] == av[1])) || ((v[0] == av[1]) && (!v[1] || v[1] == av[0])) ) { xrange = range[0]; yrange = range[1]; } else error("ifplot : invalid argument"); break; default: error("ifplot : cannot happen"); break; } can = canvas[id = search_canvas()]; if ( !geom ) { width = 300; height = 300; can->width = 300; can->height = 300; } else { can->width = QTOS((Q)BDY(BDY(geom))); can->height = QTOS((Q)BDY(NEXT(BDY(geom)))); width = can->width; height = can->height; } if ( xrange ) { n = BDY(xrange); can->vx = VR((P)BDY(n)); n = NEXT(n); can->qxmin = (Q)BDY(n); n = NEXT(n); can->qxmax = (Q)BDY(n); can->xmin = ToReal(can->qxmin); can->xmax = ToReal(can->qxmax); } if ( yrange ) { n = BDY(yrange); can->vy = VR((P)BDY(n)); n = NEXT(n); can->qymin = (Q)BDY(n); n = NEXT(n); can->qymax = (Q)BDY(n); can->ymin = ToReal(can->qymin); can->ymax = ToReal(can->qymax); } can->wname = "ifcheck"; can->formula = poly; tabe = (double **)ALLOCA((width+1)*sizeof(double *)); for ( i = 0; i <= width; i++ ) tabe[i] = (double *)ALLOCA((height+1)*sizeof(double)); for(i=0;i<=width;i++)for(j=0;j<=height;j++)tabe[i][j]=0; ccalc(tabe,can,0); MKMAT(m,width,height); mb = BDY(m); for( ix=0; ix= 0 ){ if ( (tabe[ix+1][iy] <= 0) || (tabe[ix][iy+1] <= 0 ) || (tabe[ix+1][iy+1] <= 0 ) ) mb[ix][iy] = (Obj)one; } else { if ( (tabe[ix+1][iy] >= 0 ) || ( tabe[ix][iy+1] >= 0 ) || ( tabe[ix+1][iy+1] >= 0 )) mb[ix][iy] = (Obj)one; } } } *rp = (Obj)m; } void ccalc(double **tab,struct canvas *can,int nox) { double x,y,xmin,ymin,xstep,ystep; int ix,iy; Real r,rx,ry; Obj fr,g; int w,h; V vx,vy; Obj t,s; MKReal(1.0,r); mulr(CO,(Obj)can->formula,(Obj)r,&fr); vx = can->vx; vy = can->vy; w = can->width; h = can->height; xmin = can->xmin; xstep = (can->xmax-can->xmin)/w; ymin = can->ymin; ystep = (can->ymax-can->ymin)/h; MKReal(1.0,rx); MKReal(1.0,ry); for( ix = 0, x = xmin; ix < w+1 ; ix++, x += xstep ) { BDY(rx) = x; substr(CO,0,fr,vx,x?(Obj)rx:0,&t); devalr(CO,t,&g); for( iy = 0, y = ymin; iy < h+1 ; iy++, y += ystep ) { BDY(ry) = y; substr(CO,0,g,vy,y?(Obj)ry:0,&t); devalr(CO,t,&s); tab[ix][iy] = ToReal(s); } } } /* end plot time check */ static void Pitvversion(Q *rp) { STOQ(ASIR_VERSION, *rp); } extern int bigfloat; static void Pitv(NODE arg, Obj *rp) { Num a, i, s; Itv c; double inf, sup; #if 1 if ( bigfloat ) Pitvbf(arg, rp); else Pitvd(arg,rp); #else asir_assert(ARG0(arg),O_N,"itv"); if ( argc(arg) > 1 ) { asir_assert(ARG1(arg),O_N,"itv"); istoitv((Num)ARG0(arg),(Num)ARG1(arg),&c); } else { a = (Num)ARG0(arg); if ( ! a ) { *rp = 0; return; } else if ( NID(a) == N_IP || NID(a) == N_IntervalBigFloat) { *rp = (Obj)a; return; } else if ( NID(a) == N_IntervalDouble ) { inf = INF((IntervalDouble)a); sup = SUP((IntervalDouble)a); double2bf(inf, (BF *)&i); double2bf(sup, (BF *)&s); istoitv(i,s,&c); } else istoitv(a,a,&c); } if ( NID( c ) == N_IntervalBigFloat ) addulp((IntervalBigFloat)c, (IntervalBigFloat *)rp); else *rp = (Obj)c; #endif } static void Pitvbf(NODE arg, Obj *rp) { Num a, i, s; Itv c; BF ii,ss; double inf, sup; asir_assert(ARG0(arg),O_N,"intvalbf"); a = (Num)ARG0(arg); if ( argc(arg) > 1 ) { asir_assert(ARG1(arg),O_N,"intvalbf"); i = (Num)ARG0(arg); s = (Num)ARG1(arg); ToBf(i, &ii); ToBf(s, &ss); istoitv((Num)ii,(Num)ss,&c); } else { if ( ! a ) { *rp = 0; return; } else if ( NID(a) == N_IP ) { itvtois((Itv)a, &i, &s); ToBf(i, &ii); ToBf(s, &ss); istoitv((Num)ii,(Num)ss,&c); } else if ( NID(a) == N_IntervalBigFloat) { *rp = (Obj)a; return; } else if ( NID(a) == N_IntervalDouble ) { inf = INF((IntervalDouble)a); sup = SUP((IntervalDouble)a); double2bf(inf, (BF *)&i); double2bf(sup, (BF *)&s); istoitv(i,s,&c); } else { ToBf(a, (BF *)&i); istoitv(i,i,&c); } } if ( c && OID( c ) == O_N && NID( c ) == N_IntervalBigFloat ) addulp((IntervalBigFloat)c, (IntervalBigFloat *)rp); else *rp = (Obj)c; } static void Pitvd(NODE arg, Obj *rp) { double inf, sup; Num a, a0, a1, t; Itv ia; IntervalDouble d; asir_assert(ARG0(arg),O_N,"intvald"); a0 = (Num)ARG0(arg); if ( argc(arg) > 1 ) { asir_assert(ARG1(arg),O_N,"intvald"); a1 = (Num)ARG1(arg); } else { if ( a0 && OID(a0)==O_N && NID(a0)==N_IntervalDouble ) { inf = INF((IntervalDouble)a0); sup = SUP((IntervalDouble)a0); MKIntervalDouble(inf,sup,d); *rp = (Obj)d; return; } a1 = (Num)ARG0(arg); } if ( compnum(0,a0,a1) > 0 ) { t = a0; a0 = a1; a1 = t; } inf = ToRealDown(a0); sup = ToRealUp(a1); MKIntervalDouble(inf,sup,d); *rp = (Obj)d; } static void Pinf(NODE arg, Obj *rp) { Num a, i, s; Real r; double d; a = (Num)ARG0(arg); if ( ! a ) { *rp = 0; } else if ( OID(a) == O_N ) { switch ( NID(a) ) { case N_IntervalDouble: d = INF((IntervalDouble)a); MKReal(d, r); *rp = (Obj)r; break; case N_IP: case N_IntervalBigFloat: case N_IntervalQuad: itvtois((Itv)ARG0(arg),&i,&s); *rp = (Obj)i; break; default: *rp = (Obj)a; break; } } else { *rp = (Obj)a; } } static void Psup(NODE arg, Obj *rp) { Num a, i, s; Real r; double d; a = (Num)ARG0(arg); if ( ! a ) { *rp = 0; } else if ( OID(a) == O_N ) { switch ( NID(a) ) { case N_IntervalDouble: d = SUP((IntervalDouble)a); MKReal(d, r); *rp = (Obj)r; break; case N_IP: case N_IntervalBigFloat: case N_IntervalQuad: itvtois((Itv)ARG0(arg),&i,&s); *rp = (Obj)s; break; default: *rp = (Obj)a; break; } } else { *rp = (Obj)a; } } static void Pmid(NODE arg, Obj *rp) { Num a, s; Real r; double d; a = (Num)ARG0(arg); if ( ! a ) { *rp = 0; } else switch (OID(a)) { case O_N: if ( NID(a) == N_IntervalDouble ) { d = ( INF((IntervalDouble)a)+SUP((IntervalDouble)a) ) / 2.0; MKReal(d, r); *rp = (Obj)r; } else if ( NID(a) == N_IntervalQuad ) { error("mid: not supported operation"); *rp = 0; } else if ( NID(a) == N_IP || NID(a) == N_IntervalBigFloat ) { miditvp((Itv)ARG0(arg),&s); *rp = (Obj)s; } else { *rp = (Obj)a; } break; #if 0 case O_P: case O_R: case O_LIST: case O_VECT: case O_MAT: #endif default: *rp = (Obj)a; break; } } static void Pcup(NODE arg, Obj *rp) { Itv s; Num a, b; asir_assert(ARG0(arg),O_N,"cup"); asir_assert(ARG1(arg),O_N,"cup"); a = (Num)ARG0(arg); b = (Num)ARG1(arg); if ( a && NID(a) == N_IntervalDouble && b && NID(b) == N_IntervalDouble ) { cupitvd((IntervalDouble)a, (IntervalDouble)b, (IntervalDouble *)rp); } else { cupitvp((Itv)ARG0(arg),(Itv)ARG1(arg),&s); *rp = (Obj)s; } } static void Pcap(NODE arg, Obj *rp) { Itv s; Num a, b; asir_assert(ARG0(arg),O_N,"cap"); asir_assert(ARG1(arg),O_N,"cap"); a = (Num)ARG0(arg); b = (Num)ARG1(arg); if ( a && NID(a) == N_IntervalDouble && b && NID(b) == N_IntervalDouble ) { capitvd((IntervalDouble)a, (IntervalDouble)b, (IntervalDouble *)rp); } else { capitvp((Itv)ARG0(arg),(Itv)ARG1(arg),&s); *rp = (Obj)s; } } static void Pwidth(arg,rp) NODE arg; Obj *rp; { Num s; Num a; asir_assert(ARG0(arg),O_N,"width"); a = (Num)ARG0(arg); if ( ! a ) { *rp = 0; } else if ( NID(a) == N_IntervalDouble ) { widthitvd((IntervalDouble)a, (Num *)rp); } else { widthitvp((Itv)ARG0(arg),&s); *rp = (Obj)s; } } static void Pabsitv(arg,rp) NODE arg; Obj *rp; { Num s; Num a, b; asir_assert(ARG0(arg),O_N,"absitv"); a = (Num)ARG0(arg); if ( ! a ) { *rp = 0; } else if ( NID(a) == N_IntervalDouble ) { absitvd((IntervalDouble)a, (Num *)rp); } else { absitvp((Itv)ARG0(arg),&s); *rp = (Obj)s; } } static void Pdistance(arg,rp) NODE arg; Obj *rp; { Num s; Num a, b; asir_assert(ARG0(arg),O_N,"distance"); asir_assert(ARG1(arg),O_N,"distance"); a = (Num)ARG0(arg); b = (Num)ARG1(arg); if ( a && NID(a) == N_IntervalDouble && b && NID(b) == N_IntervalDouble ) { distanceitvd((IntervalDouble)a, (IntervalDouble)b, (Num *)rp); } else { distanceitvp((Itv)ARG0(arg),(Itv)ARG1(arg),&s); *rp = (Obj)s; } } static void Pinitv(arg,rp) NODE arg; Obj *rp; { int s; Q q; asir_assert(ARG0(arg),O_N,"intval"); asir_assert(ARG1(arg),O_N,"intval"); if ( ! ARG1(arg) ) { if ( ! ARG0(arg) ) s = 1; else s = 0; } else if ( NID(ARG1(arg)) == N_IntervalDouble ) { s = initvd((Num)ARG0(arg),(IntervalDouble)ARG1(arg)); } else if ( NID(ARG1(arg)) == N_IP || NID(ARG1(arg)) == N_IntervalBigFloat ) { if ( ! ARG0(arg) ) s = initvp((Num)ARG0(arg),(Itv)ARG1(arg)); else if ( NID(ARG0(arg)) == N_IP ) { s = itvinitvp((Itv)ARG0(arg),(Itv)ARG1(arg)); } else { s = initvp((Num)ARG0(arg),(Itv)ARG1(arg)); } } else { s = ! compnum(0,(Num)ARG0(arg),(Num)ARG1(arg)); } STOQ(s,q); *rp = (Obj)q; } static void Pdisjitv(arg,rp) NODE arg; Obj *rp; { Itv s; asir_assert(ARG0(arg),O_N,"disjitv"); asir_assert(ARG1(arg),O_N,"disjitv"); error("disjitv: not implemented yet"); if ( ! s ) *rp = 0; else *rp = (Obj)ONE; } #endif extern int printmode; static void pprintmode( void ) { switch (printmode) { #if defined(INTERVAL) case MID_PRINTF_E: fprintf(stderr,"Interval printing mode is a mitpoint type.\n"); #endif case PRINTF_E: fprintf(stderr,"Printf's double printing mode is \"%%.16e\".\n"); break; #if defined(INTERVAL) case MID_PRINTF_G: fprintf(stderr,"Interval printing mode is a mitpoint type.\n"); #endif default: case PRINTF_G: fprintf(stderr,"Printf's double printing mode is \"%%g\".\n"); break; } } static void Pprintmode(NODE arg, Obj *rp) { int l; Z a, r; a = (Z)ARG0(arg); if(!a||(NUM(a)&&INT(a))){ l=QTOS(a); if ( l < 0 ) l = 0; #if defined(INTERVAL) else if ( l > MID_PRINTF_E ) l = 0; #else else if ( l > PRINTF_E ) l = 0; #endif STOQ(printmode,r); *rp = (Obj)r; printmode = l; pprintmode(); } else { *rp = 0; } }