=================================================================== RCS file: /home/cvs/OpenXM_contrib2/asir2000/builtin/pf.c,v retrieving revision 1.7 retrieving revision 1.16 diff -u -p -r1.7 -r1.16 --- OpenXM_contrib2/asir2000/builtin/pf.c 2004/06/22 09:17:21 1.7 +++ OpenXM_contrib2/asir2000/builtin/pf.c 2009/07/23 01:04:29 1.16 @@ -45,7 +45,7 @@ * DEVELOPER SHALL HAVE NO LIABILITY IN CONNECTION WITH THE USE, * PERFORMANCE OR NON-PERFORMANCE OF THE SOFTWARE. * - * $OpenXM: OpenXM_contrib2/asir2000/builtin/pf.c,v 1.6 2003/02/14 22:29:07 ohara Exp $ + * $OpenXM: OpenXM_contrib2/asir2000/builtin/pf.c,v 1.15 2008/11/18 20:52:47 ohara Exp $ */ #include "ca.h" #include "math.h" @@ -63,21 +63,29 @@ void make_tri(void); void make_exp(void); void simplify_pow(PFINS,Obj *); -void Pfunctor(),Pargs(),Pfunargs(),Pvtype(),Pcall(),Pdeval(); +void Pfunctor(),Pargs(),Pfunargs(),Pvtype(),Pcall(),Pdeval(),Pfunargs_ext(); void Pregister_handler(); void Peval_quote(); -void Pmapat(); +void Pmapat(), Pmap(); +void Padd_handler(); +void Plist_handler(); +void Pclear_handler(); struct ftab puref_tab[] = { {"mapat",Pmapat,-99999999}, + {"map",Pmap,-99999999}, {"functor",Pfunctor,1}, {"args",Pargs,1}, {"funargs",Pfunargs,1}, + {"funargs_ext",Pfunargs_ext,1}, {"register_handler",Pregister_handler,1}, + {"add_handler",Padd_handler,2}, + {"list_handler",Plist_handler,1}, + {"clear_handler",Pclear_handler,1}, {"call",Pcall,2}, {"vtype",Pvtype,1}, {"deval",Pdeval,1}, - {"eval_quote",Peval_quote,1}, + {"eval_quote",Peval_quote,-2}, {0,0,0}, }; @@ -284,9 +292,15 @@ Obj *rp; pf = ins->pf; ad = ins->ad; a0 = ad[0].arg; a1 = ad[1].arg; if ( !a1 ) *rp = (Obj)ONE; - else if ( !a0 ) - *rp = 0; - else if ( NUM(a1) && INT(a1) ) + else if ( !a0 ) { + if ( RATN(a1) && SGN((Q)a1)>0 ) + *rp = 0; + else if ( RATN(a1) && SGN((Q)a1) < 0 ) + error("simplify_pow : division by 0"); + else { + instov(ins,&v); MKV(v,t); *rp = (Obj)t; + } + } else if ( NUM(a1) && INT(a1) ) arf_pwr(CO,a0,a1,rp); else { instov(ins,&v); MKV(v,t); *rp = (Obj)t; @@ -294,8 +308,8 @@ Obj *rp; } #define ISPFINS(p)\ -(p)&&(ID(p) == O_P)&&((int)VR((P)p)->attr!=V_PF)&&\ -UNIQ(DEG(DC((P)p)))&&UNIQ(COEF(DC((P)p))) +((p)&&(ID(p) == O_P)&&((int)VR((P)p)->attr==V_PF)&&\ +UNIQ(DEG(DC((P)p)))&&UNIQ(COEF(DC((P)p)))) void Pfunctor(arg,rp) NODE arg; @@ -374,6 +388,43 @@ LIST *rp; } } +void Pfunargs_ext(arg,rp) +NODE arg; +LIST *rp; +{ + P p; + P f; + FUNC t; + PF pf; + PFINS ins; + PFAD ad; + NODE n,n0,d,d0,a,a0; + LIST alist,dlist; + Q q; + int i; + + p = (P)ARG0(arg); + if ( !ISPFINS(p) ) + *rp = 0; + else { + ins = (PFINS)VR(p)->priv; ad = ins->ad; pf = ins->pf; + t = (FUNC)MALLOC(sizeof(struct oFUNC)); + t->name = t->fullname = pf->name; t->id = A_PURE; t->argc = pf->argc; + t->f.puref = pf; + makesrvar(t,&f); + + d0 = a0 = 0; + for ( i = 0; i < pf->argc; i++ ) { + NEXTNODE(d0,d); STOQ(ad[i].d,q); BDY(d) = (pointer)q; + NEXTNODE(a0,a); BDY(a) = (pointer)ad[i].arg; + } + NEXT(d) = 0; NEXT(a) = 0; MKLIST(alist,a0); MKLIST(dlist,d0); + + n0 = mknode(3,f,dlist,alist); + MKLIST(*rp,n0); + } +} + void Pvtype(arg,rp) NODE arg; Q *rp; @@ -387,7 +438,7 @@ Q *rp; STOQ((int)VR(p)->attr,*rp); } -extern FUNC registered_handler; +extern NODE user_int_handler,user_quit_handler; void Pregister_handler(arg,rp) NODE arg; @@ -395,12 +446,15 @@ Q *rp; { P p; V v; + NODE n; FUNC func; p = (P)ARG0(arg); - if ( !p ) - registered_handler = 0; - else if ( OID(p) != 2 ) + if ( !p ) { + user_int_handler = 0; + *rp = 0; + return; + } else if ( OID(p) != 2 ) error("register_hanlder : invalid argument"); v = VR(p); if ( (int)v->attr != V_SR ) @@ -410,16 +464,111 @@ Q *rp; if ( func->argc ) error("register_hanlder : the function must be with no argument"); else { - registered_handler = func; + MKNODE(n,(pointer)func,user_int_handler); + user_int_handler = n; *rp = ONE; - } + } } } +void Padd_handler(arg,rp) +NODE arg; +Q *rp; +{ + P p; + V v; + NODE n; + FUNC func; + char *name; + NODE *hlistp; + + asir_assert(ARG0(arg),O_STR,"add_handler"); + name = BDY((STRING)ARG0(arg)); + p = (P)ARG1(arg); + if ( !strcmp(name,"intr") ) + hlistp = &user_int_handler; + else if ( !strcmp(name,"quit") ) + hlistp = &user_quit_handler; + else + error("add_handler : invalid keyword (must be \"intr\" or \"quit\")"); + if ( !p ) { + *hlistp = 0; *rp = 0; + return; + } + if ( OID(p) == 2 ) { + v = VR(p); + if ( (int)v->attr != V_SR ) + error("add_hanlder : no such function"); + func = (FUNC)v->priv; + } else if ( OID(p) == O_STR ) { + gen_searchf_searchonly(BDY((STRING)p),&func); + if ( !func ) + error("add_hanlder : no such function"); + } + if ( func->argc ) + error("register_hanlder : the function must be with no argument"); + else { + MKNODE(n,(pointer)func,*hlistp); + *hlistp = n; + *rp = ONE; + } +} + +void Plist_handler(arg,rp) +NODE arg; +LIST *rp; +{ + NODE r0,r,t; + char *name; + NODE hlist; + STRING fname; + + asir_assert(ARG0(arg),O_STR,"list_handler"); + name = BDY((STRING)ARG0(arg)); + if ( !strcmp(name,"intr") ) + hlist = user_int_handler; + else if ( !strcmp(name,"quit") ) + hlist = user_quit_handler; + else + error("list_handler : invalid keyword (must be \"intr\" or \"quit\")"); + for ( r0 = 0, t = hlist; t; t = NEXT(t) ) { + NEXTNODE(r0,r); + MKSTR(fname,((FUNC)BDY(t))->fullname); + BDY(r) = (pointer)fname; + } + if ( r0 ) NEXT(r) = 0; + MKLIST(*rp,r0); +} + +void Pclear_handler(arg,rp) +NODE arg; +Q *rp; +{ + NODE r0,r,t; + char *name; + NODE hlist; + STRING fname; + + asir_assert(ARG0(arg),O_STR,"clear_handler"); + name = BDY((STRING)ARG0(arg)); + if ( !strcmp(name,"intr") ) + user_int_handler = 0; + else if ( !strcmp(name,"quit") ) + user_quit_handler = 0; + else + error("clear_handler : invalid keyword (must be \"intr\" or \"quit\")"); + *rp = 0; +} + void Pcall(NODE arg,Obj *rp) { P p; V v; + NODE n,n1; + LIST list; + VECT vect; + pointer *a; + int len,i; p = (P)ARG0(arg); if ( !p || OID(p) != 2 ) @@ -427,9 +576,26 @@ void Pcall(NODE arg,Obj *rp) v = VR(p); if ( (int)v->attr != V_SR ) error("call : no such function"); - - else - *rp = (Obj)bevalf((FUNC)v->priv,BDY((LIST)ARG1(arg))); + else { + list = (LIST) ARG1(arg); + if ( list ) { + switch (OID(list)) { + case O_VECT: + vect = (VECT)list; len = vect->len; a = BDY(vect); + for ( i = len - 1, n = 0; i >= 0; i-- ) { + MKNODE(n1,a[i],n); n = n1; + } + MKLIST(list,n); + /* falling next case */ + case O_LIST: + *rp = (Obj)bevalf_with_opts((FUNC)v->priv,BDY(list),current_option); + return; + default: + break; + } + } + error("call : invalid argument"); + } } /* at=position of arg to be used for iteration */ @@ -447,7 +613,10 @@ void Pmapat(NODE arg,Obj *rp) int len,row,col,i,j,pos; Obj iter; pointer val; + NODE option; + option = current_option; + if ( argc(arg) < 3 ) error("mapat : too few arguments"); @@ -472,7 +641,7 @@ void Pmapat(NODE arg,Obj *rp) NEXTNODE(r0,r); iter = BDY(t); rest = NEXT(t); if ( !iter ) { - *rp = bevalf(f,node); + *rp = bevalf_with_opts(f,node,option); return; } switch ( OID(iter) ) { @@ -480,7 +649,7 @@ void Pmapat(NODE arg,Obj *rp) v = (VECT)iter; len = v->len; MKVECT(rv,len); for ( i = 0; i < len; i++ ) { BDY(r) = BDY(v)[i]; NEXT(r) = rest; - BDY(rv)[i] = bevalf(f,r0); + BDY(rv)[i] = bevalf_with_opts(f,r0,option); } *rp = (Obj)rv; break; @@ -489,7 +658,7 @@ void Pmapat(NODE arg,Obj *rp) for ( i = 0; i < row; i++ ) for ( j = 0; j < col; j++ ) { BDY(r) = BDY(m)[i][j]; NEXT(r) = rest; - BDY(rm)[i][j] = bevalf(f,r0); + BDY(rm)[i][j] = bevalf_with_opts(f,r0,option); } *rp = (Obj)rm; break; @@ -497,7 +666,7 @@ void Pmapat(NODE arg,Obj *rp) n = BDY((LIST)iter); for ( t0 = t = 0; n; n = NEXT(n) ) { BDY(r) = BDY(n); NEXT(r) = rest; - NEXTNODE(t0,t); BDY(t) = bevalf(f,r0); + NEXTNODE(t0,t); BDY(t) = bevalf_with_opts(f,r0,option); } if ( t0 ) NEXT(t) = 0; @@ -505,11 +674,85 @@ void Pmapat(NODE arg,Obj *rp) *rp = (Obj)rl; break; default: - *rp = bevalf(f,node); + *rp = bevalf_with_opts(f,node,option); break; } } +/* An implementation of 'map' as builtin function. */ +void Pmap(NODE arg,Obj *rp) +{ + LIST args; + NODE node,rest,t0,t,n,r,r0; + P fpoly; + V fvar; + FUNC f; + VECT v,rv; + MAT m,rm; + LIST rl; + int len,row,col,i,j; + Obj iter; + pointer val; + NODE option; + + option = current_option; + + if ( argc(arg) < 2 ) + error("mapat : too few arguments"); + + fpoly = (P)ARG0(arg); + if ( !fpoly || OID(fpoly) != O_P ) + error("map : invalid function specification"); + fvar = VR(fpoly); + if ( fvar->attr != (pointer)V_SR || !(f=(FUNC)fvar->priv) ) + error("map : invalid function specification"); + + node = NEXT(arg); + len = length(node); + if ( 0 >= len ) + error("evalmapf : invalid position"); + r0 = 0; + NEXTNODE(r0,r); + iter = BDY(t); rest = NEXT(t); + if ( !iter ) { + *rp = bevalf_with_opts(f,node,option); + return; + } + switch ( OID(iter) ) { + case O_VECT: + v = (VECT)iter; len = v->len; MKVECT(rv,len); + for ( i = 0; i < len; i++ ) { + BDY(r) = BDY(v)[i]; NEXT(r) = rest; + BDY(rv)[i] = bevalf_with_opts(f,r0,option); + } + *rp = (Obj)rv; + break; + case O_MAT: + m = (MAT)iter; row = m->row; col = m->col; MKMAT(rm,row,col); + for ( i = 0; i < row; i++ ) + for ( j = 0; j < col; j++ ) { + BDY(r) = BDY(m)[i][j]; NEXT(r) = rest; + BDY(rm)[i][j] = bevalf_with_opts(f,r0,option); + } + *rp = (Obj)rm; + break; + case O_LIST: + n = BDY((LIST)iter); + for ( t0 = t = 0; n; n = NEXT(n) ) { + BDY(r) = BDY(n); NEXT(r) = rest; + NEXTNODE(t0,t); BDY(t) = bevalf_with_opts(f,r0,option); + } + if ( t0 ) + NEXT(t) = 0; + MKLIST(rl,t0); + *rp = (Obj)rl; + break; + default: + *rp = bevalf_with_opts(f,node,option); + break; + } +} + void Pdeval(arg,rp) NODE arg; Obj *rp; @@ -522,6 +765,19 @@ void Peval_quote(arg,rp) NODE arg; Obj *rp; { - asir_assert(ARG0(arg),O_QUOTE,"eval_quote"); - *rp = eval((FNODE)BDY((QUOTE)ARG0(arg))); + FNODE a; + QUOTE q; + Obj f; + + f = (Obj)ARG0(arg); + if ( !f || OID(f) != O_QUOTE ) { + *rp = f; + return; + } + if ( argc(arg) == 2 && ARG1(arg) ) { + a = partial_eval((FNODE)BDY((QUOTE)ARG0(arg))); + MKQUOTE(q,a); + *rp = (Obj)q; + } else + *rp = eval((FNODE)BDY((QUOTE)ARG0(arg))); }