Annotation of OpenXM_contrib2/asir2000/builtin/strobj.c, Revision 1.109
1.6 noro 1: /*
2: * Copyright (c) 1994-2000 FUJITSU LABORATORIES LIMITED
3: * All rights reserved.
4: *
5: * FUJITSU LABORATORIES LIMITED ("FLL") hereby grants you a limited,
6: * non-exclusive and royalty-free license to use, copy, modify and
7: * redistribute, solely for non-commercial and non-profit purposes, the
8: * computer program, "Risa/Asir" ("SOFTWARE"), subject to the terms and
9: * conditions of this Agreement. For the avoidance of doubt, you acquire
10: * only a limited right to use the SOFTWARE hereunder, and FLL or any
11: * third party developer retains all rights, including but not limited to
12: * copyrights, in and to the SOFTWARE.
13: *
14: * (1) FLL does not grant you a license in any way for commercial
15: * purposes. You may use the SOFTWARE only for non-commercial and
16: * non-profit purposes only, such as academic, research and internal
17: * business use.
18: * (2) The SOFTWARE is protected by the Copyright Law of Japan and
19: * international copyright treaties. If you make copies of the SOFTWARE,
20: * with or without modification, as permitted hereunder, you shall affix
21: * to all such copies of the SOFTWARE the above copyright notice.
22: * (3) An explicit reference to this SOFTWARE and its copyright owner
23: * shall be made on your publication or presentation in any form of the
24: * results obtained by use of the SOFTWARE.
25: * (4) In the event that you modify the SOFTWARE, you shall notify FLL by
1.7 noro 26: * e-mail at risa-admin@sec.flab.fujitsu.co.jp of the detailed specification
1.6 noro 27: * for such modification or the source code of the modified part of the
28: * SOFTWARE.
29: *
30: * THE SOFTWARE IS PROVIDED AS IS WITHOUT ANY WARRANTY OF ANY KIND. FLL
31: * MAKES ABSOLUTELY NO WARRANTIES, EXPRESSED, IMPLIED OR STATUTORY, AND
32: * EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS
33: * FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT OF THIRD PARTIES'
34: * RIGHTS. NO FLL DEALER, AGENT, EMPLOYEES IS AUTHORIZED TO MAKE ANY
35: * MODIFICATIONS, EXTENSIONS, OR ADDITIONS TO THIS WARRANTY.
36: * UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, TORT, CONTRACT,
37: * OR OTHERWISE, SHALL FLL BE LIABLE TO YOU OR ANY OTHER PERSON FOR ANY
38: * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, PUNITIVE OR CONSEQUENTIAL
39: * DAMAGES OF ANY CHARACTER, INCLUDING, WITHOUT LIMITATION, DAMAGES
40: * ARISING OUT OF OR RELATING TO THE SOFTWARE OR THIS AGREEMENT, DAMAGES
41: * FOR LOSS OF GOODWILL, WORK STOPPAGE, OR LOSS OF DATA, OR FOR ANY
42: * DAMAGES, EVEN IF FLL SHALL HAVE BEEN INFORMED OF THE POSSIBILITY OF
43: * SUCH DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY. EVEN IF A PART
44: * OF THE SOFTWARE HAS BEEN DEVELOPED BY A THIRD PARTY, THE THIRD PARTY
45: * DEVELOPER SHALL HAVE NO LIABILITY IN CONNECTION WITH THE USE,
46: * PERFORMANCE OR NON-PERFORMANCE OF THE SOFTWARE.
47: *
1.109 ! noro 48: * $OpenXM: OpenXM_contrib2/asir2000/builtin/strobj.c,v 1.108 2005/12/11 07:21:43 noro Exp $
1.6 noro 49: */
1.1 noro 50: #include "ca.h"
51: #include "parse.h"
52: #include "ctype.h"
1.10 ohara 53: #if defined(PARI)
1.1 noro 54: #include "genpari.h"
1.11 saito 55: # if !(PARI_VERSION_CODE > 131588)
1.1 noro 56: extern jmp_buf environnement;
1.11 saito 57: # endif
1.1 noro 58: #endif
1.5 noro 59: #include <string.h>
60:
1.89 noro 61: #if defined(__GNUC__)
62: #define INLINE inline
63: #elif defined(VISUAL)
64: #define INLINE __inline
65: #else
66: #define INLINE
67: #endif
68:
1.18 noro 69: struct TeXSymbol {
70: char *text;
71: char *symbol;
72: };
73:
1.71 noro 74: #define OPNAME(f) (((ARF)FA0(f))->name[0])
1.77 noro 75: #define IS_ZERO(f) (((f)->id==I_FORMULA) && FA0(f)==0 )
1.75 noro 76: #define IS_BINARYPWR(f) (((f)->id==I_BOP) &&(OPNAME(f)=='^'))
77: #define IS_NARYADD(f) (((f)->id==I_NARYOP) &&(OPNAME(f)=='+'))
78: #define IS_NARYMUL(f) (((f)->id==I_NARYOP) &&(OPNAME(f)=='*'))
1.71 noro 79:
1.1 noro 80: extern char *parse_strp;
81:
1.50 ohara 82: void Psprintf();
1.1 noro 83: void Prtostr(), Pstrtov(), Peval_str();
1.3 noro 84: void Pstrtoascii(), Pasciitostr();
1.5 noro 85: void Pstr_len(), Pstr_chr(), Psub_str();
1.14 noro 86: void Pwrite_to_tb();
87: void Ptb_to_string();
88: void Pclear_tb();
89: void Pstring_to_tb();
90: void Pquotetotex_tb();
91: void Pquotetotex();
1.24 noro 92: void Pquotetotex_env();
1.47 noro 93: void Pflatten_quote();
1.69 noro 94:
1.108 noro 95: void Pqt_is_integer(),Pqt_is_rational(),Pqt_is_number(),Pqt_is_coef();
96: void Pqt_is_dependent(),Pqt_is_function(),Pqt_is_var();
1.109 ! noro 97: void Pqt_set_ord(),Pqt_set_coef(),Pqt_set_weight();
1.105 noro 98: void Pqt_normalize();
99: void Pnqt_comp();
100: void Pnqt_match();
1.106 noro 101: void Pnqt_match_rewrite();
1.69 noro 102:
1.105 noro 103: void Pqt_to_nbp();
1.101 noro 104: void Pshuffle_mul(), Pharmonic_mul();
1.102 noro 105: void Pnbp_hm(), Pnbp_ht(), Pnbp_hc(), Pnbp_rest();
106: void Pnbm_deg();
107: void Pnbm_hp_rest();
108: void Pnbm_hxky(), Pnbm_xky_rest();
109: void Pnbm_hv(), Pnbm_rest();
1.98 noro 110:
1.52 noro 111: void Pquote_to_funargs(),Pfunargs_to_quote(),Pget_function_name();
1.107 noro 112: void Pqt_match(),Pget_quote_id();
1.105 noro 113: void Pqt_to_nary(),Pqt_to_bin();
1.88 noro 114: void fnode_do_assign(NODE arg);
1.58 ohara 115: void do_assign(NODE arg);
1.14 noro 116: void fnodetotex_tb(FNODE f,TB tb);
117: char *symbol_name(char *name);
1.28 noro 118: char *conv_rule(char *name);
1.38 noro 119: char *conv_subs(char *name);
1.28 noro 120: char *call_convfunc(char *name);
1.14 noro 121: void tb_to_string(TB tb,STRING *rp);
122: void fnodenodetotex_tb(NODE n,TB tb);
123: void fargstotex_tb(char *opname,FNODE f,TB tb);
1.35 noro 124: int top_is_minus(FNODE f);
1.105 noro 125: int qt_match(Obj f,Obj pat,NODE *rp);
1.106 noro 126: FNODE partial_eval(FNODE), fnode_to_nary(FNODE), fnode_to_bin(FNODE,int);
127: FNODE nfnode_add(FNODE a1,FNODE a2,int expand);
128: FNODE nfnode_mul(FNODE a1,FNODE a2,int expand);
129: FNODE nfnode_pwr(FNODE a1,FNODE a2,int expand);
1.108 noro 130: FNODE nfnode_mul_coef(Obj c,FNODE f,int expand);
1.106 noro 131: FNODE fnode_expand_pwr(FNODE f,int n,int expand);
132: FNODE to_narymul(FNODE f);
133: FNODE to_naryadd(FNODE f);
134: FNODE fnode_node_to_nary(ARF op,NODE n);
135: void fnode_base_exp(FNODE f,FNODE *bp,FNODE *ep);
1.108 noro 136: void fnode_coef_body(FNODE f,Obj *cp,FNODE *bp);
1.106 noro 137: FNODE nfnode_match_rewrite(FNODE f,FNODE p,FNODE c,FNODE a,int mode);
138: FNODE fnode_apply(FNODE f,FNODE (*func)(),int expand);
139: FNODE fnode_normalize(FNODE f,int expand);
1.107 noro 140: FNODE rewrite_fnode(FNODE f,NODE arg,int qarg);
1.1 noro 141:
142: struct ftab str_tab[] = {
1.50 ohara 143: {"sprintf",Psprintf,-99999999},
1.1 noro 144: {"rtostr",Prtostr,1},
145: {"strtov",Pstrtov,1},
146: {"eval_str",Peval_str,1},
1.3 noro 147: {"strtoascii",Pstrtoascii,1},
148: {"asciitostr",Pasciitostr,1},
1.5 noro 149: {"str_len",Pstr_len,1},
150: {"str_chr",Pstr_chr,3},
151: {"sub_str",Psub_str,3},
1.14 noro 152: {"write_to_tb",Pwrite_to_tb,2},
153: {"clear_tb",Pclear_tb,1},
154: {"tb_to_string",Ptb_to_string,1},
155: {"string_to_tb",Pstring_to_tb,1},
1.63 noro 156: {"get_quote_id",Pget_quote_id,1},
1.69 noro 157:
1.108 noro 158: {"qt_is_var",Pqt_is_var,1},
159: {"qt_is_coef",Pqt_is_coef,1},
1.105 noro 160: {"qt_is_number",Pqt_is_number,1},
161: {"qt_is_rational",Pqt_is_rational,1},
162: {"qt_is_integer",Pqt_is_integer,1},
163: {"qt_is_function",Pqt_is_function,1},
164: {"qt_is_dependent",Pqt_is_dependent,2},
165:
1.108 noro 166: {"qt_set_coef",Pqt_set_coef,-1},
1.105 noro 167: {"qt_set_ord",Pqt_set_ord,-1},
1.109 ! noro 168: {"qt_set_weight",Pqt_set_weight,-1},
1.105 noro 169: {"qt_normalize",Pqt_normalize,-2},
170: {"qt_match",Pqt_match,2},
1.106 noro 171: {"nqt_match_rewrite",Pnqt_match_rewrite,3},
1.105 noro 172:
173: {"nqt_comp",Pnqt_comp,2},
174: {"nqt_match",Pnqt_match,-3},
175: {"qt_to_nbp",Pqt_to_nbp,1},
1.101 noro 176: {"shuffle_mul",Pshuffle_mul,2},
177: {"harmonic_mul",Pharmonic_mul,2},
1.70 noro 178:
1.100 noro 179: {"nbp_hm", Pnbp_hm,1},
180: {"nbp_ht", Pnbp_ht,1},
181: {"nbp_hc", Pnbp_hc,1},
182: {"nbp_rest", Pnbp_rest,1},
1.102 noro 183: {"nbm_deg", Pnbm_deg,1},
184: {"nbm_hxky", Pnbm_hxky,1},
185: {"nbm_xky_rest", Pnbm_xky_rest,1},
186: {"nbm_hp_rest", Pnbm_hp_rest,1},
187: {"nbm_hv", Pnbm_hv,1},
1.100 noro 188: {"nbm_rest", Pnbm_rest,1},
189:
1.105 noro 190: {"qt_to_nary",Pqt_to_nary,1},
191: {"qt_to_bin",Pqt_to_bin,2},
1.95 noro 192:
1.60 noro 193: {"quotetotex_tb",Pquotetotex_tb,2},
194: {"quotetotex",Pquotetotex,1},
195: {"quotetotex_env",Pquotetotex_env,-99999999},
1.65 noro 196: {"flatten_quote",Pflatten_quote,-2},
1.60 noro 197: {"quote_to_funargs",Pquote_to_funargs,1},
1.48 noro 198: {"funargs_to_quote",Pfunargs_to_quote,1},
1.52 noro 199: {"get_function_name",Pget_function_name,1},
1.1 noro 200: {0,0,0},
201: };
1.13 noro 202:
1.14 noro 203: void write_tb(char *s,TB tb)
204: {
205: if ( tb->next == tb->size ) {
206: tb->size *= 2;
207: tb->body = (char **)REALLOC(tb->body,tb->size*sizeof(char *));
208: }
209: tb->body[tb->next] = s;
210: tb->next++;
211: }
1.13 noro 212:
1.18 noro 213: int register_symbol_table(Obj arg);
214: int register_conv_rule(Obj arg);
1.38 noro 215: int register_conv_func(Obj arg);
1.23 noro 216: int register_dp_vars(Obj arg);
1.46 noro 217: int register_dp_vars_origin(Obj arg);
218: int register_dp_dvars_origin(Obj arg);
219: int register_dp_dvars_prefix(Obj arg);
1.25 noro 220: int register_dp_vars_prefix(Obj arg);
1.31 noro 221: int register_dp_vars_hweyl(Obj arg);
1.27 noro 222: int register_show_lt(Obj arg);
1.40 noro 223: char *objtostr(Obj obj);
1.18 noro 224: static struct TeXSymbol *user_texsymbol;
1.23 noro 225: static char **dp_vars;
1.25 noro 226: static int dp_vars_len;
227: static char *dp_vars_prefix;
1.46 noro 228: static char *dp_dvars_prefix;
229: static int dp_vars_origin;
230: static int dp_dvars_origin;
1.27 noro 231: static int show_lt;
1.26 noro 232: static FUNC convfunc;
1.27 noro 233: static int is_lt;
1.28 noro 234: static int conv_flag;
1.31 noro 235: static int dp_vars_hweyl;
1.28 noro 236:
1.38 noro 237: #define CONV_TABLE (1U<<0)
238: #define CONV_SUBS (1U<<1)
239: #define CONV_DMODE (1U<<2)
1.18 noro 240:
241: static struct {
242: char *name;
243: Obj value;
244: int (*reg)();
245: } qtot_env[] = {
246: {"symbol_table",0,register_symbol_table},
247: {"conv_rule",0,register_conv_rule},
1.38 noro 248: {"conv_func",0,register_conv_func},
1.23 noro 249: {"dp_vars",0,register_dp_vars},
1.25 noro 250: {"dp_vars_prefix",0,register_dp_vars_prefix},
1.46 noro 251: {"dp_dvars_prefix",0,register_dp_dvars_prefix},
252: {"dp_vars_origin",0,register_dp_vars_origin},
253: {"dp_dvars_origin",0,register_dp_dvars_origin},
1.31 noro 254: {"dp_vars_hweyl",0,register_dp_vars_hweyl},
1.27 noro 255: {"show_lt",0,register_show_lt},
1.18 noro 256: {0,0,0},
257: };
258:
1.20 noro 259: #define PARTIAL "\\partial"
1.28 noro 260:
261: char *conv_rule(char *name)
262: {
263: char *body,*r;
1.41 noro 264: int len;
1.28 noro 265:
1.38 noro 266: if ( convfunc )
267: name = call_convfunc(name);
1.41 noro 268: if ( conv_flag & CONV_TABLE ) {
269: r = symbol_name(name);
270: if ( r ) return r;
271: }
272: if ( (conv_flag & CONV_DMODE) && *name == 'd' ) {
273: body = conv_rule(name+1);
274: r = MALLOC_ATOMIC((strlen(PARTIAL)+strlen(body)+5)*sizeof(char));
275: if ( !body || !(len=strlen(body)) )
276: strcpy(r,PARTIAL);
277: else if ( len == 1 )
278: sprintf(r,"%s_%s",PARTIAL,body);
279: else
280: sprintf(r,"%s_{%s}",PARTIAL,body);
281: return r;
282: } else
283: return conv_subs(name);
1.28 noro 284: }
285:
1.40 noro 286: int _is_delimiter(char c)
287: {
288: if ( (c == ' ' || c == '_' || c == ',') ) return 1;
289: else return 0;
290: }
291:
292: int _is_alpha(char c)
293: {
294: if ( isdigit(c) || c == '{' || _is_delimiter(c) ) return 0;
295: else return 1;
296: }
297:
1.38 noro 298: char *conv_subs(char *name)
1.19 noro 299: {
1.29 noro 300: int i,j,k,len,clen,slen,start,level;
1.41 noro 301: char *buf,*head,*r,*h,*brace,*buf_conv;
1.28 noro 302: char **subs;
303:
1.41 noro 304: if ( !name || !(len=strlen(name)) ) return "";
305: if ( !(conv_flag&CONV_SUBS) ) return name;
1.28 noro 306: subs = (char **)ALLOCA(len*sizeof(char* ));
1.32 noro 307: for ( i = 0, j = 0, start = i; ; j++ ) {
1.40 noro 308: while ( (i < len) && _is_delimiter(name[i]) ) i++;
1.32 noro 309: start = i;
1.28 noro 310: if ( i == len ) break;
1.29 noro 311: if ( name[i] == '{' ) {
312: for ( level = 1, i++; i < len && level; i++ ) {
313: if ( name[i] == '{' ) level++;
314: else if ( name[i] == '}' ) level--;
315: }
1.32 noro 316: slen = i-start;
1.37 noro 317: if ( slen >= 3 ) {
318: brace = (char *)ALLOCA((slen+1)*sizeof(char));
319: strncpy(brace,name+start+1,slen-2);
320: brace[slen-2] = 0;
1.38 noro 321: buf = conv_subs(brace);
1.37 noro 322: subs[j] = (char *)ALLOCA((strlen(buf)+3)*sizeof(char));
1.38 noro 323: if ( strlen(buf) == 1 )
324: strcpy(subs[j],buf);
325: else
326: sprintf(subs[j],"{%s}",buf);
1.37 noro 327: } else
328: subs[j] = "{}";
1.32 noro 329: } else {
330: if ( isdigit(name[i]) )
331: while ( i < len && isdigit(name[i]) ) i++;
332: else
1.40 noro 333: while ( i < len && _is_alpha(name[i]) ) i++;
1.32 noro 334: slen = i-start;
335: buf = (char *)ALLOCA((slen+1)*sizeof(char));
336: strncpy(buf,name+start,slen); buf[slen] = 0;
1.41 noro 337: buf_conv = symbol_name(buf);
338: subs[j] = buf_conv?buf_conv:buf;
1.32 noro 339: }
1.28 noro 340: }
1.32 noro 341: for ( k = 0, clen = 0; k < j; k++ ) clen += strlen(subs[k]);
342: /* {subs(0)}_{{subs(1)},...,{subs(j-1)}} => {}:j+1 _:1 ,:j-2 */
343: h = r = MALLOC_ATOMIC((clen+(j+1)*2+1+(j-2)+1)*sizeof(char));
344: if ( j == 1 )
345: sprintf(h,"{%s}",subs[0]);
1.28 noro 346: else {
1.38 noro 347: sprintf(h,"{%s}_{%s",subs[0],subs[1]);
1.28 noro 348: h += strlen(h);
1.32 noro 349: for ( k = 2; k < j; k++ ) {
1.38 noro 350: sprintf(h,",%s",subs[k]);
1.28 noro 351: h += strlen(h);
1.19 noro 352: }
1.28 noro 353: strcpy(h,"}");
1.20 noro 354: }
355: return r;
1.19 noro 356: }
357:
1.26 noro 358: char *call_convfunc(char *name)
359: {
360: STRING str,r;
361: NODE arg;
362:
363: MKSTR(str,name);
364: arg = mknode(1,str);
365: r = (STRING)bevalf(convfunc,arg);
366: if ( !r || OID(r) != O_STR )
367: error("call_convfunc : invalid result");
368: return BDY(r);
369: }
370:
1.18 noro 371: int register_symbol_table(Obj arg)
372: {
373: NODE n,t;
374: Obj b;
375: STRING a0,a1;
376: struct TeXSymbol *uts;
377: int i,len;
378:
379: /* check */
380: if ( !arg ) {
381: user_texsymbol = 0;
382: return 1;
383: }
384: if ( OID(arg) != O_LIST ) return 0;
385:
386: n = BDY((LIST)arg);
387: len = length(n);
388: uts = (struct TeXSymbol *)MALLOC((len+1)*sizeof(struct TeXSymbol));
389: for ( i = 0; n; n = NEXT(n), i++ ) {
390: b = (Obj)BDY(n);
391: if ( !b || OID(b) != O_LIST ) return 0;
392: t = BDY((LIST)b);
393: if ( !t || !NEXT(t) ) return 0;
394: a0 = (STRING)BDY(t);
395: a1 = (STRING)BDY(NEXT(t));
1.23 noro 396: if ( !a0 ) return 0;
397: if ( OID(a0) == O_STR )
398: uts[i].text = BDY(a0);
399: else if ( OID(a0) == O_P )
400: uts[i].text = NAME(VR((P)a0));
401: else
402: return 0;
403: if ( !a1 ) return 0;
404: if ( OID(a1) == O_STR )
405: uts[i].symbol = BDY(a1);
406: else if ( OID(a1) == O_P )
407: uts[i].symbol = NAME(VR((P)a1));
408: else
409: return 0;
1.18 noro 410: }
411: uts[i].text = 0;
412: uts[i].symbol = 0;
413: user_texsymbol = uts;
414: return 1;
415: }
416:
1.46 noro 417: int register_dp_vars_origin(Obj arg)
418: {
419: if ( INT(arg) ) {
420: dp_vars_origin = QTOS((Q)arg);
421: return 1;
422: } else return 0;
423: }
424:
425: int register_dp_dvars_origin(Obj arg)
426: {
427: if ( INT(arg) ) {
428: dp_dvars_origin = QTOS((Q)arg);
429: return 1;
430: } else return 0;
431: }
432:
1.31 noro 433: int register_dp_vars_hweyl(Obj arg)
434: {
435: if ( INT(arg) ) {
436: dp_vars_hweyl = QTOS((Q)arg);
437: return 1;
438: } else return 0;
439: }
440:
1.27 noro 441: int register_show_lt(Obj arg)
442: {
443: if ( INT(arg) ) {
444: show_lt = QTOS((Q)arg);
445: return 1;
446: } else return 0;
447: }
1.26 noro 448:
1.18 noro 449: int register_conv_rule(Obj arg)
450: {
1.19 noro 451: if ( INT(arg) ) {
1.28 noro 452: conv_flag = QTOS((Q)arg);
453: convfunc = 0;
454: return 1;
1.38 noro 455: } else return 0;
456: }
457:
458: int register_conv_func(Obj arg)
459: {
1.43 noro 460: if ( !arg ) {
461: convfunc = 0;
462: return 1;
463: } else if ( OID(arg) == O_P && (int)(VR((P)arg))->attr == V_SR ) {
1.26 noro 464: convfunc = (FUNC)(VR((P)arg)->priv);
465: /* f must be a function which takes single argument */
466: return 1;
1.19 noro 467: } else return 0;
1.18 noro 468: }
469:
1.23 noro 470: int register_dp_vars(Obj arg)
471: {
472: int l,i;
473: char **r;
474: NODE n;
475: STRING a;
476:
477: if ( !arg ) {
478: dp_vars = 0;
479: dp_vars_len = 0;
1.25 noro 480: return 1;
1.23 noro 481: } else if ( OID(arg) != O_LIST )
482: return 0;
483: else {
484: n = BDY((LIST)arg);
485: l = length(n);
486: r = (char **)MALLOC_ATOMIC(l*sizeof(char *));
487: for ( i = 0; i < l; i++, n = NEXT(n) ) {
488: a = (STRING)BDY(n);
489: if ( !a ) return 0;
490: if ( OID(a) == O_STR )
491: r[i] = BDY(a);
492: else if ( OID(a) == O_P )
493: r[i] = NAME(VR((P)a));
494: else
495: return 0;
496: }
497: dp_vars = r;
498: dp_vars_len = l;
499: return 1;
500: }
501: }
502:
1.25 noro 503: int register_dp_vars_prefix(Obj arg)
504: {
505: if ( !arg ) {
506: dp_vars_prefix = 0;
507: return 1;
508: } else if ( OID(arg) == O_STR ) {
509: dp_vars_prefix = BDY((STRING)arg);
510: return 1;
511: } else if ( OID(arg) == O_P ) {
512: dp_vars_prefix = NAME(VR((P)arg));
513: return 1;
514: } else return 0;
515: }
516:
1.46 noro 517: int register_dp_dvars_prefix(Obj arg)
518: {
519: if ( !arg ) {
520: dp_dvars_prefix = 0;
521: return 1;
522: } else if ( OID(arg) == O_STR ) {
523: dp_dvars_prefix = BDY((STRING)arg);
524: return 1;
525: } else if ( OID(arg) == O_P ) {
526: dp_dvars_prefix = NAME(VR((P)arg));
527: return 1;
528: } else return 0;
529: }
530:
1.24 noro 531: void Pquotetotex_env(NODE arg,Obj *rp)
1.18 noro 532: {
533: int ac,i;
534: char *name;
535: NODE n,n0;
536: STRING s;
537: LIST l;
538:
539: ac = argc(arg);
540: if ( !ac ) {
541: n0 = 0;
542: for ( i = 0; qtot_env[i].name; i++ ) {
543: NEXTNODE(n0,n); MKSTR(s,qtot_env[i].name); BDY(n) = (pointer)s;
544: NEXTNODE(n0,n); BDY(n) = (Q)qtot_env[i].value;
545: }
546: NEXT(n) = 0;
547: MKLIST(l,n0);
548: *rp = (Obj)l;
1.34 noro 549: } else if ( ac == 1 && !ARG0(arg) ) {
550: /* set to default */
1.43 noro 551: for ( i = 0; qtot_env[i].name; i++ ) {
552: (qtot_env[i].reg)(0);
1.34 noro 553: qtot_env[i].value = 0;
1.43 noro 554: }
1.34 noro 555: *rp = 0;
1.18 noro 556: } else if ( ac == 1 || ac == 2 ) {
1.24 noro 557: asir_assert(ARG0(arg),O_STR,"quotetotex_env");
1.18 noro 558: name = BDY((STRING)ARG0(arg));
559: for ( i = 0; qtot_env[i].name; i++ )
560: if ( !strcmp(qtot_env[i].name,name) ) {
561: if ( ac == 2 ) {
562: if ( (qtot_env[i].reg)((Obj)ARG1(arg)) )
563: qtot_env[i].value = (Obj)ARG1(arg);
564: else
1.24 noro 565: error("quotetotex_env : invalid argument");
1.18 noro 566: }
567: *rp = qtot_env[i].value;
568: return;
569: }
570: *rp = 0;
571: } else
572: *rp = 0;
573: }
574:
1.14 noro 575: void Pwrite_to_tb(NODE arg,Q *rp)
1.13 noro 576: {
577: int i;
1.16 noro 578: Obj obj;
579: TB tb;
1.13 noro 580:
1.14 noro 581: asir_assert(ARG1(arg),O_TB,"write_to_tb");
1.16 noro 582: obj = ARG0(arg);
583: if ( !obj )
584: write_tb("",ARG1(arg));
585: else if ( OID(obj) == O_STR )
586: write_tb(BDY((STRING)obj),ARG1(arg));
587: else if ( OID(obj) == O_TB ) {
588: tb = (TB)obj;
589: for ( i = 0; i < tb->next; i++ )
590: write_tb(tb->body[i],ARG1(arg));
591: }
1.14 noro 592: *rp = 0;
1.53 noro 593: }
594:
1.105 noro 595: void Pqt_to_nary(NODE arg,QUOTE *rp)
1.63 noro 596: {
597: FNODE f;
598:
1.70 noro 599: f = fnode_to_nary(BDY((QUOTE)ARG0(arg)));
1.63 noro 600: MKQUOTE(*rp,f);
601: }
602:
1.105 noro 603: void Pqt_to_bin(NODE arg,QUOTE *rp)
1.63 noro 604: {
605: FNODE f;
606: int direction;
607:
608: direction = QTOS((Q)ARG1(arg));
1.70 noro 609: f = fnode_to_bin(BDY((QUOTE)ARG0(arg)),direction);
1.63 noro 610:
611: MKQUOTE(*rp,f);
612: }
1.61 noro 613:
1.108 noro 614: void Pqt_is_var(NODE arg,Q *rp)
615: {
616: QUOTE q;
617: int ret;
618:
619: q = (QUOTE)ARG0(arg);
620: asir_assert(q,O_QUOTE,"qt_is_var");
621: ret = fnode_is_var(BDY(q));
622: STOQ(ret,*rp);
623: }
624:
625: void Pqt_is_coef(NODE arg,Q *rp)
626: {
627: QUOTE q;
628: int ret;
629:
630: q = (QUOTE)ARG0(arg);
631: asir_assert(q,O_QUOTE,"qt_is_coef");
632: ret = fnode_is_coef(BDY(q));
633: STOQ(ret,*rp);
634: }
635:
1.105 noro 636: void Pqt_is_number(NODE arg,Q *rp)
1.69 noro 637: {
638: QUOTE q;
639: int ret;
640:
641: q = (QUOTE)ARG0(arg);
1.105 noro 642: asir_assert(q,O_QUOTE,"qt_is_number");
1.69 noro 643: ret = fnode_is_number(BDY(q));
644: STOQ(ret,*rp);
645: }
646:
1.105 noro 647: void Pqt_is_rational(NODE arg,Q *rp)
1.69 noro 648: {
649: QUOTE q;
650: int ret;
651:
652: q = (QUOTE)ARG0(arg);
1.105 noro 653: asir_assert(q,O_QUOTE,"qt_is_rational");
1.69 noro 654: ret = fnode_is_rational(BDY(q));
655: STOQ(ret,*rp);
656: }
657:
1.105 noro 658: void Pqt_is_integer(NODE arg,Q *rp)
1.69 noro 659: {
660: QUOTE q;
661: int ret;
662:
663: q = (QUOTE)ARG0(arg);
1.105 noro 664: asir_assert(q,O_QUOTE,"qt_is_integer");
1.69 noro 665: ret = fnode_is_integer(BDY(q));
666: STOQ(ret,*rp);
667: }
668:
1.105 noro 669: void Pqt_is_function(NODE arg,Q *rp)
1.69 noro 670: {
671: QUOTE q;
672: int ret;
673:
674: q = (QUOTE)ARG0(arg);
1.105 noro 675: asir_assert(q,O_QUOTE,"qt_is_function");
1.69 noro 676: if ( q->id == I_FUNC || q->id == I_IFUNC )
677: ret = 1;
678: else
679: ret = 0;
680: STOQ(ret,*rp);
681: }
682:
1.105 noro 683: void Pqt_is_dependent(NODE arg,Q *rp)
1.69 noro 684: {
685: P x;
686: QUOTE q,v;
687: int ret;
688: V var;
689:
690: q = (QUOTE)ARG0(arg);
691: v = (QUOTE)ARG1(arg);
1.105 noro 692: asir_assert(q,O_QUOTE,"qt_is_dependent");
693: asir_assert(v,O_QUOTE,"qt_is_dependent");
1.69 noro 694: x = (P)eval(BDY(v));
695: if ( !x || OID(x) != O_P )
696: *rp = 0;
697: var = VR(x);
698: ret = fnode_is_dependent(BDY(q),var);
699: STOQ(ret,*rp);
700: }
701:
702:
1.105 noro 703: void Pqt_match(NODE arg,Q *rp)
1.53 noro 704: {
1.61 noro 705: FNODE f,g;
1.65 noro 706: Obj obj;
1.61 noro 707: QUOTE q;
1.53 noro 708: NODE r;
1.56 noro 709: int ret;
1.53 noro 710:
1.65 noro 711: obj = (Obj)ARG0(arg);
1.105 noro 712: ret = qt_match(obj,(Obj)ARG1(arg),&r);
1.57 noro 713: if ( ret ) {
714: do_assign(r);
715: *rp = ONE;
716: } else
1.56 noro 717: *rp = 0;
1.68 noro 718: }
719:
1.105 noro 720: void Pnqt_match(NODE arg,Q *rp)
1.88 noro 721: {
722: QUOTE fq,pq;
723: FNODE f,p;
724: int ret;
1.104 noro 725: Q mode;
1.88 noro 726: NODE r;
727:
1.104 noro 728: mode = argc(arg)==3 ? (Q)ARG2(arg) : 0;
1.105 noro 729: fq = (QUOTE)ARG0(arg); Pqt_normalize(mknode(2,fq,mode),&fq); f = (FNODE)BDY(fq);
730: pq = (QUOTE)ARG1(arg); Pqt_normalize(mknode(2,pq,mode),&pq); p = (FNODE)BDY(pq);
1.95 noro 731: ret = nfnode_match(f,p,&r);
1.88 noro 732: if ( ret ) {
733: fnode_do_assign(r);
734: *rp = ONE;
735: } else
736: *rp = 0;
737: }
738:
1.106 noro 739: void Pnqt_match_rewrite(NODE arg,Obj *rp)
740: {
741: FNODE f,p,c,a,r;
742: Obj obj,pat,cond,action;
743: NODE rule;
744: QUOTE q;
745: Q mode;
746: int m;
747:
748: obj = (Obj)ARG0(arg);
749: rule = BDY((LIST)ARG1(arg));
750: mode = (Q)ARG2(arg);
751: if ( length(rule) == 2 ) {
752: pat = ARG0(rule);
753: cond = (Obj)ONE;
754: action = (Obj)ARG1(rule);
755: } else {
756: pat = ARG0(rule);
757: cond = ARG1(rule);
758: action = (Obj)ARG2(rule);
759: }
760: Pqt_normalize(mknode(2,obj,mode),&q); f = (FNODE)BDY(q);
761: Pqt_normalize(mknode(2,pat,mode),&q); p = (FNODE)BDY(q);
762: Pqt_normalize(mknode(2,action,mode),&q);
763: a = (FNODE)BDY(q);
764: if ( OID(cond) == O_QUOTE ) c = BDY((QUOTE)cond);
765: else c = mkfnode(1,I_FORMULA,ONE);
766:
767: m = QTOS(mode);
768: r = nfnode_match_rewrite(f,p,c,a,m);
769: if ( r ) {
770: MKQUOTE(q,r);
771: *rp = (Obj)q;
772: } else
773: *rp = obj;
774: }
775:
776: /* f is NARYOP => do submatch */
777:
778: #define PV_ANY 99999999
779:
780: FNODE nfnode_match_rewrite(FNODE f,FNODE p,FNODE c,FNODE a,int mode)
781: {
782: ARF op;
783: NODE arg,h0,t,h,valuen;
784: NODE r,s0,s,pair;
1.107 noro 785: FNODE any,pany,head,tail,a1,a2;
1.106 noro 786: QUOTE q;
787: int ret;
788: FNODE value;
789: int ind;
790:
791: if ( f->id == I_NARYOP ) {
792: op = (ARF)FA0(f);
793: arg = (NODE)FA1(f);
794: pany = 0;
795: for ( h0 = 0, t = arg; t; t = NEXT(t) ) {
796: tail = fnode_node_to_nary(op,t);
797: ret = nfnode_match(tail,p,&r) && eval(rewrite_fnode(c,r,1));
798: if ( ret ) break;
799:
800: /* append a variable to the pattern */
801: if ( !pany ) {
802: any = mkfnode(1,I_PVAR,PV_ANY);
803: pany = mkfnode(3,I_BOP,op,p,any);
804: pany = fnode_normalize(pany,mode);
805: }
806: ret = nfnode_match(tail,pany,&r) && eval(rewrite_fnode(c,r,1));
807: if ( ret ) {
808: a = fnode_normalize(mkfnode(3,I_BOP,op,a,any),mode);
809: break;
810: }
811:
812: NEXTNODE(h0,h);
813: BDY(h) = BDY(t);
814: }
815: if ( t ) {
816: if ( h0 ) NEXT(h) = 0;
817: head = fnode_node_to_nary(op,h0);
818: a = fnode_normalize(mkfnode(3,I_BOP,op,head,a),mode);
819: ret = 1;
820: } else
821: ret = 0;
822: } else
823: ret = nfnode_match(f,p,&r) && eval(rewrite_fnode(c,r,1));
824:
825: if ( ret ) {
1.107 noro 826: a1 = rewrite_fnode(a,r,0);
827: a2 = partial_eval(a1);
828: return fnode_normalize(a2,mode);
1.106 noro 829: } else
830: return 0;
831: }
832:
1.56 noro 833: void do_assign(NODE arg)
834: {
835: NODE t,pair;
836: int pv;
837:
838: QUOTE value;
839:
840: for ( t = arg; t; t = NEXT(t) ) {
841: pair = BDY((LIST)BDY(t));
842: pv = (int)FA0((FNODE)BDY((QUOTE)BDY(pair)));
843: value = (QUOTE)(BDY(NEXT(pair)));
844: ASSPV(pv,value);
845: }
1.53 noro 846: }
847:
1.88 noro 848: /* [[index,fnode],...] */
849:
850: void fnode_do_assign(NODE arg)
851: {
852: NODE t,pair;
853: int pv;
854: FNODE f;
855: QUOTE value;
1.95 noro 856: QUOTEARG qa;
1.88 noro 857:
858: for ( t = arg; t; t = NEXT(t) ) {
859: pair = (NODE)BDY(t);
860: pv = (int)BDY(pair);
861: f = (FNODE)(BDY(NEXT(pair)));
1.96 noro 862: if ( f->id == I_FUNC_HEAD ) {
863: /* XXX : I_FUNC_HEAD is a dummy id to pass FUNC */
1.95 noro 864: MKQUOTEARG(qa,A_func,FA0(f));
865: value = (QUOTE)qa;
866: } else
867: MKQUOTE(value,f);
1.88 noro 868: ASSPV(pv,value);
869: }
870: }
871:
1.53 noro 872: /*
1.56 noro 873: /* consistency check and merge
874: */
1.53 noro 875:
1.56 noro 876: int merge_matching_node(NODE n,NODE a,NODE *rp)
1.53 noro 877: {
878: NODE ta,ba,tn,bn;
879: QUOTE pa,va,pn,vn;
880:
1.56 noro 881: if ( !n ) {
882: *rp = a;
883: return 1;
884: }
1.53 noro 885: for ( ta = a; ta; ta = NEXT(ta) ) {
886: ba = BDY((LIST)BDY(ta));
1.55 noro 887: if ( !ba ) continue;
1.53 noro 888: pa = (QUOTE)BDY(ba); va = (QUOTE)BDY(NEXT(ba));
889: for ( tn = n; tn; tn = NEXT(tn) ) {
890: bn = BDY((LIST)BDY(tn));
1.55 noro 891: if ( !bn ) continue;
1.53 noro 892: pn = (QUOTE)BDY(bn); vn = (QUOTE)BDY(NEXT(bn));
1.55 noro 893: if ( !compquote(CO,pa,pn) ) {
894: if ( !compquote(CO,va,vn) ) break;
895: else return 0;
896: }
1.53 noro 897: }
898: if ( !tn ) {
899: MKNODE(tn,(pointer)BDY(ta),n);
900: n = tn;
901: }
902: }
1.56 noro 903: *rp = n;
904: return 1;
1.53 noro 905: }
906:
1.105 noro 907: int qt_match_node(NODE f,NODE pat,NODE *rp) {
1.56 noro 908: NODE r,a,tf,tp,r1;
909: int ret;
1.53 noro 910:
911: if ( length(f) != length(pat) ) return 0;
912: r = 0;
913: for ( tf = f, tp = pat; tf; tf = NEXT(tf), tp = NEXT(tp) ) {
1.105 noro 914: ret = qt_match((Obj)BDY(tf),(Obj)BDY(tp),&a);
1.56 noro 915: if ( !ret ) return 0;
916: ret = merge_matching_node(r,a,&r1);
917: if ( !ret ) return 0;
918: else r = r1;
1.53 noro 919: }
1.56 noro 920: *rp = r;
921: return 1;
1.53 noro 922: }
923:
1.66 noro 924: /* f = [a,b,c,...] pat = [X,Y,...] rpat matches the rest of f */
925:
1.105 noro 926: int qt_match_cons(NODE f,NODE pat,Obj rpat,NODE *rp) {
1.66 noro 927: QUOTE q;
928: Q id;
929: FNODE fn;
930: NODE r,a,tf,tp,r1,arg;
931: int ret;
932: LIST list,alist;
933:
934: /* matching of the head part */
935: if ( length(f) < length(pat) ) return 0;
936: r = 0;
937: for ( tf = f, tp = pat; tp; tf = NEXT(tf), tp = NEXT(tp) ) {
1.105 noro 938: ret = qt_match((Obj)BDY(tf),(Obj)BDY(tp),&a);
1.66 noro 939: if ( !ret ) return 0;
940: ret = merge_matching_node(r,a,&r1);
941: if ( !ret ) return 0;
942: else r = r1;
943: }
944: /* matching of the rest */
945: MKLIST(list,tf);
946: STOQ(I_LIST,id); a = mknode(2,id,list);
947: MKLIST(alist,a);
948: arg = mknode(1,alist);
949: Pfunargs_to_quote(arg,&q);
1.105 noro 950: ret = qt_match((Obj)q,rpat,&a);
1.66 noro 951: if ( !ret ) return 0;
952: ret = merge_matching_node(r,a,&r1);
953: if ( !ret ) return 0;
954: *rp = r1;
955: return 1;
956: }
957:
1.53 noro 958: void get_quote_id_arg(QUOTE f,int *id,NODE *r)
959: {
960: LIST fa;
961: NODE arg,fab;
962:
963: arg = mknode(1,f); Pquote_to_funargs(arg,&fa); fab = BDY((LIST)fa);
964: *id = QTOS((Q)BDY(fab)); *r = NEXT(fab);
965: }
966:
1.56 noro 967: /* *rp : [[quote(A),quote(1)],...] */
1.53 noro 968:
1.105 noro 969: int qt_match(Obj f, Obj pat, NODE *rp)
1.53 noro 970: {
971: NODE tf,tp,head,body;
972: NODE parg,farg,r;
1.66 noro 973: Obj rpat;
1.53 noro 974: LIST fa,l;
975: int pid,id;
1.55 noro 976: FUNC ff,pf;
1.56 noro 977: int ret;
1.64 noro 978: QUOTE q;
979: FNODE g;
1.53 noro 980:
1.67 noro 981: if ( !f )
982: if ( !pat ) {
983: *rp = 0; return 1;
984: } else
985: return 0;
986: else if ( OID(pat) == O_LIST ) {
1.53 noro 987: if ( OID(f) == O_LIST )
1.105 noro 988: return qt_match_node(BDY((LIST)f),BDY((LIST)pat),rp);
1.53 noro 989: else
990: return 0;
991: } else if ( OID(pat) == O_QUOTE ) {
1.67 noro 992: pid = ((FNODE)BDY((QUOTE)pat))->id;
1.53 noro 993: switch ( pid ) {
1.55 noro 994: case I_FORMULA:
995: if ( compquote(CO,f,pat) )
996: return 0;
997: else {
1.67 noro 998: *rp = 0; return 1;
1.55 noro 999: }
1000: break;
1.67 noro 1001:
1002: case I_LIST: case I_CONS:
1003: get_quote_id_arg((QUOTE)pat,&pid,&parg);
1004: if ( OID(f) == O_LIST )
1005: tf = BDY((LIST)f);
1006: else if ( OID(f) == O_QUOTE
1007: && ((FNODE)BDY((QUOTE)f))->id == pid ) {
1008: get_quote_id_arg((QUOTE)f,&id,&farg);
1009: tf = BDY((LIST)BDY(farg));
1010: } else
1011: return 0;
1012:
1.66 noro 1013: tp = BDY((LIST)BDY(parg));
1.67 noro 1014: if ( pid == I_LIST )
1.105 noro 1015: return qt_match_node(tf,tp,rp);
1.67 noro 1016: else {
1017: rpat = (Obj)BDY(NEXT(parg));
1.105 noro 1018: return qt_match_cons(tf,tp,rpat,rp);
1.67 noro 1019: }
1020:
1.53 noro 1021: case I_PVAR:
1022: /* [[pat,f]] */
1023: r = mknode(2,pat,f); MKLIST(l,r);
1.56 noro 1024: *rp = mknode(1,l);
1025: return 1;
1.67 noro 1026:
1.53 noro 1027: case I_IFUNC:
1028: /* F(X,Y,...) = ... */
1.67 noro 1029: get_quote_id_arg((QUOTE)f,&id,&farg);
1030: get_quote_id_arg((QUOTE)pat,&pid,&parg);
1.53 noro 1031: if ( id == I_FUNC ) {
1.54 noro 1032: r = mknode(2,BDY(parg),BDY(farg)); MKLIST(l,r);
1033: head = mknode(1,l);
1.105 noro 1034: ret = qt_match(BDY(NEXT(farg)),
1.56 noro 1035: BDY(NEXT(parg)),&body);
1036: if ( !ret ) return 0;
1037: else return merge_matching_node(head,body,rp);
1.53 noro 1038: } else
1039: return 0;
1.64 noro 1040:
1.67 noro 1041: case I_NARYOP: case I_BOP: case I_FUNC:
1.64 noro 1042: /* X+Y = ... */
1.67 noro 1043: /* f(...) = ... */
1044: if ( OID(f) != O_QUOTE ) return 0;
1045: id = ((FNODE)BDY((QUOTE)f))->id;
1046: if ( pid == I_FUNC )
1047: ;
1048: else {
1049: /* XXX converting to I_BOP */
1050: if ( pid == I_NARYOP ) {
1.70 noro 1051: g = fnode_to_bin(BDY((QUOTE)pat),1);
1.67 noro 1052: MKQUOTE(q,g); pat = (Obj)q;
1053: }
1054: if ( id == I_NARYOP ) {
1.70 noro 1055: g = fnode_to_bin(BDY((QUOTE)f),1);
1.67 noro 1056: MKQUOTE(q,g); f = (Obj)q;
1057: }
1058: }
1059: get_quote_id_arg((QUOTE)pat,&pid,&parg);
1060: get_quote_id_arg((QUOTE)f,&id,&farg);
1.64 noro 1061: if ( compqa(CO,BDY(farg),BDY(parg)) ) return 0;
1.105 noro 1062: return qt_match_node(NEXT(farg),NEXT(parg),rp);
1.64 noro 1063:
1.53 noro 1064: default:
1.67 noro 1065: if ( OID(f) != O_QUOTE ) return 0;
1066: id = ((FNODE)BDY((QUOTE)f))->id;
1067: if ( id != pid ) return 0;
1068: get_quote_id_arg((QUOTE)pat,&pid,&parg);
1069: get_quote_id_arg((QUOTE)f,&id,&farg);
1.105 noro 1070: return qt_match_node(farg,parg,rp);
1.53 noro 1071: }
1072: }
1.13 noro 1073: }
1074:
1.14 noro 1075: void Pquotetotex(NODE arg,STRING *rp)
1.13 noro 1076: {
1.14 noro 1077: TB tb;
1.13 noro 1078:
1.14 noro 1079: NEWTB(tb);
1.27 noro 1080: /* XXX for DP */
1081: is_lt = 1;
1.14 noro 1082: fnodetotex_tb(BDY((QUOTE)ARG0(arg)),tb);
1083: tb_to_string(tb,rp);
1.13 noro 1084: }
1085:
1.14 noro 1086: void Pquotetotex_tb(NODE arg,Q *rp)
1.13 noro 1087: {
1088: int i;
1.14 noro 1089: TB tb;
1.13 noro 1090:
1.14 noro 1091: asir_assert(ARG1(arg),O_TB,"quotetotex_tb");
1.27 noro 1092: /* XXX for DP */
1093: is_lt = 1;
1.14 noro 1094: fnodetotex_tb(BDY((QUOTE)ARG0(arg)),ARG1(arg));
1.13 noro 1095: *rp = 0;
1096: }
1097:
1.14 noro 1098: void Pstring_to_tb(NODE arg,TB *rp)
1099: {
1100: TB tb;
1101:
1102: asir_assert(ARG0(arg),O_STR,"string_to_tb");
1103: NEWTB(tb);
1104: tb->body[0] = BDY((STRING)ARG0(arg));
1105: tb->next++;
1106: *rp = tb;
1107: }
1108:
1109: void Ptb_to_string(NODE arg,STRING *rp)
1110: {
1111: TB tb;
1112:
1113: asir_assert(ARG0(arg),O_TB,"tb_to_string");
1114: tb = (TB)ARG0(arg);
1115: tb_to_string(tb,rp);
1116: }
1117:
1118: void tb_to_string(TB tb,STRING *rp)
1.13 noro 1119: {
1.14 noro 1120: int j,len;
1.13 noro 1121: char *all,*p,*q;
1122:
1.14 noro 1123: for ( j = 0, len = 0; j < tb->next; j++ )
1124: len += strlen(tb->body[j]);
1125: all = (char *)MALLOC_ATOMIC((len+1)*sizeof(char));
1126: for ( j = 0, p = all; j < tb->next; j++ )
1127: for ( q = tb->body[j]; *q; *p++ = *q++ );
1128: *p = 0;
1129: MKSTR(*rp,all);
1130: }
1131:
1132: void Pclear_tb(NODE arg,Q *rp)
1133: {
1134: TB tb;
1135: int j;
1136:
1137: asir_assert(ARG0(arg),O_TB,"clear_tb");
1138: tb = (TB)ARG0(arg);
1139: for ( j = 0; j < tb->next; j++ )
1140: tb->body[j] = 0;
1141: tb->next = 0;
1142: *rp = 0;
1.13 noro 1143: }
1.5 noro 1144:
1145: void Pstr_len(arg,rp)
1146: NODE arg;
1147: Q *rp;
1148: {
1.16 noro 1149: Obj obj;
1150: TB tb;
1151: int r,i;
1.5 noro 1152:
1.16 noro 1153: obj = (Obj)ARG0(arg);
1154: if ( !obj || (OID(obj) != O_STR && OID(obj) != O_TB) )
1155: error("str_len : invalid argument");
1156: if ( OID(obj) == O_STR)
1157: r = strlen(BDY((STRING)obj));
1158: else if ( OID(obj) == O_TB ) {
1159: tb = (TB)obj;
1160: for ( r = i = 0; i < tb->next; i++ )
1161: r += strlen(tb->body[i]);
1162: }
1.5 noro 1163: STOQ(r,*rp);
1164: }
1165:
1166: void Pstr_chr(arg,rp)
1167: NODE arg;
1168: Q *rp;
1169: {
1170: STRING str,terminator;
1171: Q start;
1172: char *p,*ind;
1173: int chr,spos,r;
1174:
1175: str = (STRING)ARG0(arg);
1176: start = (Q)ARG1(arg);
1177: terminator = (STRING)ARG2(arg);
1178: asir_assert(str,O_STR,"str_chr");
1179: asir_assert(start,O_N,"str_chr");
1180: asir_assert(terminator,O_STR,"str_chr");
1181: p = BDY(str);
1182: spos = QTOS(start);
1183: chr = BDY(terminator)[0];
1.8 noro 1184: if ( spos > (int)strlen(p) )
1.5 noro 1185: r = -1;
1186: else {
1187: ind = strchr(p+spos,chr);
1188: if ( ind )
1189: r = ind-p;
1190: else
1191: r = -1;
1192: }
1193: STOQ(r,*rp);
1194: }
1195:
1196: void Psub_str(arg,rp)
1197: NODE arg;
1198: STRING *rp;
1199: {
1200: STRING str;
1201: Q head,tail;
1202: char *p,*r;
1203: int spos,epos,len;
1204:
1205: str = (STRING)ARG0(arg);
1206: head = (Q)ARG1(arg);
1207: tail = (Q)ARG2(arg);
1208: asir_assert(str,O_STR,"sub_str");
1209: asir_assert(head,O_N,"sub_str");
1210: asir_assert(tail,O_N,"sub_str");
1211: p = BDY(str);
1212: spos = QTOS(head);
1213: epos = QTOS(tail);
1214: len = strlen(p);
1215: if ( (spos >= len) || (epos < spos) ) {
1216: *rp = 0; return;
1217: }
1218: if ( epos >= len )
1219: epos = len-1;
1220: len = epos-spos+1;
1221: r = (char *)MALLOC(len+1);
1222: strncpy(r,p+spos,len);
1223: r[len] = 0;
1224: MKSTR(*rp,r);
1225: }
1.3 noro 1226:
1227: void Pstrtoascii(arg,rp)
1228: NODE arg;
1229: LIST *rp;
1230: {
1231: STRING str;
1232: unsigned char *p;
1233: int len,i;
1234: NODE n,n1;
1235: Q q;
1236:
1237: str = (STRING)ARG0(arg);
1238: asir_assert(str,O_STR,"strtoascii");
1239: p = BDY(str);
1240: len = strlen(p);
1241: for ( i = len-1, n = 0; i >= 0; i-- ) {
1242: UTOQ((unsigned int)p[i],q);
1243: MKNODE(n1,q,n);
1244: n = n1;
1245: }
1246: MKLIST(*rp,n);
1247: }
1248:
1249: void Pasciitostr(arg,rp)
1250: NODE arg;
1251: STRING *rp;
1252: {
1253: LIST list;
1254: unsigned char *p;
1255: int len,i,j;
1256: NODE n;
1257: Q q;
1258:
1259: list = (LIST)ARG0(arg);
1260: asir_assert(list,O_LIST,"asciitostr");
1261: n = BDY(list);
1262: len = length(n);
1263: p = MALLOC_ATOMIC(len+1);
1264: for ( i = 0; i < len; i++, n = NEXT(n) ) {
1265: q = (Q)BDY(n);
1266: asir_assert(q,O_N,"asciitostr");
1267: j = QTOS(q);
1.4 noro 1268: if ( j >= 256 || j <= 0 )
1.3 noro 1269: error("asciitostr : argument out of range");
1270: p[i] = j;
1271: }
1272: p[i] = 0;
1273: MKSTR(*rp,(char *)p);
1274: }
1.1 noro 1275:
1276: void Peval_str(arg,rp)
1277: NODE arg;
1278: Obj *rp;
1279: {
1280: FNODE fnode;
1281: char *cmd;
1.10 ohara 1282: #if defined(PARI)
1.8 noro 1283: void recover(int);
1284:
1.1 noro 1285: recover(0);
1.11 saito 1286: # if !(PARI_VERSION_CODE > 131588)
1.1 noro 1287: if ( setjmp(environnement) ) {
1288: avma = top; recover(1);
1289: resetenv("");
1290: }
1.11 saito 1291: # endif
1.1 noro 1292: #endif
1293: cmd = BDY((STRING)ARG0(arg));
1.9 noro 1294: exprparse_create_var(0,cmd,&fnode);
1.1 noro 1295: *rp = eval(fnode);
1296: }
1297:
1298: void Prtostr(arg,rp)
1299: NODE arg;
1300: STRING *rp;
1301: {
1302: char *b;
1303: int len;
1304:
1.2 noro 1305: len = estimate_length(CO,ARG0(arg));
1.12 noro 1306: b = (char *)MALLOC_ATOMIC(len+1);
1.1 noro 1307: soutput_init(b);
1308: sprintexpr(CO,ARG0(arg));
1309: MKSTR(*rp,b);
1310: }
1311:
1312: void Pstrtov(arg,rp)
1313: NODE arg;
1314: P *rp;
1315: {
1.8 noro 1316: char *p;
1.1 noro 1317:
1318: p = BDY((STRING)ARG0(arg));
1319: #if 0
1320: if ( !islower(*p) )
1321: *rp = 0;
1322: else {
1323: for ( t = p+1; t && (isalnum(*t) || *t == '_'); t++ );
1324: if ( *t )
1325: *rp = 0;
1326: else
1327: makevar(p,rp);
1328: }
1329: #else
1330: makevar(p,rp);
1331: #endif
1.14 noro 1332: }
1333:
1.15 noro 1334: static struct TeXSymbol texsymbol[] = {
1335: {"sin","\\sin"},
1336: {"cos","\\cos"},
1337: {"tan","\\tan"},
1338: {"sinh","\\sinh"},
1339: {"cosh","\\cosh"},
1340: {"tanh","\\tanh"},
1341: {"exp","\\exp"},
1342: {"log","\\log"},
1343:
1344: /* Greek Letters (lower case) */
1345: {"alpha","\\alpha"},
1346: {"beta","\\beta"},
1347: {"gamma","\\gamma"},
1348: {"delta","\\delta"},
1349: {"epsilon","\\epsilon"},
1350: {"varepsilon","\\varepsilon"},
1351: {"zeta","\\zeta"},
1352: {"eta","\\eta"},
1353: {"theta","\\theta"},
1354: {"vartheta","\\vartheta"},
1355: {"iota","\\iota"},
1356: {"kappa","\\kappa"},
1357: {"lambda","\\lambda"},
1358: {"mu","\\mu"},
1359: {"nu","\\nu"},
1360: {"xi","\\xi"},
1361: {"pi","\\pi"},
1362: {"varpi","\\varpi"},
1363: {"rho","\\rho"},
1364: {"sigma","\\sigma"},
1365: {"varsigma","\\varsigma"},
1366: {"tau","\\tau"},
1367: {"upsilon","\\upsilon"},
1368: {"phi","\\phi"},
1369: {"varphi","\\varphi"},
1370: {"chi","\\chi"},
1371: {"omega","\\omega"},
1372:
1373: /* Greek Letters, (upper case) */
1374: {"ggamma","\\Gamma"},
1375: {"ddelta","\\Delta"},
1376: {"ttheta","\\Theta"},
1377: {"llambda","\\Lambda"},
1378: {"xxi","\\Xi"},
1379: {"ppi","\\Pi"},
1380: {"ssigma","\\Sigma"},
1381: {"uupsilon","\\Upsilon"},
1382: {"pphi","\\Phi"},
1383: {"ppsi","\\Psi"},
1384: {"oomega","\\Omega"},
1385:
1386: /* Our own mathematical functions */
1387: {"algebra_tensor","\\otimes"},
1388: {"base_where","{\\rm \\ where \\ }"},
1389: /* Mathematical constants */
1390: {"c_pi","\\pi"},
1391: {"c_i","\\sqrt{-1}"},
1392:
1393: /* Temporary */
1394: {0,0}
1395: };
1396:
1.14 noro 1397: char *symbol_name(char *name)
1398: {
1.15 noro 1399: int i;
1400:
1.41 noro 1401: if ( !name || strlen(name) == 0 )
1402: return "";
1.38 noro 1403: if ( !(conv_flag & CONV_TABLE) )
1404: return name;
1405:
1.18 noro 1406: if ( user_texsymbol )
1407: for ( i = 0; user_texsymbol[i].text; i++ )
1408: if ( !strcmp(user_texsymbol[i].text,name) )
1409: return user_texsymbol[i].symbol;
1.15 noro 1410: for ( i = 0; texsymbol[i].text; i++ )
1411: if ( !strcmp(texsymbol[i].text,name) )
1412: return texsymbol[i].symbol;
1.41 noro 1413: return 0;
1.52 noro 1414: }
1415:
1416: void Pget_function_name(NODE arg,STRING *rp)
1417: {
1418: QUOTEARG qa;
1419: ARF f;
1420: char *opname;
1421:
1422: qa = (QUOTEARG)BDY(arg);
1423: if ( !qa || OID(qa) != O_QUOTEARG || qa->type != A_arf )
1424: *rp = 0;
1425: else {
1426: f = (ARF)BDY(qa);
1427: opname = f->name;
1428: MKSTR(*rp,opname);
1429: }
1.14 noro 1430: }
1431:
1.51 noro 1432: FNODE strip_paren(FNODE);
1433:
1.14 noro 1434: void fnodetotex_tb(FNODE f,TB tb)
1435: {
1.91 noro 1436: NODE n,t,t0,args;
1.38 noro 1437: char vname[BUFSIZ],prefix[BUFSIZ];
1438: char *opname,*vname_conv,*prefix_conv;
1.14 noro 1439: Obj obj;
1.46 noro 1440: int i,len,allzero,elen,elen2,si;
1.40 noro 1441: C cplx;
1442: char *r;
1.91 noro 1443: FNODE fi,f2,f1;
1.14 noro 1444:
1445: write_tb(" ",tb);
1446: if ( !f ) {
1447: write_tb("0",tb);
1448: return;
1449: }
1450: switch ( f->id ) {
1451: /* unary operators */
1.23 noro 1452: case I_NOT:
1453: write_tb("\\neg (",tb);
1454: fnodetotex_tb((FNODE)FA0(f),tb);
1455: write_tb(")",tb);
1456: break;
1457: case I_PAREN:
1458: write_tb("(",tb);
1459: fnodetotex_tb((FNODE)FA0(f),tb);
1460: write_tb(")",tb);
1461: break;
1462: case I_MINUS:
1463: write_tb("-",tb);
1464: fnodetotex_tb((FNODE)FA0(f),tb);
1465: break;
1466:
1467: /* binary operators */
1468: /* arg list */
1469: /* I_AND, I_OR => FA0(f), FA1(f) */
1470: /* otherwise => FA1(f), FA2(f) */
1471: case I_BOP:
1472: opname = ((ARF)FA0(f))->name;
1.70 noro 1473: switch ( opname[0] ) {
1474: case '+':
1475: fnodetotex_tb((FNODE)FA1(f),tb);
1476: if ( !top_is_minus((FNODE)FA2(f)) ) write_tb(opname,tb);
1477: fnodetotex_tb((FNODE)FA2(f),tb);
1478: break;
1479: case '-':
1480: if ( FA1(f) ) fnodetotex_tb((FNODE)FA1(f),tb);
1481: write_tb(opname,tb);
1482: fnodetotex_tb((FNODE)FA2(f),tb);
1483: break;
1484: case '*':
1485: fnodetotex_tb((FNODE)FA1(f),tb);
1486: write_tb(" ",tb);
1487: /* XXX special care for DP */
1488: f2 = (FNODE)FA2(f);
1489: if ( f2->id == I_EV ) {
1490: n = (NODE)FA0(f2);
1491: for ( i = 0; n; n = NEXT(n), i++ ) {
1492: fi = (FNODE)BDY(n);
1493: if ( fi->id != I_FORMULA || FA0(fi) )
1494: break;
1495: }
1496: if ( n )
1497: fnodetotex_tb((FNODE)FA2(f),tb);
1498: } else
1.23 noro 1499: fnodetotex_tb((FNODE)FA2(f),tb);
1.70 noro 1500: break;
1501: case '/':
1502: write_tb("\\frac{",tb);
1503: fnodetotex_tb((FNODE)FA1(f),tb);
1504: write_tb("} {",tb);
1505: fnodetotex_tb((FNODE)FA2(f),tb);
1506: write_tb("}",tb);
1507: break;
1508: case '^':
1509: fnodetotex_tb((FNODE)FA1(f),tb);
1510: write_tb("^{",tb);
1511: fnodetotex_tb(strip_paren((FNODE)FA2(f)),tb);
1512: write_tb("} ",tb);
1513: break;
1514: case '%':
1515: fnodetotex_tb((FNODE)FA1(f),tb);
1516: write_tb(" {\\rm mod}\\, ",tb);
1.23 noro 1517: fnodetotex_tb((FNODE)FA2(f),tb);
1.70 noro 1518: break;
1519: default:
1520: error("invalid binary operator");
1521: break;
1522: }
1.23 noro 1523: break;
1.91 noro 1524: case I_NARYOP:
1525: args = (NODE)FA1(f);
1526: write_tb("(",tb);
1527: switch ( OPNAME(f) ) {
1528: case '+':
1529: fnodetotex_tb((FNODE)BDY(args),tb);
1530: for ( args = NEXT(args); args; args = NEXT(args) ) {
1531: write_tb("+",tb);
1532: fnodetotex_tb((FNODE)BDY(args),tb);
1533: }
1534: break;
1535: case '*':
1536: f1 = (FNODE)BDY(args);
1537: if ( f1->id == I_FORMULA && MUNIQ(FA0(f1)) )
1538: write_tb("-",tb);
1539: else
1540: fnodetotex_tb(f1,tb);
1541: write_tb(" ",tb);
1542: for ( args = NEXT(args); args; args = NEXT(args) ) {
1543: /* XXX special care for DP */
1544: f2 = (FNODE)BDY(args);
1545: if ( f2->id == I_EV ) {
1546: n = (NODE)FA0(f2);
1547: for ( i = 0; n; n = NEXT(n), i++ ) {
1548: fi = (FNODE)BDY(n);
1549: if ( fi->id != I_FORMULA || FA0(fi) )
1550: break;
1551: }
1552: if ( n )
1553: fnodetotex_tb(f2,tb);
1554: } else
1555: fnodetotex_tb(f2,tb);
1556: }
1557: break;
1558: default:
1559: error("invalid nary op");
1560: break;
1561: }
1562: write_tb(")",tb);
1563: break;
1.23 noro 1564:
1565: case I_COP:
1566: switch( (cid)FA0(f) ) {
1567: case C_EQ:
1568: fnodetotex_tb((FNODE)FA1(f),tb);
1569: write_tb(" = ",tb);
1570: fnodetotex_tb((FNODE)FA2(f),tb);
1571: break;
1572: case C_NE:
1573: fnodetotex_tb((FNODE)FA1(f),tb);
1574: write_tb(" \\neq ",tb);
1575: fnodetotex_tb((FNODE)FA2(f),tb);
1576: break;
1577: case C_GT:
1578: fnodetotex_tb((FNODE)FA1(f),tb);
1.45 noro 1579: write_tb(" > ",tb);
1.23 noro 1580: fnodetotex_tb((FNODE)FA2(f),tb);
1581: break;
1582: case C_LT:
1583: fnodetotex_tb((FNODE)FA1(f),tb);
1.45 noro 1584: write_tb(" < ",tb);
1.23 noro 1585: fnodetotex_tb((FNODE)FA2(f),tb);
1.14 noro 1586: break;
1.23 noro 1587: case C_GE:
1588: fnodetotex_tb((FNODE)FA1(f),tb);
1589: write_tb(" \\geq ",tb);
1590: fnodetotex_tb((FNODE)FA2(f),tb);
1.14 noro 1591: break;
1.23 noro 1592: case C_LE:
1593: fnodetotex_tb((FNODE)FA1(f),tb);
1594: write_tb(" \\leq ",tb);
1595: fnodetotex_tb((FNODE)FA2(f),tb);
1.14 noro 1596: break;
1597: }
1598: break;
1599:
1.23 noro 1600: case I_LOP:
1601: switch( (lid)FA0(f) ) {
1602: case L_EQ:
1603: fnodetotex_tb((FNODE)FA1(f),tb);
1604: write_tb(" = ",tb);
1605: fnodetotex_tb((FNODE)FA2(f),tb);
1606: break;
1607: case L_NE:
1608: fnodetotex_tb((FNODE)FA1(f),tb);
1609: write_tb(" \\neq ",tb);
1610: fnodetotex_tb((FNODE)FA2(f),tb);
1611: break;
1612: case L_GT:
1613: fnodetotex_tb((FNODE)FA1(f),tb);
1.45 noro 1614: write_tb(" > ",tb);
1.23 noro 1615: fnodetotex_tb((FNODE)FA2(f),tb);
1616: break;
1617: case L_LT:
1618: fnodetotex_tb((FNODE)FA1(f),tb);
1.45 noro 1619: write_tb(" < ",tb);
1.23 noro 1620: fnodetotex_tb((FNODE)FA2(f),tb);
1621: break;
1622: case L_GE:
1623: fnodetotex_tb((FNODE)FA1(f),tb);
1624: write_tb(" \\geq ",tb);
1625: fnodetotex_tb((FNODE)FA2(f),tb);
1.14 noro 1626: break;
1.23 noro 1627: case L_LE:
1628: fnodetotex_tb((FNODE)FA1(f),tb);
1629: write_tb(" \\leq ",tb);
1630: fnodetotex_tb((FNODE)FA2(f),tb);
1.14 noro 1631: break;
1.23 noro 1632: case L_AND:
1633: fnodetotex_tb((FNODE)FA1(f),tb);
1.14 noro 1634: write_tb(" {\\rm \\ and\\ } ",tb);
1.23 noro 1635: fnodetotex_tb((FNODE)FA2(f),tb);
1636: break;
1637: case L_OR:
1.14 noro 1638: fnodetotex_tb((FNODE)FA1(f),tb);
1.23 noro 1639: write_tb(" {\\rm \\ or\\ } ",tb);
1640: fnodetotex_tb((FNODE)FA2(f),tb);
1.14 noro 1641: break;
1.23 noro 1642: case L_NOT:
1643: /* XXX : L_NOT is a unary operator */
1644: write_tb("\\neg (",tb);
1.14 noro 1645: fnodetotex_tb((FNODE)FA1(f),tb);
1.23 noro 1646: write_tb(")",tb);
1647: return;
1.14 noro 1648: }
1649: break;
1650:
1.23 noro 1651: case I_AND:
1652: fnodetotex_tb((FNODE)FA0(f),tb);
1653: write_tb(" {\\rm \\ and\\ } ",tb);
1654: fnodetotex_tb((FNODE)FA1(f),tb);
1655: break;
1656:
1657: case I_OR:
1658: fnodetotex_tb((FNODE)FA0(f),tb);
1659: write_tb(" {\\rm \\ or\\ } ",tb);
1660: fnodetotex_tb((FNODE)FA1(f),tb);
1661: break;
1662:
1.14 noro 1663: /* ternary operators */
1664: case I_CE:
1665: error("fnodetotex_tb : not implemented yet");
1666: break;
1667:
1668: /* lists */
1669: case I_LIST:
1670: write_tb(" [ ",tb);
1671: n = (NODE)FA0(f);
1672: fnodenodetotex_tb(n,tb);
1673: write_tb("]",tb);
1674: break;
1675:
1676: /* function */
1.23 noro 1677: case I_FUNC:
1.40 noro 1678: if ( !strcmp(((FUNC)FA0(f))->name,"@pi") )
1679: write_tb("\\pi",tb);
1680: else if ( !strcmp(((FUNC)FA0(f))->name,"@e") )
1681: write_tb("e",tb);
1682: else {
1683: opname = conv_rule(((FUNC)FA0(f))->name);
1684: write_tb(opname,tb);
1685: write_tb("(",tb);
1686: fargstotex_tb(opname,FA1(f),tb);
1687: write_tb(")",tb);
1688: }
1.23 noro 1689: break;
1690:
1691: /* XXX */
1692: case I_CAR:
1.28 noro 1693: opname = conv_rule("car");
1.23 noro 1694: write_tb(opname,tb);
1695: write_tb("(",tb);
1696: fargstotex_tb(opname,FA0(f),tb);
1697: write_tb(")",tb);
1698: break;
1699:
1700: case I_CDR:
1.28 noro 1701: opname = conv_rule("cdr");
1.23 noro 1702: write_tb(opname,tb);
1703: write_tb("(",tb);
1704: fargstotex_tb(opname,FA0(f),tb);
1705: write_tb(")",tb);
1706: break;
1707:
1708: /* exponent vector */
1709: case I_EV:
1710: n = (NODE)FA0(f);
1.31 noro 1711: if ( dp_vars_hweyl ) {
1712: elen = length(n);
1713: elen2 = elen>>1;
1714: elen = elen2<<1;
1715: }
1.23 noro 1716: allzero = 1;
1.27 noro 1717: if ( show_lt && is_lt )
1718: write_tb("\\underline{",tb);
1.23 noro 1719: for ( t0 = 0, i = 0; n; n = NEXT(n), i++ ) {
1720: fi = (FNODE)BDY(n);
1721: if ( fi->id == I_FORMULA && !FA0(fi) ) continue;
1722: allzero = 0;
1.38 noro 1723: if ( dp_vars && i < dp_vars_len ) {
1724: strcpy(vname,dp_vars[i]);
1725: vname_conv = conv_rule(vname);
1726: } else {
1727: if ( dp_vars_hweyl ) {
1.44 noro 1728: if ( i < elen2 ) {
1.38 noro 1729: strcpy(prefix,dp_vars_prefix?dp_vars_prefix:"x");
1.44 noro 1730: prefix_conv = conv_rule(prefix);
1731: vname_conv = (char *)ALLOCA(strlen(prefix_conv)+50);
1.46 noro 1732: si = i+dp_vars_origin;
1733: sprintf(vname_conv,(si>=0&&si<10)?"%s_%d":"%s_{%d}",
1734: prefix_conv,si);
1.44 noro 1735: } else if ( i < elen ) {
1.46 noro 1736: strcpy(prefix,
1737: dp_dvars_prefix?dp_dvars_prefix:"\\partial");
1.44 noro 1738: prefix_conv = conv_rule(prefix);
1739: vname_conv = (char *)ALLOCA(strlen(prefix_conv)+50);
1.46 noro 1740: si = i+dp_dvars_origin-elen2;
1741: sprintf(vname_conv,(si>=0&&si<10)?"%s_%d":"%s_{%d}",
1742: prefix_conv,si);
1.44 noro 1743: } else {
1.38 noro 1744: strcpy(prefix,"h");
1.44 noro 1745: vname_conv = conv_rule(prefix);
1746: }
1747: } else {
1.38 noro 1748: strcpy(prefix,dp_vars_prefix?dp_vars_prefix:"x");
1.44 noro 1749: prefix_conv = conv_rule(prefix);
1750: vname_conv = (char *)ALLOCA(strlen(prefix_conv)+50);
1.46 noro 1751: si = i+dp_vars_origin;
1752: sprintf(vname_conv,(si>=0&&si<10)?"%s_%d":"%s_{%d}",
1753: prefix_conv,si);
1.44 noro 1754: }
1.38 noro 1755: }
1.23 noro 1756: if ( fi->id == I_FORMULA && UNIQ(FA0(fi)) ) {
1757: len = strlen(vname_conv);
1758: opname = MALLOC_ATOMIC(len+2);
1759: sprintf(opname,"%s ",vname_conv);
1.14 noro 1760: write_tb(opname,tb);
1.23 noro 1761: } else {
1762: len = strlen(vname_conv);
1763: /* 2: ^{ */
1764: opname = MALLOC_ATOMIC(len+1+2);
1765: sprintf(opname,"%s^{",vname_conv);
1.14 noro 1766: write_tb(opname,tb);
1.23 noro 1767: fnodetotex_tb((FNODE)BDY(n),tb);
1768: write_tb("} ",tb);
1769: }
1.14 noro 1770: }
1.23 noro 1771: /* XXX */
1772: if ( allzero )
1773: write_tb(" 1 ",tb);
1.27 noro 1774: if ( show_lt && is_lt ) {
1775: write_tb("}",tb);
1776: is_lt = 0;
1777: }
1.14 noro 1778: break;
1779:
1.23 noro 1780: /* string */
1.14 noro 1781: case I_STR:
1782: write_tb((char *)FA0(f),tb);
1783: break;
1784:
1.23 noro 1785: /* internal object */
1.14 noro 1786: case I_FORMULA:
1787: obj = (Obj)FA0(f);
1.40 noro 1788: if ( !obj )
1.42 noro 1789: write_tb("0",tb);
1.40 noro 1790: else if ( OID(obj) == O_N && NID(obj) == N_C ) {
1791: cplx = (C)obj;
1792: write_tb("(",tb);
1793: if ( cplx->r ) {
1794: r = objtostr((Obj)cplx->r); write_tb(r,tb);
1795: }
1796: if ( cplx->i ) {
1797: if ( cplx->r && compnum(0,cplx->i,0) > 0 ) {
1798: write_tb("+",tb);
1799: if ( !UNIQ(cplx->i) ) {
1800: r = objtostr((Obj)cplx->i); write_tb(r,tb);
1801: }
1802: } else if ( MUNIQ(cplx->i) )
1803: write_tb("-",tb);
1804: else if ( !UNIQ(cplx->i) ) {
1805: r = objtostr((Obj)cplx->i); write_tb(r,tb);
1806: }
1807: write_tb("\\sqrt{-1}",tb);
1808: }
1809: write_tb(")",tb);
1810: } else if ( OID(obj) == O_P )
1811: write_tb(conv_rule(VR((P)obj)->name),tb);
1812: else
1813: write_tb(objtostr(obj),tb);
1.14 noro 1814: break;
1815:
1.23 noro 1816: /* program variable */
1.14 noro 1817: case I_PVAR:
1818: if ( FA1(f) )
1819: error("fnodetotex_tb : not implemented yet");
1820: GETPVNAME(FA0(f),opname);
1821: write_tb(opname,tb);
1822: break;
1823:
1824: default:
1825: error("fnodetotex_tb : not implemented yet");
1826: }
1.40 noro 1827: }
1828:
1829: char *objtostr(Obj obj)
1830: {
1831: int len;
1832: char *r;
1833:
1834: len = estimate_length(CO,obj);
1835: r = (char *)MALLOC_ATOMIC(len+1);
1836: soutput_init(r);
1837: sprintexpr(CO,obj);
1838: return r;
1.50 ohara 1839: }
1840:
1841: void Psprintf(NODE arg,STRING *rp)
1842: {
1843: STRING string;
1844: char *s,*t,*r;
1845: int argc,n,len;
1846: NODE node;
1847:
1848: string = (STRING)ARG0(arg);
1849: asir_assert(string,O_STR,"sprintf");
1850: s = BDY(string);
1851: for(n = 0, t = s; *t; t++) {
1852: if (*t=='%' && *(t+1)=='a') {
1853: n++;
1854: }
1855: }
1856: for(node = NEXT(arg), argc = 0, len = strlen(s); node; node = NEXT(node), argc++) {
1857: len += estimate_length(CO,BDY(node));
1858: }
1859: if (argc < n) {
1860: error("sprintf: invalid argument");
1861: }
1862: r = (char *)MALLOC_ATOMIC(len);
1863: for(node = NEXT(arg), t = r; *s; s++) {
1864: if (*s=='%' && *(s+1)=='a') {
1865: strcpy(t,objtostr(BDY(node)));
1866: node = NEXT(node);
1867: t = strchr(t,0);
1868: s++;
1869: }else {
1870: *t++ = *s;
1871: }
1872: }
1873: *t = 0;
1874: MKSTR(*rp,r);
1.14 noro 1875: }
1876:
1877: void fnodenodetotex_tb(NODE n,TB tb)
1878: {
1879: for ( ; n; n = NEXT(n) ) {
1.27 noro 1880: is_lt = 1;
1.14 noro 1881: fnodetotex_tb((FNODE)BDY(n),tb);
1882: if ( NEXT(n) ) write_tb(", ",tb);
1883: }
1884: }
1885:
1886: void fargstotex_tb(char *name,FNODE f,TB tb)
1887: {
1888: NODE n;
1889:
1890: if ( !strcmp(name,"matrix") ) {
1891: error("fargstotex_tb : not implemented yet");
1892: } else if ( !strcmp(name,"vector") ) {
1893: error("fargstotex_tb : not implemented yet");
1894: } else {
1895: if ( f->id == I_LIST ) {
1896: n = (NODE)FA0(f);
1897: fnodenodetotex_tb(n,tb);
1898: } else
1899: fnodetotex_tb(f,tb);
1.35 noro 1900: }
1901: }
1902:
1903: int top_is_minus(FNODE f)
1904: {
1905: char *opname;
1906: int len;
1907: Obj obj;
1908:
1909: if ( !f )
1910: return 0;
1911: switch ( f->id ) {
1912: case I_MINUS:
1913: return 1;
1914: case I_BOP:
1915: opname = ((ARF)FA0(f))->name;
1916: switch ( opname[0] ) {
1917: case '+': case '*': case '/': case '^': case '%':
1918: return top_is_minus((FNODE)FA1(f));
1919: case '-':
1920: if ( FA1(f) )
1921: return top_is_minus((FNODE)FA1(f));
1922: else
1923: return 1;
1924: default:
1925: return 0;
1926: }
1927: break;
1928: case I_COP:
1929: return top_is_minus((FNODE)FA1(f));
1930: case I_LOP:
1931: if ( (lid)FA0(f) == L_NOT ) return 0;
1932: else return top_is_minus((FNODE)FA1(f));
1933: case I_AND: case I_OR:
1934: return top_is_minus((FNODE)FA0(f));
1935: case I_FORMULA:
1936: obj = (Obj)FA0(f);
1.36 noro 1937: if ( !obj )
1938: return 0;
1939: else {
1940: switch ( OID(obj) ) {
1941: case O_N:
1942: return mmono((P)obj);
1943: case O_P:
1944: /* must be a variable */
1945: opname = conv_rule(VR((P)obj)->name);
1946: return opname[0]=='-';
1947: default:
1948: /* ??? */
1949: len = estimate_length(CO,obj);
1950: opname = (char *)MALLOC_ATOMIC(len+1);
1951: soutput_init(opname);
1952: sprintexpr(CO,obj);
1953: return opname[0]=='-';
1954: }
1.35 noro 1955: }
1.91 noro 1956: case I_NARYOP:
1957: return top_is_minus((FNODE)BDY((NODE)FA1(f)));
1958:
1.35 noro 1959: default:
1960: return 0;
1.14 noro 1961: }
1.47 noro 1962: }
1963:
1964: FNODE flatten_fnode(FNODE,char *);
1965:
1.48 noro 1966: void Pflatten_quote(NODE arg,Obj *rp)
1.47 noro 1967: {
1968: FNODE f;
1969: QUOTE q;
1970:
1.48 noro 1971: if ( !ARG0(arg) || OID((Obj)ARG0(arg)) != O_QUOTE )
1972: *rp = (Obj)ARG0(arg);
1.65 noro 1973: else if ( argc(arg) == 1 ) {
1974: f = flatten_fnode(BDY((QUOTE)ARG0(arg)),"+");
1975: f = flatten_fnode(f,"*");
1976: MKQUOTE(q,f);
1977: *rp = (Obj)q;
1978: } else {
1.48 noro 1979: f = flatten_fnode(BDY((QUOTE)ARG0(arg)),BDY((STRING)ARG1(arg)));
1980: MKQUOTE(q,f);
1981: *rp = (Obj)q;
1982: }
1.63 noro 1983: }
1984:
1985: void Pget_quote_id(NODE arg,Q *rp)
1986: {
1987: FNODE f;
1988: QUOTE q;
1989:
1990: q = (QUOTE)ARG0(arg);
1991: if ( !q || OID(q) != O_QUOTE )
1992: error("get_quote_id : invalid argument");
1993: f = BDY(q);
1994: STOQ((int)f->id,*rp);
1.48 noro 1995: }
1996:
1997: void Pquote_to_funargs(NODE arg,LIST *rp)
1998: {
1999: fid_spec_p spec;
2000: QUOTE q;
2001: QUOTEARG qa;
2002: FNODE f;
2003: STRING s;
2004: QUOTE r;
2005: int i;
2006: Q id,a;
1.49 noro 2007: LIST l;
2008: NODE t0,t,w,u,u0;
1.48 noro 2009:
2010: q = (QUOTE)ARG0(arg);
2011: if ( !q || OID(q) != O_QUOTE )
2012: error("quote_to_funargs : invalid argument");
2013: f = BDY(q);
2014: if ( !f ) {
2015: MKLIST(*rp,0);
2016: return;
2017: }
2018: get_fid_spec(f->id,&spec);
2019: if ( !spec )
2020: error("quote_to_funargs : not supported yet");
2021: t0 = 0;
2022: STOQ((int)f->id,id);
2023: NEXTNODE(t0,t);
2024: BDY(t) = (pointer)id;
2025: for ( i = 0; spec->type[i] != A_end; i++ ) {
2026: NEXTNODE(t0,t);
2027: switch ( spec->type[i] ) {
2028: case A_fnode:
2029: MKQUOTE(r,(FNODE)f->arg[i]);
2030: BDY(t) = (pointer)r;
2031: break;
2032: case A_int:
2033: STOQ((int)f->arg[i],a);
2034: BDY(t) = (pointer)a;
2035: break;
2036: case A_str:
2037: MKSTR(s,(char *)f->arg[i]);
2038: BDY(t) = (pointer)s;
2039: break;
2040: case A_internal:
2041: BDY(t) = (pointer)f->arg[i];
2042: break;
1.49 noro 2043: case A_node:
2044: w = (NODE)f->arg[i];
2045: for ( u0 = 0; w; w = NEXT(w) ){
2046: NEXTNODE(u0,u);
2047: MKQUOTE(r,(FNODE)BDY(w));
2048: BDY(u) = (pointer)r;
2049: }
2050: if ( u0 ) NEXT(u) = 0;
2051: MKLIST(l,u0);
2052: BDY(t) = (pointer)l;
2053: break;
1.48 noro 2054: default:
2055: MKQUOTEARG(qa,spec->type[i],f->arg[i]);
2056: BDY(t) = (pointer)qa;
2057: break;
2058: }
2059: }
2060: if ( t0 ) NEXT(t) = 0;
2061: MKLIST(*rp,t0);
2062: }
2063:
2064: void Pfunargs_to_quote(NODE arg,QUOTE *rp)
2065: {
2066: fid_spec_p spec;
2067: QUOTE q;
2068: QUOTEARG qa;
2069: FNODE f;
2070: STRING s;
1.49 noro 2071: QUOTE r,b;
1.48 noro 2072: int i;
2073: LIST l;
2074: fid id;
2075: Obj a;
1.49 noro 2076: NODE t0,t,u0,u,w;
1.48 noro 2077:
2078: l = (LIST)ARG0(arg);
2079: if ( !l || OID(l) != O_LIST || !(t=BDY(l)) )
2080: error("funargs_to_quote : invalid argument");
2081: t = BDY(l);
2082: id = (fid)QTOS((Q)BDY(t)); t = NEXT(t);
2083: get_fid_spec(id,&spec);
2084: if ( !spec )
2085: error("funargs_to_quote : not supported yet");
2086: for ( i = 0; spec->type[i] != A_end; i++ );
2087: NEWFNODE(f,i);
2088: f->id = id;
2089: for ( i = 0; spec->type[i] != A_end; i++, t = NEXT(t) ) {
2090: if ( !t )
2091: error("funargs_to_quote : argument mismatch");
2092: a = (Obj)BDY(t);
2093: switch ( spec->type[i] ) {
2094: case A_fnode:
2095: if ( !a || OID(a) != O_QUOTE )
2096: error("funargs_to_quote : invalid argument");
2097: f->arg[i] = BDY((QUOTE)a);
2098: break;
2099: case A_int:
2100: if ( !INT(a) )
2101: error("funargs_to_quote : invalid argument");
2102: f->arg[i] = (pointer)QTOS((Q)a);
2103: break;
2104: case A_str:
2105: if ( !a || OID(a) != O_STR )
2106: error("funargs_to_quote : invalid argument");
2107: f->arg[i] = (pointer)BDY((STRING)a);
2108: break;
2109: case A_internal:
2110: f->arg[i] = (pointer)a;
1.49 noro 2111: break;
2112: case A_node:
2113: if ( !a || OID(a) != O_LIST )
2114: error("funargs_to_quote : invalid argument");
2115: u0 = 0;
2116: for ( w = BDY((LIST)a); w; w = NEXT(w) ) {
2117: NEXTNODE(u0,u);
2118: b = (QUOTE)BDY(w);
2119: if ( !b || OID(b) != O_QUOTE )
2120: error("funargs_to_quote : invalid argument");
2121: BDY(u) = BDY(b);
2122: }
2123: if ( u0 ) NEXT(u) = 0;
2124: f->arg[i] = (pointer)u0;
1.48 noro 2125: break;
2126: default:
2127: if ( !a || OID(a) != O_QUOTEARG ||
2128: ((QUOTEARG)a)->type != spec->type[i] )
2129: error("funargs_to_quote : invalid argument");
2130: f->arg[i] = BDY((QUOTEARG)a);
2131: break;
2132: }
2133: }
2134: MKQUOTE(*rp,f);
1.69 noro 2135: }
2136:
1.105 noro 2137: VL reordvars(VL vl0,NODE head)
2138: {
2139: VL vl,svl,tvl;
2140: int i,j;
2141: NODE n;
2142: P t;
2143: V *va;
2144: V v;
2145:
2146: for ( vl = 0, i = 0, n = head; n; n = NEXT(n), i++ ) {
2147: NEXTVL(vl,tvl);
2148: if ( !(t = (P)BDY(n)) || (OID(t) != O_P) )
2149: error("reordvars : invalid argument");
2150: VR(tvl) = VR(t);
2151: }
2152: va = (V *)ALLOCA(i*sizeof(V));
2153: for ( j = 0, svl = vl; j < i; j++, svl = NEXT(svl) )
2154: va[j] = VR(svl);
2155: for ( svl = vl0; svl; svl = NEXT(svl) ) {
2156: v = VR(svl);
2157: for ( j = 0; j < i; j++ )
2158: if ( v == va[j] )
2159: break;
2160: if ( j == i ) {
2161: NEXTVL(vl,tvl);
2162: VR(tvl) = v;
2163: }
2164: }
2165: if ( vl )
2166: NEXT(tvl) = 0;
2167: return vl;
2168: }
2169:
1.109 ! noro 2170: struct wtab {
! 2171: V v;
! 2172: int w;
! 2173: };
! 2174:
! 2175: struct wtab *qt_weight_tab;
1.108 noro 2176: VL qt_current_ord, qt_current_coef;
1.109 ! noro 2177: LIST qt_current_ord_obj,qt_current_coef_obj,qt_current_weight_obj;
! 2178: LIST qt_current_weight_obj;
1.105 noro 2179:
2180: void Pqt_set_ord(NODE arg,LIST *rp)
2181: {
2182: NODE r0,r;
2183: VL vl;
2184: P v;
2185:
2186: if ( !argc(arg) )
2187: *rp = qt_current_ord_obj;
1.109 ! noro 2188: else if ( !ARG0(arg) ) {
! 2189: qt_current_ord_obj = 0;
! 2190: qt_current_ord = 0;
! 2191: } else {
1.105 noro 2192: qt_current_ord = reordvars(CO,BDY((LIST)ARG0(arg)));
2193: for ( r0 = 0, vl = qt_current_ord; vl; vl = NEXT(vl) ) {
2194: NEXTNODE(r0,r); MKV(vl->v,v); BDY(r) = v;
2195: }
2196: if ( r0 ) NEXT(r) = 0;
2197: MKLIST(*rp,r0);
2198: qt_current_ord_obj = *rp;
2199: }
2200: }
2201:
1.109 ! noro 2202: void Pqt_set_weight(NODE arg,LIST *rp)
! 2203: {
! 2204: NODE n,pair;
! 2205: int l,i;
! 2206: struct wtab *tab;
! 2207:
! 2208: if ( !argc(arg) )
! 2209: *rp = qt_current_weight_obj;
! 2210: else if ( !ARG0(arg) ) {
! 2211: qt_current_weight_obj = 0;
! 2212: qt_weight_tab = 0;
! 2213: } else {
! 2214: n = BDY((LIST)ARG0(arg));
! 2215: l = length(n);
! 2216: tab = qt_weight_tab = (struct wtab *)MALLOC((l+1)*sizeof(struct wtab));
! 2217: for ( i = 0; i < l; i++, n = NEXT(n) ) {
! 2218: pair = BDY((LIST)BDY(n));
! 2219: tab[i].v = VR((P)ARG0(pair));
! 2220: tab[i].w = QTOS((Q)ARG1(pair));
! 2221: }
! 2222: tab[i].v = 0;
! 2223: qt_current_weight_obj = (LIST)ARG0(arg);
! 2224: *rp = qt_current_weight_obj;
! 2225: }
! 2226: }
! 2227:
1.108 noro 2228: void Pqt_set_coef(NODE arg,LIST *rp)
2229: {
2230: NODE r0,r,n;
2231: VL vl0,vl;
2232: P v;
2233:
2234: if ( !argc(arg) )
2235: *rp = qt_current_coef_obj;
1.109 ! noro 2236: else if ( !ARG0(arg) ) {
! 2237: qt_current_coef_obj = 0;
! 2238: qt_current_coef = 0;
! 2239: } else {
1.108 noro 2240: n = BDY((LIST)ARG0(arg));
2241: for ( vl0 = 0, r0 = 0; n; n = NEXT(n) ) {
2242: NEXTNODE(r0,r);
2243: NEXTVL(vl0,vl);
2244: vl->v = VR((P)BDY(n));
2245: MKV(vl->v,v); BDY(r) = v;
2246: }
2247: if ( r0 ) NEXT(r) = 0;
2248: if ( vl0 ) NEXT(vl) = 0;
2249: qt_current_coef = vl0;
2250: MKLIST(*rp,r0);
2251: qt_current_coef_obj = *rp;
2252: }
2253: }
2254:
1.105 noro 2255: void Pqt_normalize(NODE arg,QUOTE *rp)
1.70 noro 2256: {
2257: QUOTE q,r;
2258: FNODE f;
1.76 noro 2259: int expand,ac;
1.70 noro 2260:
1.76 noro 2261: ac = argc(arg);
1.105 noro 2262: if ( !ac ) error("qt_normalize : invalid argument");
1.70 noro 2263: q = (QUOTE)ARG0(arg);
1.103 noro 2264: if ( ac == 2 )
2265: expand = QTOS((Q)ARG1(arg));
1.97 noro 2266: if ( !q || OID(q) != O_QUOTE )
1.87 noro 2267: *rp = q;
2268: else {
1.76 noro 2269: f = fnode_normalize(BDY(q),expand);
1.70 noro 2270: MKQUOTE(r,f);
2271: *rp = r;
1.98 noro 2272: }
2273: }
2274:
2275: NBP fnode_to_nbp(FNODE f);
2276:
1.105 noro 2277: void Pqt_to_nbp(NODE arg,NBP *rp)
1.98 noro 2278: {
2279: QUOTE q;
2280: FNODE f;
2281:
2282: q = (QUOTE)ARG0(arg); f = (FNODE)BDY(q);
2283: f = fnode_normalize(f,0);
2284: *rp = fnode_to_nbp(f);
2285: }
2286:
1.101 noro 2287: void Pshuffle_mul(NODE arg,NBP *rp)
1.98 noro 2288: {
2289: NBP p1,p2;
2290:
2291: p1 = (NBP)ARG0(arg);
2292: p2 = (NBP)ARG1(arg);
2293: shuffle_mulnbp(CO,p1,p2,rp);
2294: }
1.99 noro 2295:
1.101 noro 2296: void Pharmonic_mul(NODE arg,NBP *rp)
1.99 noro 2297: {
2298: NBP p1,p2;
2299:
2300: p1 = (NBP)ARG0(arg);
2301: p2 = (NBP)ARG1(arg);
2302: harmonic_mulnbp(CO,p1,p2,rp);
2303: }
2304:
1.100 noro 2305: void Pnbp_hm(NODE arg, NBP *rp)
2306: {
2307: NBP p;
2308: NODE n;
2309: NBM m;
2310:
2311: p = (NBP)ARG0(arg);
2312: if ( !p ) *rp = 0;
2313: else {
2314: m = (NBM)BDY(BDY(p));
2315: MKNODE(n,m,0);
2316: MKNBP(*rp,n);
2317: }
2318: }
2319:
2320: void Pnbp_ht(NODE arg, NBP *rp)
2321: {
2322: NBP p;
2323: NODE n;
2324: NBM m,m1;
2325:
2326: p = (NBP)ARG0(arg);
2327: if ( !p ) *rp = 0;
2328: else {
2329: m = (NBM)BDY(BDY(p));
2330: NEWNBM(m1);
2331: m1->d = m->d; m1->c = ONE; m1->b = m->b;
2332: MKNODE(n,m1,0);
2333: MKNBP(*rp,n);
2334: }
2335: }
2336:
2337: void Pnbp_hc(NODE arg, Q *rp)
2338: {
2339: NBP p;
2340: NBM m;
2341:
2342: p = (NBP)ARG0(arg);
2343: if ( !p ) *rp = 0;
2344: else {
2345: m = (NBM)BDY(BDY(p));
2346: *rp = m->c;
2347: }
2348: }
2349:
2350: void Pnbp_rest(NODE arg, NBP *rp)
2351: {
2352: NBP p;
2353: NODE n;
2354:
2355: p = (NBP)ARG0(arg);
2356: if ( !p ) *rp = 0;
2357: else {
2358: n = BDY(p);
2359: if ( !NEXT(n) ) *rp = 0;
2360: else
2361: MKNBP(*rp,NEXT(n));
2362: }
2363: }
2364:
1.102 noro 2365: void Pnbm_deg(NODE arg, Q *rp)
1.100 noro 2366: {
2367: NBP p;
2368: NBM m;
1.102 noro 2369:
2370: p = (NBP)ARG0(arg);
2371: if ( !p )
2372: STOQ(-1,*rp);
2373: else {
2374: m = (NBM)BDY(BDY(p));
2375: STOQ(m->d,*rp);
2376: }
2377: }
2378:
2379: void Pnbm_hp_rest(NODE arg, LIST *rp)
2380: {
2381: NBP p,h,r;
2382: NBM m,m1;
1.100 noro 2383: NODE n;
1.102 noro 2384: int *b,*b1;
2385: int d,d1,v,i,j,k;
1.100 noro 2386:
2387: p = (NBP)ARG0(arg);
1.102 noro 2388: if ( !p )
1.100 noro 2389: MKLIST(*rp,0);
1.102 noro 2390: else {
2391: m = (NBM)BDY(BDY(p));
2392: b = m->b; d = m->d;
1.100 noro 2393: if ( !d )
2394: MKLIST(*rp,0);
2395: else {
1.102 noro 2396: v = NBM_GET(b,0);
1.100 noro 2397: for ( i = 1; i < d; i++ )
1.102 noro 2398: if ( NBM_GET(b,i) != v ) break;
2399: NEWNBM(m1); NEWNBMBDY(m1,i);
2400: b1 = m1->b; m1->d = i; m1->c = ONE;
2401: if ( v ) for ( j = 0; j < i; j++ ) NBM_SET(b1,j);
2402: else for ( j = 0; j < i; j++ ) NBM_CLR(b1,j);
2403: MKNODE(n,m1,0); MKNBP(h,n);
2404:
2405: d1 = d-i;
2406: NEWNBM(m1); NEWNBMBDY(m1,d1);
2407: b1 = m1->b; m1->d = d1; m1->c = ONE;
2408: for ( j = 0, k = i; j < d1; j++, k++ )
2409: if ( NBM_GET(b,k) ) NBM_SET(b1,j);
2410: else NBM_CLR(b1,j);
2411: MKNODE(n,m1,0); MKNBP(r,n);
2412: n = mknode(2,h,r);
1.100 noro 2413: MKLIST(*rp,n);
2414: }
2415: }
2416: }
2417:
1.102 noro 2418: void Pnbm_hxky(NODE arg, LIST *rp)
2419: {
2420: NBP p;
2421:
2422: p = (NBP)ARG0(arg);
2423: if ( !p )
2424: *rp = 0;
2425: else
2426: separate_xky_nbm((NBM)BDY(BDY(p)),0,rp,0);
2427: }
2428:
2429: void Pnbm_xky_rest(NODE arg,NBP *rp)
1.100 noro 2430: {
2431: NBP p;
2432:
2433: p = (NBP)ARG0(arg);
2434: if ( !p )
2435: *rp = 0;
1.102 noro 2436: else
2437: separate_xky_nbm((NBM)BDY(BDY(p)),0,0,rp);
2438: }
2439:
2440: void Pnbm_hv(NODE arg, NBP *rp)
2441: {
2442: NBP p;
2443:
2444: p = (NBP)ARG0(arg);
2445: if ( !p )
2446: *rp = 0;
2447: else
2448: separate_nbm((NBM)BDY(BDY(p)),0,rp,0);
2449: }
2450:
2451: void Pnbm_rest(NODE arg, NBP *rp)
2452: {
2453: NBP p;
2454:
2455: p = (NBP)ARG0(arg);
2456: if ( !p )
2457: *rp = 0;
2458: else
2459: separate_nbm((NBM)BDY(BDY(p)),0,0,rp);
1.100 noro 2460: }
1.98 noro 2461:
2462: NBP fnode_to_nbp(FNODE f)
2463: {
2464: Q r;
2465: int n,i;
2466: NBM m;
2467: V v;
2468: NBP u,u1,u2;
2469: NODE t,b;
2470:
2471: if ( f->id == I_FORMULA ) {
2472: r = eval(f);
2473: NEWNBM(m);
2474: if ( OID(r) == O_N ) {
2475: m->d = 0; m->c = (Q)r; m->b = 0;
2476: } else {
2477: v = VR((P)r);
2478: m->d = 1; m->c = ONE; NEWNBMBDY(m,1);
2479: if ( !strcmp(NAME(v),"x") ) NBM_SET(m->b,0);
2480: else NBM_CLR(m->b,0);
2481: }
2482: MKNODE(b,m,0); MKNBP(u,b);
2483: return u;
2484: } else if ( IS_NARYADD(f) ) {
2485: t = (NODE)FA1(f); u = fnode_to_nbp((FNODE)BDY(t));
2486: for ( t = NEXT(t); t; t = NEXT(t) ) {
2487: u1 = fnode_to_nbp((FNODE)BDY(t));
2488: addnbp(CO,u,u1,&u2); u = u2;
2489: }
2490: return u;
2491: } else if ( IS_NARYMUL(f) ) {
2492: t = (NODE)FA1(f); u = fnode_to_nbp((FNODE)BDY(t));
2493: for ( t = NEXT(t); t; t = NEXT(t) ) {
2494: u1 = fnode_to_nbp((FNODE)BDY(t));
2495: mulnbp(CO,u,u1,&u2); u = u2;
2496: }
2497: return u;
2498: } else if ( IS_BINARYPWR(f) ) {
2499: u = fnode_to_nbp((FNODE)FA1(f));
2500: r = eval((FNODE)FA2(f));
2501: pwrnbp(CO,u,r,&u1);
2502: return u1;
1.70 noro 2503: }
2504: }
2505:
1.105 noro 2506: void Pnqt_comp(NODE arg,Q *rp)
1.80 noro 2507: {
1.87 noro 2508: QUOTE q1,q2;
1.80 noro 2509: FNODE f1,f2;
2510: int r;
2511:
1.87 noro 2512: q1 = (QUOTE)ARG0(arg); f1 = (FNODE)BDY(q1);
2513: q2 = (QUOTE)ARG1(arg); f2 = (FNODE)BDY(q2);
1.97 noro 2514: f1 = fnode_normalize(f1,0);
2515: f2 = fnode_normalize(f2,0);
1.95 noro 2516: r = nfnode_comp(f1,f2);
1.80 noro 2517: STOQ(r,*rp);
2518: }
2519:
1.108 noro 2520: int fnode_is_var(FNODE f)
2521: {
2522: Obj obj;
2523: VL vl,t,s;
2524: DCP dc;
2525:
2526: if ( fnode_is_coef(f) ) return 0;
2527: switch ( f->id ) {
2528: case I_PAREN:
2529: return fnode_is_var(FA0(f));
2530:
2531: case I_FORMULA:
2532: obj = FA0(f);
2533: if ( obj && OID(obj) == O_P ) {
2534: dc = DC((P)obj);
2535: if ( !cmpq(DEG(dc),ONE) && !NEXT(dc)
2536: && !arf_comp(CO,(Obj)COEF(dc),(Obj)ONE) ) return 1;
2537: else return 0;
2538: } else return 0;
2539:
2540: default:
2541: return 0;
2542: }
2543: }
2544:
2545: int fnode_is_coef(FNODE f)
2546: {
2547: Obj obj;
2548: VL vl,t,s;
2549:
2550: switch ( f->id ) {
2551: case I_MINUS: case I_PAREN:
2552: return fnode_is_coef(FA0(f));
2553:
2554: case I_FORMULA:
2555: obj = FA0(f);
2556: if ( !obj ) return 1;
2557: else if ( OID(obj) == O_QUOTE )
2558: return fnode_is_coef(BDY((QUOTE)obj));
2559: else if ( NUM(obj) ) return 1;
2560: else if ( OID(obj) == O_P || OID(obj) == O_R) {
2561: get_vars_recursive(obj,&vl);
2562: for ( t = vl; t; t = NEXT(t) ) {
2563: for ( s = qt_current_coef; s; s = NEXT(s) )
2564: if ( t->v == s->v ) break;
2565: if ( !s ) return 0;
2566: }
2567: return 1;
2568: } else return 0;
2569:
2570: case I_BOP:
2571: return fnode_is_coef(FA1(f)) && fnode_is_coef(FA2(f));
2572:
2573: default:
2574: return 0;
2575: }
2576: }
2577:
2578: int fnode_is_number(FNODE f)
1.69 noro 2579: {
2580: Obj obj;
2581:
2582: switch ( f->id ) {
2583: case I_MINUS: case I_PAREN:
2584: return fnode_is_number(FA0(f));
2585:
2586: case I_FORMULA:
2587: obj = FA0(f);
2588: if ( !obj ) return 1;
2589: else if ( OID(obj) == O_QUOTE )
2590: return fnode_is_number(BDY((QUOTE)obj));
2591: else if ( NUM(obj) ) return 1;
2592: else return 0;
2593:
2594: case I_BOP:
2595: return fnode_is_number(FA1(f)) && fnode_is_number(FA2(f));
2596:
2597: default:
2598: return 0;
2599: }
2600: }
2601:
2602: int fnode_is_rational(FNODE f)
2603: {
2604: Obj obj;
2605:
2606: switch ( f->id ) {
2607: case I_MINUS: case I_PAREN:
2608: return fnode_is_number(FA0(f));
2609:
2610: case I_FORMULA:
2611: obj = FA0(f);
2612: if ( !obj ) return 1;
2613: else if ( OID(obj) == O_QUOTE )
2614: return fnode_is_rational(BDY((QUOTE)obj));
2615: else if ( NUM(obj) && RATN(obj) ) return 1;
2616: else return 0;
2617:
2618: case I_BOP:
2619: if ( !strcmp(((ARF)FA0(f))->name,"^") )
2620: return fnode_is_rational(FA1(f)) && fnode_is_integer(FA2(f));
2621: else
2622: return fnode_is_rational(FA1(f)) && fnode_is_rational(FA2(f));
2623:
2624: default:
2625: return 0;
2626: }
2627: }
2628:
2629: int fnode_is_integer(FNODE f)
2630: {
2631: Obj obj;
2632:
2633: switch ( f->id ) {
2634: case I_MINUS: case I_PAREN:
2635: return fnode_is_integer(FA0(f));
2636:
2637: case I_FORMULA:
2638: obj = FA0(f);
2639: if ( !obj ) return 1;
2640: else if ( OID(obj) == O_QUOTE )
2641: return fnode_is_integer(BDY((QUOTE)obj));
2642: else if ( INT(obj)) return 1;
2643: else return 0;
2644:
2645: case I_BOP:
1.70 noro 2646: switch ( ((ARF)FA0(f))->name[0] ) {
2647: case '^':
2648: return fnode_is_integer(FA1(f))
2649: && fnode_is_nonnegative_integer(FA2(f));
2650: case '/':
2651: return fnode_is_integer(FA1(f)) &&
2652: ( fnode_is_one(FA2(f)) || fnode_is_minusone(FA2(f)) );
2653: default:
2654: return fnode_is_integer(FA1(f)) && fnode_is_integer(FA2(f));
2655: }
2656: break;
2657:
1.69 noro 2658: default:
2659: return 0;
2660: }
2661: }
2662:
2663: int fnode_is_nonnegative_integer(FNODE f)
2664: {
2665: Q n;
2666:
2667: n = eval(f);
2668: if ( !n || (INT(n) && SGN(n) > 0) ) return 1;
2669: else return 0;
2670: }
2671:
2672: int fnode_is_one(FNODE f)
2673: {
2674: Q n;
2675:
2676: n = eval(f);
2677: if ( UNIQ(n) ) return 1;
2678: else return 0;
2679: }
2680:
2681: int fnode_is_minusone(FNODE f)
2682: {
2683: Q n;
2684:
2685: n = eval(f);
2686: if ( MUNIQ(n) ) return 1;
2687: else return 0;
2688: }
2689:
2690: int fnode_is_dependent(FNODE f,V v)
2691: {
2692: Obj obj;
2693: FNODE arg;
2694: NODE t;
2695:
2696: switch ( f->id ) {
2697: case I_MINUS: case I_PAREN:
2698: return fnode_is_dependent(FA0(f),v);
2699:
2700: case I_FORMULA:
2701: obj = FA0(f);
2702: if ( !obj ) return 0;
2703: else if ( OID(obj) == O_QUOTE )
2704: return fnode_is_dependent(BDY((QUOTE)obj),v);
2705: else if ( obj_is_dependent(obj,v) ) return 1;
2706: else return 0;
2707:
2708: case I_BOP:
2709: return fnode_is_dependent(FA1(f),v) || fnode_is_dependent(FA2(f),v);
2710:
2711: case I_FUNC:
2712: arg = (FNODE)FA1(f);
2713: for ( t = FA0(arg); t; t = NEXT(t) )
2714: if ( fnode_is_dependent(BDY(t),v) ) return 1;
2715: return 0;
2716:
2717: default:
2718: return 0;
2719: }
1.1 noro 2720: }
1.70 noro 2721:
1.72 noro 2722:
1.76 noro 2723: FNODE fnode_normalize(FNODE f,int expand)
1.70 noro 2724: {
1.73 noro 2725: FNODE a1,a2,mone,r,b2;
1.72 noro 2726: NODE n;
1.70 noro 2727: Q q;
2728:
1.103 noro 2729: if ( f->normalized && (f->expanded == expand) ) return f;
1.72 noro 2730: STOQ(-1,q);
2731: mone = mkfnode(1,I_FORMULA,q);
1.70 noro 2732: switch ( f->id ) {
2733: case I_PAREN:
1.89 noro 2734: r = fnode_normalize(FA0(f),expand);
2735: break;
1.71 noro 2736:
2737: case I_MINUS:
1.108 noro 2738: r = nfnode_mul_coef((Obj)q,
1.76 noro 2739: fnode_normalize(FA0(f),expand),expand);
1.89 noro 2740: break;
1.71 noro 2741:
1.70 noro 2742: case I_BOP:
2743: /* arf fnode fnode */
1.76 noro 2744: a1 = fnode_normalize(FA1(f),expand);
2745: a2 = fnode_normalize(FA2(f),expand);
1.72 noro 2746: switch ( OPNAME(f) ) {
2747: case '+':
1.95 noro 2748: r = nfnode_add(a1,a2,expand);
1.89 noro 2749: break;
1.70 noro 2750: case '-':
1.108 noro 2751: a2 = nfnode_mul_coef((Obj)q,a2,expand);
1.95 noro 2752: r = nfnode_add(a1,a2,expand);
1.89 noro 2753: break;
1.72 noro 2754: case '*':
1.95 noro 2755: r = nfnode_mul(a1,a2,expand);
1.89 noro 2756: break;
1.70 noro 2757: case '/':
1.95 noro 2758: a2 = nfnode_pwr(a2,mone,expand);
2759: r = nfnode_mul(a1,a2,expand);
1.89 noro 2760: break;
1.73 noro 2761: case '^':
1.95 noro 2762: r = nfnode_pwr(a1,a2,expand);
1.89 noro 2763: break;
1.70 noro 2764: default:
1.89 noro 2765: r = mkfnode(3,I_BOP,FA0(f),a1,a2);
2766: break;
1.70 noro 2767: }
2768: break;
1.71 noro 2769:
1.70 noro 2770: case I_NARYOP:
1.72 noro 2771: switch ( OPNAME(f) ) {
1.71 noro 2772: case '+':
1.73 noro 2773: n = (NODE)FA1(f);
1.76 noro 2774: r = fnode_normalize(BDY(n),expand); n = NEXT(n);
1.72 noro 2775: for ( ; n; n = NEXT(n) ) {
1.76 noro 2776: a1 = fnode_normalize(BDY(n),expand);
1.95 noro 2777: r = nfnode_add(r,a1,expand);
1.72 noro 2778: }
1.89 noro 2779: break;
1.70 noro 2780: case '*':
1.73 noro 2781: n = (NODE)FA1(f);
1.76 noro 2782: r = fnode_normalize(BDY(n),expand); n = NEXT(n);
1.72 noro 2783: for ( ; n; n = NEXT(n) ) {
1.76 noro 2784: a1 = fnode_normalize(BDY(n),expand);
1.95 noro 2785: r = nfnode_mul(r,a1,expand);
1.72 noro 2786: }
1.89 noro 2787: break;
1.70 noro 2788: default:
1.72 noro 2789: error("fnode_normallize : cannot happen");
1.70 noro 2790: }
1.89 noro 2791: break;
1.72 noro 2792:
1.70 noro 2793: default:
1.76 noro 2794: return fnode_apply(f,fnode_normalize,expand);
1.70 noro 2795: }
1.89 noro 2796: r->normalized = 1;
2797: r->expanded = expand;
2798: return r;
1.70 noro 2799: }
2800:
1.76 noro 2801: FNODE fnode_apply(FNODE f,FNODE (*func)(),int expand)
1.70 noro 2802: {
2803: fid_spec_p spec;
2804: FNODE r;
2805: int i,n;
2806: NODE t,t0,s;
2807:
2808: get_fid_spec(f->id,&spec);
2809: for ( n = 0; spec->type[n] != A_end; n++ );
2810: NEWFNODE(r,n); r->id = f->id;
2811: for ( i = 0; i < n; i++ ) {
2812: switch ( spec->type[i] ) {
2813: case A_fnode:
1.78 noro 2814: r->arg[i] = func(f->arg[i],expand);
1.70 noro 2815: break;
2816: case A_node:
2817: s = (NODE)f->arg[i];
2818: for ( t0 = 0; s; s = NEXT(s) ) {
2819: NEXTNODE(t0,t);
1.76 noro 2820: BDY(t) = (pointer)func((FNODE)BDY(s),expand);
1.70 noro 2821: }
2822: if ( t0 ) NEXT(t) = 0;
2823: r->arg[i] = t0;
2824: break;
2825: default:
2826: r->arg[i] = f->arg[i];
2827: break;
2828: }
2829: }
2830: return r;
2831: }
2832:
1.95 noro 2833: FNODE nfnode_add(FNODE f1,FNODE f2,int expand)
1.71 noro 2834: {
1.72 noro 2835: NODE n1,n2,r0,r;
2836: FNODE b1,b2;
2837: int s;
1.108 noro 2838: Obj c1,c2,c;
1.72 noro 2839:
1.77 noro 2840: if ( IS_ZERO(f1) ) return f2;
2841: else if ( IS_ZERO(f2) ) return f1;
1.75 noro 2842: f1 = to_naryadd(f1); f2 = to_naryadd(f2);
2843: n1 = (NODE)FA1(f1); n2 = (NODE)FA1(f2);
1.72 noro 2844: r0 = 0;
2845: while ( n1 && n2 ) {
1.75 noro 2846: fnode_coef_body(BDY(n1),&c1,&b1); fnode_coef_body(BDY(n2),&c2,&b2);
1.95 noro 2847: if ( (s = nfnode_comp(b1,b2)) > 0 ) {
1.73 noro 2848: NEXTNODE(r0,r); BDY(r) = BDY(n1); n1 = NEXT(n1);
1.72 noro 2849: } else if ( s < 0 ) {
1.73 noro 2850: NEXTNODE(r0,r); BDY(r) = BDY(n2); n2 = NEXT(n2);
1.72 noro 2851: } else {
1.108 noro 2852: arf_add(CO,c1,c2,&c);
1.72 noro 2853: if ( c ) {
1.95 noro 2854: NEXTNODE(r0,r); BDY(r) = nfnode_mul_coef(c,b1,expand);
1.71 noro 2855: }
1.72 noro 2856: n1 = NEXT(n1); n2 = NEXT(n2);
1.71 noro 2857: }
2858: }
1.72 noro 2859: if ( n1 )
2860: if ( r0 ) NEXT(r) = n1;
2861: else r0 = n1;
2862: else if ( n2 )
2863: if ( r0 ) NEXT(r) = n2;
2864: else r0 = n2;
2865: else if ( r0 )
2866: NEXT(r) = 0;
2867:
1.106 noro 2868: return fnode_node_to_nary(addfs,r0);
1.75 noro 2869: }
2870:
1.106 noro 2871: FNODE fnode_node_to_nary(ARF op,NODE n)
1.75 noro 2872: {
1.106 noro 2873: if ( !n ) {
2874: if ( op->name[0] == '+' )
2875: return mkfnode(1,I_FORMULA,0);
2876: else
2877: return mkfnode(1,I_FORMULA,ONE);
2878: } else if ( !NEXT(n) ) return BDY(n);
2879: else return mkfnode(2,I_NARYOP,op,n);
1.71 noro 2880: }
2881:
1.95 noro 2882: FNODE nfnode_mul(FNODE f1,FNODE f2,int expand)
1.71 noro 2883: {
1.72 noro 2884: NODE n1,n2,r0,r,r1;
1.76 noro 2885: FNODE b1,b2,e1,e2,cc,t,t1;
1.72 noro 2886: FNODE *m;
2887: int s;
1.109 ! noro 2888: Obj c1,c2,c,e;
1.75 noro 2889: int l1,l,i,j;
1.72 noro 2890:
1.77 noro 2891: if ( IS_ZERO(f1) || IS_ZERO(f2) ) return mkfnode(1,I_FORMULA,0);
1.108 noro 2892: else if ( fnode_is_coef(f1) )
2893: return nfnode_mul_coef((Obj)eval(f1),f2,expand);
2894: else if ( fnode_is_coef(f2) )
2895: return nfnode_mul_coef((Obj)eval(f2),f1,expand);
1.76 noro 2896:
2897: if ( expand && IS_NARYADD(f1) ) {
2898: t = mkfnode(1,I_FORMULA,0);
2899: for ( n1 = (NODE)FA1(f1); n1; n1 = NEXT(n1) ) {
1.95 noro 2900: t1 = nfnode_mul(BDY(n1),f2,expand);
2901: t = nfnode_add(t,t1,expand);
1.76 noro 2902: }
2903: return t;
2904: }
2905: if ( expand && IS_NARYADD(f2) ) {
2906: t = mkfnode(1,I_FORMULA,0);
2907: for ( n2 = (NODE)FA1(f2); n2; n2 = NEXT(n2) ) {
1.95 noro 2908: t1 = nfnode_mul(f1,BDY(n2),expand);
2909: t = nfnode_add(t,t1,expand);
1.76 noro 2910: }
2911: return t;
2912: }
1.72 noro 2913:
1.75 noro 2914: fnode_coef_body(f1,&c1,&b1); fnode_coef_body(f2,&c2,&b2);
1.108 noro 2915: arf_mul(CO,c1,c2,&c);
1.72 noro 2916: if ( !c ) return mkfnode(1,I_FORMULA,0);
1.71 noro 2917:
1.76 noro 2918:
1.75 noro 2919: n1 = (NODE)FA1(to_narymul(b1)); n2 = (NODE)FA1(to_narymul(b2));
2920: l1 = length(n1); l = l1+length(n2);
1.72 noro 2921: m = (FNODE *)ALLOCA(l*sizeof(FNODE));
2922: for ( r = n1, i = 0; i < l1; r = NEXT(r), i++ ) m[i] = BDY(r);
2923: for ( r = n2; r; r = NEXT(r) ) {
1.103 noro 2924: if ( i == 0 || (expand == 2) )
1.72 noro 2925: m[i++] = BDY(r);
2926: else {
1.75 noro 2927: fnode_base_exp(m[i-1],&b1,&e1); fnode_base_exp(BDY(r),&b2,&e2);
2928: if ( compfnode(b1,b2) ) break;
1.109 ! noro 2929: arf_add(CO,eval(e1),eval(e2),&e);
1.75 noro 2930: if ( !e ) i--;
2931: else if ( UNIQ(e) )
2932: m[i-1] = b1;
2933: else
2934: m[i-1] = mkfnode(3,I_BOP,pwrfs,b1,mkfnode(1,I_FORMULA,e));
1.71 noro 2935: }
2936: }
1.75 noro 2937: for ( j = i-1; j >= 0; j-- ) {
2938: MKNODE(r1,m[j],r); r = r1;
2939: }
2940: if ( !UNIQ(c) ) {
2941: cc = mkfnode(1,I_FORMULA,c); MKNODE(r1,cc,r); r = r1;
1.72 noro 2942: }
1.106 noro 2943: return fnode_node_to_nary(mulfs,r);
1.73 noro 2944: }
2945:
1.95 noro 2946: FNODE nfnode_pwr(FNODE f1,FNODE f2,int expand)
1.73 noro 2947: {
1.89 noro 2948: FNODE b,b1,e1,e,cc,r,mf2,mone,inv;
1.108 noro 2949: Obj c,c1;
2950: Num nf2;
1.89 noro 2951: int ee;
2952: NODE arg,n,t0,t1;
1.76 noro 2953: Q q;
1.73 noro 2954:
1.77 noro 2955: if ( IS_ZERO(f2) ) return mkfnode(1,I_FORMULA,ONE);
2956: else if ( IS_ZERO(f1) ) return mkfnode(1,I_FORMULA,0);
1.108 noro 2957: else if ( fnode_is_coef(f1) ) {
1.73 noro 2958: if ( fnode_is_integer(f2) ) {
1.92 noro 2959: if ( fnode_is_one(f2) ) return f1;
2960: else {
1.108 noro 2961: arf_pwr(CO,eval(f1),(Obj)eval(f2),&c);
1.92 noro 2962: return mkfnode(1,I_FORMULA,c);
2963: }
1.108 noro 2964: } else {
2965: f1 = mkfnode(1,I_FORMULA,eval(f1));
1.73 noro 2966: return mkfnode(3,I_BOP,pwrfs,f1,f2);
1.108 noro 2967: }
1.92 noro 2968: } else if ( IS_BINARYPWR(f1) ) {
1.73 noro 2969: b1 = FA1(f1); e1 = FA2(f1);
1.95 noro 2970: e = nfnode_mul(e1,f2,expand);
1.73 noro 2971: if ( fnode_is_one(e) )
2972: return b1;
2973: else
2974: return mkfnode(3,I_BOP,FA0(f1),b1,e);
1.92 noro 2975: } else if ( expand && IS_NARYMUL(f1) && fnode_is_number(f2)
2976: && fnode_is_integer(f2) ) {
1.73 noro 2977: fnode_coef_body(f1,&c1,&b1);
1.89 noro 2978: nf2 = (Num)eval(f2);
1.108 noro 2979: arf_pwr(CO,c1,(Obj)nf2,&c);
1.89 noro 2980: ee = QTOS((Q)nf2);
1.75 noro 2981: cc = mkfnode(1,I_FORMULA,c);
1.89 noro 2982: if ( fnode_is_nonnegative_integer(f2) )
1.103 noro 2983: b = fnode_expand_pwr(b1,ee,expand);
1.89 noro 2984: else {
2985: STOQ(-1,q);
2986: mone = mkfnode(1,I_FORMULA,q);
1.92 noro 2987: b1 = to_narymul(b1);
1.89 noro 2988: for ( t0 = 0, n = (NODE)FA1(b1); n; n = NEXT(n) ) {
2989: inv = mkfnode(3,I_BOP,pwrfs,BDY(n),mone);
2990: MKNODE(t1,inv,t0); t0 = t1;
2991: }
1.106 noro 2992: b1 = fnode_node_to_nary(mulfs,t0);
1.103 noro 2993: b = fnode_expand_pwr(b1,-ee,expand);
1.89 noro 2994: }
1.75 noro 2995: if ( fnode_is_one(cc) )
2996: return b;
2997: else
1.106 noro 2998: return fnode_node_to_nary(mulfs,mknode(2,cc,b));
1.82 noro 2999: } else if ( expand && fnode_is_integer(f2)
3000: && fnode_is_nonnegative_integer(f2) ) {
1.76 noro 3001: q = (Q)eval(f2);
1.95 noro 3002: if ( PL(NM(q)) > 1 ) error("nfnode_pwr : exponent too large");
1.103 noro 3003: return fnode_expand_pwr(f1,QTOS(q),expand);
1.73 noro 3004: } else
3005: return mkfnode(3,I_BOP,pwrfs,f1,f2);
1.72 noro 3006: }
3007:
1.103 noro 3008: FNODE fnode_expand_pwr(FNODE f,int n,int expand)
1.76 noro 3009: {
1.103 noro 3010: int n1,i;
3011: FNODE f1,f2,fn;
3012: Q q;
1.76 noro 3013:
3014: if ( !n ) return mkfnode(1,I_FORMULA,ONE);
1.77 noro 3015: else if ( IS_ZERO(f) ) return mkfnode(1,I_FORMULA,0);
1.76 noro 3016: else if ( n == 1 ) return f;
3017: else {
1.103 noro 3018: switch ( expand ) {
3019: case 1:
3020: n1 = n/2;
3021: f1 = fnode_expand_pwr(f,n1,expand);
3022: f2 = nfnode_mul(f1,f1,expand);
3023: if ( n%2 ) f2 = nfnode_mul(f2,f,1);
3024: return f2;
3025: case 2:
3026: for ( i = 1, f1 = f; i < n; i++ )
3027: f1 = nfnode_mul(f1,f,expand);
3028: return f1;
3029: case 0: default:
3030: STOQ(n,q);
3031: fn = mkfnode(1,I_FORMULA,q);
3032: return mkfnode(3,I_BOP,pwrfs,f,fn);
3033: }
1.76 noro 3034: }
3035: }
3036:
1.72 noro 3037: /* f = b^e */
3038: void fnode_base_exp(FNODE f,FNODE *bp,FNODE *ep)
3039: {
1.75 noro 3040: if ( IS_BINARYPWR(f) ) {
1.72 noro 3041: *bp = FA1(f); *ep = FA2(f);
3042: } else {
3043: *bp = f; *ep = mkfnode(1,I_FORMULA,ONE);
3044: }
3045: }
3046:
3047: FNODE to_naryadd(FNODE f)
3048: {
3049: FNODE r;
3050: NODE n;
3051:
1.75 noro 3052: if ( IS_NARYADD(f) ) return f;
3053:
3054: NEWFNODE(r,2); r->id = I_NARYOP;
3055: FA0(r) = addfs; MKNODE(n,f,0); FA1(r) = n;
1.72 noro 3056: return r;
3057: }
3058:
3059: FNODE to_narymul(FNODE f)
3060: {
3061: FNODE r;
3062: NODE n;
3063:
1.75 noro 3064: if ( IS_NARYMUL(f) ) return f;
3065:
3066: NEWFNODE(r,2); r->id = I_NARYOP;
3067: FA0(r) = mulfs; MKNODE(n,f,0); FA1(r) = n;
1.72 noro 3068: return r;
3069: }
3070:
1.108 noro 3071: FNODE nfnode_mul_coef(Obj c,FNODE f,int expand)
1.72 noro 3072: {
1.76 noro 3073: FNODE b1,cc;
1.108 noro 3074: Obj c1,c2;
1.76 noro 3075: NODE n,r,r0;
1.72 noro 3076:
3077: if ( !c )
3078: return mkfnode(I_FORMULA,0);
1.75 noro 3079: else {
3080: fnode_coef_body(f,&c1,&b1);
1.108 noro 3081: arf_mul(CO,c,c1,&c2);
1.75 noro 3082: if ( UNIQ(c2) ) return b1;
3083: else {
3084: cc = mkfnode(1,I_FORMULA,c2);
3085: if ( fnode_is_number(b1) ) {
3086: if ( !fnode_is_one(b1) )
1.95 noro 3087: error("nfnode_mul_coef : cannot happen");
1.75 noro 3088: else
3089: return cc;
1.76 noro 3090: } else if ( IS_NARYMUL(b1) ) {
1.75 noro 3091: MKNODE(n,cc,FA1(b1));
1.106 noro 3092: return fnode_node_to_nary(mulfs,n);
1.76 noro 3093: } else if ( expand && IS_NARYADD(b1) ) {
3094: for ( r0 = 0, n = (NODE)FA1(b1); n; n = NEXT(n) ) {
3095: NEXTNODE(r0,r);
1.95 noro 3096: BDY(r) = nfnode_mul_coef(c2,BDY(n),expand);
1.76 noro 3097: }
3098: if ( r0 ) NEXT(r) = 0;
1.106 noro 3099: return fnode_node_to_nary(addfs,r0);
1.76 noro 3100: } else
1.106 noro 3101: return fnode_node_to_nary(mulfs,mknode(2,cc,b1));
1.72 noro 3102: }
1.71 noro 3103: }
3104: }
3105:
1.108 noro 3106: void fnode_coef_body(FNODE f,Obj *cp,FNODE *bp)
1.70 noro 3107: {
1.72 noro 3108: FNODE c;
1.70 noro 3109:
1.108 noro 3110: if ( fnode_is_coef(f) ) {
3111: *cp = (Obj)eval(f); *bp = mkfnode(1,I_FORMULA,ONE);
1.75 noro 3112: } else if ( IS_NARYMUL(f) ) {
3113: c=(FNODE)BDY((NODE)FA1(f));
1.108 noro 3114: if ( fnode_is_coef(c) ) {
3115: *cp = (Obj)eval(c);
1.106 noro 3116: *bp = fnode_node_to_nary(mulfs,NEXT((NODE)FA1(f)));
1.70 noro 3117: } else {
1.108 noro 3118: *cp = (Obj)ONE; *bp = f;
1.70 noro 3119: }
3120: } else {
1.108 noro 3121: *cp = (Obj)ONE; *bp = f;
1.70 noro 3122: }
1.80 noro 3123: }
3124:
1.95 noro 3125: int nfnode_comp_pwr(FNODE f1,FNODE f2);
1.80 noro 3126:
1.109 ! noro 3127: int nfnode_weight(struct wtab *tab,FNODE f)
! 3128: {
! 3129: NODE n;
! 3130: int w,w1;
! 3131: int i;
! 3132: Q a2;
! 3133: V v;
! 3134:
! 3135: switch ( f->id ) {
! 3136: case I_FORMULA:
! 3137: if ( fnode_is_coef(f) ) return 0;
! 3138: else if ( fnode_is_var(f) ) {
! 3139: v = VR((P)FA0(f));
! 3140: for ( i = 0; tab[i].v; i++ )
! 3141: if ( v == tab[i].v ) return tab[i].w;
! 3142: return w;
! 3143: } else return 0;
! 3144:
! 3145: /* XXX */
! 3146: case I_PVAR: return 1;
! 3147: /* XXX */
! 3148: case I_FUNC: I_FUNC: I_FUNC_QARG:
! 3149: /* w(f) = 1 */
! 3150: /* w(f(a1,...,an)=w(a1)+...+w(an) */
! 3151: n = FA0((FNODE)FA1(f));
! 3152: for ( w = 0; n; n = NEXT(n) )
! 3153: w += nfnode_weight(tab,BDY(n));
! 3154: return w;
! 3155: case I_NARYOP:
! 3156: n = (NODE)FA1(f);
! 3157: if ( IS_NARYADD(f) )
! 3158: for ( w = nfnode_weight(tab,BDY(n)),
! 3159: n = NEXT(n); n; n = NEXT(n) ) {
! 3160: w1 = nfnode_weight(tab,BDY(n));
! 3161: w = MAX(w,w1);
! 3162: }
! 3163: else
! 3164: for ( w = 0; n; n = NEXT(n) )
! 3165: w += nfnode_weight(tab,BDY(n));
! 3166: return w;
! 3167: case I_BOP:
! 3168: /* must be binary power */
! 3169: /* XXX w(2^x)=0 ? */
! 3170: if ( fnode_is_rational(FA2(f)) ) {
! 3171: a2 = (Q)eval(FA2(f));
! 3172: w = QTOS(a2);
! 3173: } else
! 3174: w = nfnode_weight(tab,FA2(f));
! 3175: return nfnode_weight(tab,FA1(f))*w;
! 3176: default:
! 3177: error("nfnode_weight : not_implemented");
! 3178: }
! 3179: }
! 3180:
1.95 noro 3181: int nfnode_comp(FNODE f1,FNODE f2)
1.80 noro 3182: {
3183: NODE n1,n2;
1.95 noro 3184: int r,i1,i2,ret;
1.82 noro 3185: char *nm1,*nm2;
1.95 noro 3186: FNODE b1,b2,e1,e2,g,a1,a2,fn1,fn2;
1.108 noro 3187: Num ee,ee1;
3188: Obj c1,c2;
1.109 ! noro 3189: int w1,w2;
! 3190:
! 3191: if ( qt_weight_tab ) {
! 3192: w1 = nfnode_weight(qt_weight_tab,f1);
! 3193: w2 = nfnode_weight(qt_weight_tab,f2);
! 3194: if ( w1 > w2 ) return 1;
! 3195: if ( w1 < w2 ) return -1;
! 3196: }
1.80 noro 3197:
3198: if ( IS_NARYADD(f1) || IS_NARYADD(f2) ) {
3199: f1 = to_naryadd(f1); f2 = to_naryadd(f2);
3200: n1 = (NODE)FA1(f1); n2 = (NODE)FA1(f2);
3201: while ( n1 && n2 )
1.95 noro 3202: if ( r = nfnode_comp(BDY(n1),BDY(n2)) ) return r;
1.80 noro 3203: else {
3204: n1 = NEXT(n1); n2 = NEXT(n2);
3205: }
1.85 noro 3206: return n1?1:(n2?-1:0);
1.80 noro 3207: }
3208: if ( IS_NARYMUL(f1) || IS_NARYMUL(f2) ) {
1.83 noro 3209: fnode_coef_body(f1,&c1,&b1);
3210: fnode_coef_body(f2,&c2,&b2);
1.108 noro 3211: if ( !compfnode(b1,b2) ) return arf_comp(CO,c1,c2);
1.83 noro 3212: b1 = to_narymul(b1); b2 = to_narymul(b2);
3213: n1 = (NODE)FA1(b1); n2 = (NODE)FA1(b2);
1.80 noro 3214: while ( 1 ) {
3215: while ( n1 && n2 && !compfnode(BDY(n1),BDY(n2)) ) {
3216: n1 = NEXT(n1); n2 = NEXT(n2);
3217: }
3218: if ( !n1 || !n2 ) {
1.85 noro 3219: return n1?1:(n2?-1:0);
1.80 noro 3220: }
3221: fnode_base_exp(BDY(n1),&b1,&e1);
3222: fnode_base_exp(BDY(n2),&b2,&e2);
3223:
1.95 noro 3224: if ( r = nfnode_comp(b1,b2) ) {
1.83 noro 3225: if ( r > 0 )
1.95 noro 3226: return nfnode_comp(e1,mkfnode(1,I_FORMULA,0));
1.83 noro 3227: else if ( r < 0 )
1.95 noro 3228: return nfnode_comp(mkfnode(1,I_FORMULA,0),e2);
1.83 noro 3229: } else {
3230: n1 = NEXT(n1); n2 = NEXT(n2);
3231: if ( fnode_is_number(e1) && fnode_is_number(e2) ) {
3232: /* f1 = t b^e1 ... , f2 = t b^e2 ... */
3233: subnum(0,eval(e1),eval(e2),&ee);
1.86 noro 3234: r = compnum(0,ee,0);
3235: if ( r > 0 ) {
1.83 noro 3236: g = mkfnode(3,I_BOP,pwrfs,b1,mkfnode(1,I_FORMULA,ee));
3237: MKNODE(n1,g,n1);
1.86 noro 3238: } else if ( r < 0 ) {
3239: chsgnnum(ee,&ee1);
3240: g = mkfnode(3,I_BOP,pwrfs,b1,mkfnode(1,I_FORMULA,ee1));
3241: MKNODE(n2,g,n2);
1.83 noro 3242: }
3243: } else {
1.95 noro 3244: r = nfnode_comp(e1,e2);
1.83 noro 3245: if ( r > 0 ) return 1;
3246: else if ( r < 0 ) return -1;
1.80 noro 3247: }
3248: }
3249: }
3250: }
3251: if ( IS_BINARYPWR(f1) || IS_BINARYPWR(f2) )
1.95 noro 3252: return nfnode_comp_pwr(f1,f2);
1.80 noro 3253:
1.95 noro 3254: /* now, IDs of f1 and f2 must be I_FORMULA, I_FUNC, I_IFUNC or I_PVAR */
1.106 noro 3255: /* I_IFUNC > I_PVAR > I_FUNC=I_FUNC_QARG > I_FORMULA */
1.80 noro 3256: switch ( f1->id ) {
3257: case I_FORMULA:
3258: switch ( f2->id ) {
3259: case I_FORMULA:
1.105 noro 3260: return arf_comp(qt_current_ord?qt_current_ord:CO,FA0(f1),FA0(f2));
1.95 noro 3261: case I_FUNC: case I_IFUNC: case I_PVAR:
1.80 noro 3262: return -1;
3263: default:
1.95 noro 3264: error("nfnode_comp : undefined");
1.80 noro 3265: }
3266: break;
1.106 noro 3267: case I_FUNC: case I_FUNC_QARG:
1.80 noro 3268: switch ( f2->id ) {
3269: case I_FORMULA:
3270: return 1;
1.95 noro 3271: case I_PVAR: case I_IFUNC:
3272: return -1;
1.106 noro 3273: case I_FUNC: case I_FUNC_QARG:
1.82 noro 3274: nm1 = ((FUNC)FA0(f1))->name; nm2 = ((FUNC)FA0(f2))->name;
3275: r = strcmp(nm1,nm2);
3276: if ( r > 0 ) return 1;
3277: else if ( r < 0 ) return -1;
1.80 noro 3278: else {
3279: /* compare args */
3280: n1 = FA0((FNODE)FA1(f1)); n2 = FA0((FNODE)FA1(f2));
3281: while ( n1 && n2 )
1.95 noro 3282: if ( r = nfnode_comp(BDY(n1),BDY(n2)) ) return r;
1.82 noro 3283: else {
3284: n1 = NEXT(n1); n2 = NEXT(n2);
3285: }
1.85 noro 3286: return n1?1:(n2?-1:0);
1.80 noro 3287: }
3288: break;
3289: default:
1.95 noro 3290: error("nfnode_comp : undefined");
1.80 noro 3291: }
3292: case I_PVAR:
3293: switch ( f2->id ) {
1.106 noro 3294: case I_FORMULA: case I_FUNC: case I_FUNC_QARG:
1.80 noro 3295: return 1;
1.95 noro 3296: case I_IFUNC:
3297: return -1;
1.80 noro 3298: case I_PVAR:
3299: i1 = (int)FA0(f1); i2 = (int)FA0(f2);
3300: if ( i1 > i2 ) return 1;
3301: else if ( i1 < i2 ) return -1;
3302: else return 0;
3303: default:
1.95 noro 3304: error("nfnode_comp : undefined");
3305: }
3306: break;
3307: case I_IFUNC:
3308: switch ( f2->id ) {
1.106 noro 3309: case I_FORMULA: case I_FUNC: case I_FUNC_QARG: case I_PVAR:
1.95 noro 3310: return 1;
3311: case I_IFUNC:
3312: i1 = (int)FA0((FNODE)FA0(f1));
3313: i2 = (int)FA0((FNODE)FA0(f2));
3314: if ( i1 > i2 ) return 1;
3315: else if ( i1 < i2 ) return -1;
3316: else {
3317: /* compare args */
3318: n1 = FA0((FNODE)FA1(f1)); n2 = FA0((FNODE)FA1(f2));
3319: while ( n1 && n2 )
3320: if ( r = nfnode_comp(BDY(n1),BDY(n2)) ) return r;
3321: else {
3322: n1 = NEXT(n1); n2 = NEXT(n2);
3323: }
3324: return n1?1:(n2?-1:0);
3325: }
3326: break;
3327:
3328: default:
3329: error("nfnode_comp : undefined");
1.80 noro 3330: }
3331: break;
3332: default:
1.95 noro 3333: error("nfnode_comp : undefined");
1.80 noro 3334: }
3335: }
3336:
1.95 noro 3337: int nfnode_comp_pwr(FNODE f1,FNODE f2)
1.80 noro 3338: {
3339: FNODE b1,b2,e1,e2;
3340: int r;
3341:
3342: fnode_base_exp(f1,&b1,&e1);
3343: fnode_base_exp(f2,&b2,&e2);
1.95 noro 3344: if ( r = nfnode_comp(b1,b2) ) {
1.83 noro 3345: if ( r > 0 )
1.95 noro 3346: return nfnode_comp(e1,mkfnode(1,I_FORMULA,0));
1.83 noro 3347: else if ( r < 0 )
1.95 noro 3348: return nfnode_comp(mkfnode(1,I_FORMULA,0),e2);
3349: } else return nfnode_comp(e1,e2);
1.70 noro 3350: }
1.87 noro 3351:
1.88 noro 3352: NODE append_node(NODE a1,NODE a2)
3353: {
3354: NODE t,t0;
3355:
3356: if ( !a1 )
3357: return a2;
3358: else {
3359: for ( t0 = 0; a1; a1 = NEXT(a1) ) {
3360: NEXTNODE(t0,t); BDY(t) = BDY(a1);
3361: }
3362: NEXT(t) = a2;
3363: return t0;
3364: }
3365: }
3366:
1.95 noro 3367: int nfnode_match(FNODE f,FNODE pat,NODE *rp)
1.87 noro 3368: {
3369: NODE m,m1,m2,base,exp,fa,pa,n;
3370: LIST l;
3371: QUOTE qp,qf;
1.96 noro 3372: FNODE fbase,fexp,a,fh;
1.87 noro 3373: FUNC ff,pf;
3374: int r;
3375:
1.97 noro 3376: if ( !pat )
3377: if ( !f ) {
3378: *rp = 0;
3379: return 1;
3380: } else
3381: return 0;
3382: else if ( !f )
3383: return 0;
1.87 noro 3384: switch ( pat->id ) {
3385: case I_PVAR:
3386: /* [[pat,f]] */
1.103 noro 3387: *rp = mknode(1,mknode(2,(int)FA0(pat),f));
1.87 noro 3388: return 1;
3389:
3390: case I_FORMULA:
1.93 noro 3391: if ( f->id == I_FORMULA && !arf_comp(CO,(Obj)FA0(f),(Obj)FA0(pat)) ) {
1.87 noro 3392: *rp = 0; return 1;
3393: } else
3394: return 0;
3395:
3396: case I_BOP:
3397: /* OPNAME should be "^" */
3398: if ( !IS_BINARYPWR(pat) )
1.95 noro 3399: error("nfnode_match : invalid BOP");
1.87 noro 3400: if ( IS_BINARYPWR(f) ) {
3401: fbase = FA1(f); fexp = FA2(f);
3402: } else {
3403: fbase = f; fexp = mkfnode(1,I_FORMULA,ONE);
3404: }
1.95 noro 3405: if ( !nfnode_match(fbase,FA1(pat),&base) ) return 0;
1.106 noro 3406: a = rewrite_fnode(FA2(pat),base,0);
1.95 noro 3407: if ( !nfnode_match(fexp,a,&exp) ) return 0;
1.88 noro 3408: else {
3409: *rp = append_node(base,exp);
3410: return 1;
3411: }
1.87 noro 3412: break;
3413:
1.95 noro 3414: case I_FUNC: case I_IFUNC:
1.87 noro 3415: if ( f->id != I_FUNC ) return 0;
1.95 noro 3416: ff = (FUNC)FA0(f);
3417: if ( pat->id == I_FUNC ) {
3418: pf = (FUNC)FA0(pat);
3419: if ( strcmp(ff->fullname,pf->fullname) ) return 0;
3420: m = 0;
3421: } else {
1.96 noro 3422: /* XXX : I_FUNC_HEAD is a dummy id to pass FUNC */
3423: fh = mkfnode(1,I_FUNC_HEAD,FA0(f));
3424: m = mknode(1,mknode(2,FA0((FNODE)FA0(pat)),fh),0);
1.95 noro 3425: }
1.87 noro 3426: /* FA1(f) and FA1(pat) are I_LIST */
3427: fa = (NODE)FA0((FNODE)FA1(f));
3428: pa = (NODE)FA0((FNODE)FA1(pat));
3429: while ( fa && pa ) {
1.106 noro 3430: a = rewrite_fnode(BDY(pa),m,0);
1.95 noro 3431: if ( !nfnode_match(BDY(fa),a,&m1) ) return 0;
1.88 noro 3432: m = append_node(m1,m);
3433: fa = NEXT(fa); pa = NEXT(pa);
1.87 noro 3434: }
3435: if ( fa || pa ) return 0;
3436: else {
3437: *rp = m;
3438: return 1;
3439: }
3440:
3441: case I_NARYOP:
3442: if ( IS_NARYADD(pat) )
1.95 noro 3443: return nfnode_match_naryadd(f,pat,rp);
1.87 noro 3444: else if ( IS_NARYMUL(pat) )
1.95 noro 3445: return nfnode_match_narymul(f,pat,rp);
1.87 noro 3446: else
1.95 noro 3447: error("nfnode_match : invalid NARYOP");
1.87 noro 3448: break;
3449:
3450: default:
1.95 noro 3451: error("nfnode_match : invalid pattern");
1.87 noro 3452: }
3453: }
3454:
1.88 noro 3455: /* remove i-th element */
1.87 noro 3456:
1.88 noro 3457: FNODE fnode_removeith_naryadd(FNODE p,int i)
3458: {
3459: int k,l;
3460: NODE t,r0,r,a;
3461:
3462: a = (NODE)FA1(p);
3463: l = length(a);
3464: if ( i < 0 || i >= l ) error("fnode_removeith_naryadd: invalid index");
3465: else if ( i == 0 )
1.106 noro 3466: return fnode_node_to_nary(addfs,NEXT(a));
1.88 noro 3467: else {
3468: for ( r0 = 0, k = 0, t = a; k < i; k++, t = NEXT(t) ) {
3469: NEXTNODE(r0,r);
3470: BDY(r) = BDY(t);
3471: }
1.94 noro 3472: NEXT(r) = NEXT(t);
1.106 noro 3473: return fnode_node_to_nary(addfs,r0);
1.88 noro 3474: }
3475:
3476: }
1.87 noro 3477:
1.88 noro 3478: /* a0,...,a(i-1) */
3479: FNODE fnode_left_narymul(FNODE p,int i)
1.87 noro 3480: {
1.88 noro 3481: int k,l;
3482: NODE t,r0,r,a;
3483:
3484: a = (NODE)FA1(p);
3485: l = length(a);
3486: if ( i < 0 || i >= l ) error("fnode_left_narymul : invalid index");
1.97 noro 3487: if ( i == 0 ) return 0;
1.88 noro 3488: else if ( i == 1 ) return (FNODE)BDY(a);
3489: else {
3490: for ( r0 = 0, k = 0, t = a; k < i; k++, t = NEXT(t) ) {
3491: NEXTNODE(r0,r);
3492: BDY(r) = BDY(t);
3493: }
3494: NEXT(r) = 0;
1.106 noro 3495: return fnode_node_to_nary(mulfs,r0);
1.88 noro 3496: }
3497: }
3498:
3499: /* a(i+1),...,a(l-1) */
3500: FNODE fnode_right_narymul(FNODE p,int i)
3501: {
3502: NODE a,t;
3503: int l,k;
3504:
3505: a = (NODE)FA1(p);
3506: l = length(a);
3507: if ( i < 0 || i >= l ) error("fnode_right_narymul : invalid index");
1.97 noro 3508: if ( i == l-1 ) return 0;
1.88 noro 3509: else {
3510: for ( k = 0, t = a; k <= i; k++, t = NEXT(t) );
1.106 noro 3511: return fnode_node_to_nary(mulfs,t);
1.88 noro 3512: }
3513: }
3514:
1.95 noro 3515: int nfnode_match_naryadd(FNODE f,FNODE p,NODE *rp)
1.88 noro 3516: {
3517: int fl,pl,fi,pi;
3518: NODE fa,pa,t,s,m,m1;
3519: FNODE fr,pr,prr,pivot;
1.87 noro 3520:
3521: f = to_naryadd(f);
1.88 noro 3522: fa = (NODE)FA1(f); fl = length(fa);
3523: pa = (NODE)FA1(p); pl = length(pa);
3524: if ( fl < pl ) return 0;
3525: else if ( pl == 1 ) {
3526: if ( fl == 1 )
1.95 noro 3527: return nfnode_match(BDY(fa),BDY(pa),rp);
1.87 noro 3528: else
3529: return 0;
3530: } else {
1.88 noro 3531: for ( t = pa, pi = 0; t; t = NEXT(t), pi++ )
3532: if ( ((FNODE)BDY(t))->id != I_PVAR ) break;
3533: if ( !t ) {
3534: /* all are I_PVAR */
3535: m = 0;
3536: for ( t = pa, s = fa; NEXT(t); t = NEXT(t), s = NEXT(s) ) {
1.95 noro 3537: nfnode_match(BDY(s),BDY(t),&m1);
1.88 noro 3538: m = append_node(m1,m);
3539: }
3540: if ( !NEXT(s) )
3541: fr = (FNODE)BDY(s);
3542: else
3543: fr = mkfnode(2,I_NARYOP,FA0(f),s);
1.95 noro 3544: nfnode_match(fr,BDY(t),&m1);
1.88 noro 3545: *rp = append_node(m1,m);
3546: return 1;
3547: } else {
3548: pivot = (FNODE)BDY(t);
3549: pr = fnode_removeith_naryadd(p,pi);
3550: for ( s = fa, fi = 0; s; s = NEXT(s), fi++ ) {
1.95 noro 3551: if ( nfnode_match(BDY(s),pivot,&m) ) {
1.88 noro 3552: fr = fnode_removeith_naryadd(f,fi);
1.106 noro 3553: prr = rewrite_fnode(pr,m,0);
1.95 noro 3554: if ( nfnode_match(fr,prr,&m1) ) {
1.88 noro 3555: *rp = append_node(m,m1);
3556: return 1;
3557: }
3558: }
3559: }
3560: return 0;
3561: }
1.87 noro 3562: }
3563: }
3564:
1.95 noro 3565: int nfnode_match_narymul(FNODE f,FNODE p,NODE *rp)
1.88 noro 3566: {
3567: int fl,pl,fi,pi;
3568: NODE fa,pa,t,s,m,m1;
3569: FNODE fr,pr,pleft,pleft1,pright,pright1,fleft,fright,pivot;
3570:
3571: f = to_narymul(f);
3572: fa = (NODE)FA1(f); fl = length(fa);
3573: pa = (NODE)FA1(p); pl = length(pa);
3574: if ( fl < pl ) return 0;
3575: else if ( pl == 1 ) {
3576: if ( fl == 1 )
1.95 noro 3577: return nfnode_match(BDY(fa),BDY(pa),rp);
1.88 noro 3578: else
3579: return 0;
3580: } else {
3581: for ( t = pa, pi = 0; t; t = NEXT(t), pi++ )
3582: if ( ((FNODE)BDY(t))->id != I_PVAR ) break;
3583: if ( !t ) {
3584: /* all are I_PVAR */
3585: m = 0;
3586: for ( t = pa, s = fa; NEXT(t); t = NEXT(t), s = NEXT(s) ) {
1.106 noro 3587: pr = rewrite_fnode(BDY(t),m,0);
1.95 noro 3588: if ( !nfnode_match(BDY(s),pr,&m1) ) return 0;
1.88 noro 3589: m = append_node(m1,m);
3590: }
3591: if ( !NEXT(s) )
3592: fr = (FNODE)BDY(s);
3593: else
3594: fr = mkfnode(2,I_NARYOP,FA0(f),s);
1.106 noro 3595: pr = rewrite_fnode(BDY(t),m,0);
1.95 noro 3596: if ( !nfnode_match(fr,pr,&m1) ) return 0;
1.88 noro 3597: *rp = append_node(m1,m);
3598: return 1;
3599: } else {
3600: pivot = (FNODE)BDY(t);
3601: pleft = fnode_left_narymul(p,pi);
3602: pright = fnode_right_narymul(p,pi);
3603: /* XXX : incomplete */
3604: for ( s = fa, fi = 0; s; s = NEXT(s), fi++ ) {
1.97 noro 3605: if ( fi < pi ) continue;
1.95 noro 3606: if ( nfnode_match(BDY(s),pivot,&m) ) {
1.88 noro 3607: fleft = fnode_left_narymul(f,fi);
1.106 noro 3608: pleft1 = rewrite_fnode(pleft,m,0);
1.95 noro 3609: if ( nfnode_match(fleft,pleft1,&m1) ) {
1.88 noro 3610: m = append_node(m1,m);
3611: fright = fnode_right_narymul(f,fi);
1.106 noro 3612: pright1 = rewrite_fnode(pright,m,0);
1.95 noro 3613: if ( nfnode_match(fright,pright1,&m1) ) {
1.88 noro 3614: *rp = append_node(m1,m);
3615: return 1;
3616: }
3617: }
3618: }
3619: }
3620: return 0;
3621: }
1.95 noro 3622: }
3623: }
3624:
3625: NODE nfnode_pvars(FNODE pat,NODE found)
3626: {
3627: int ind;
3628: NODE prev,t;
3629: int *pair;
3630:
3631: switch ( pat->id ) {
3632: case I_PVAR:
3633: ind = (int)FA0(pat);
3634: for ( prev = 0, t = found; t; prev = t, t = NEXT(t) ) {
3635: pair = (int *)BDY(t);
3636: if ( pair[0] == ind ) {
3637: pair[1]++;
3638: return found;
3639: }
3640: }
3641: pair = (int *)MALLOC_ATOMIC(sizeof(int)*2);
3642: pair[0] = ind; pair[1] = 1;
3643: if ( !prev )
3644: MKNODE(found,pair,0);
3645: else
3646: MKNODE(NEXT(prev),pair,0);
3647: return found;
3648:
3649: case I_FORMULA:
3650: return found;
3651:
3652: case I_BOP:
3653: /* OPNAME should be "^" */
3654: if ( !IS_BINARYPWR(pat) )
3655: error("nfnode_pvar : invalid BOP");
3656: found = nfnode_pvars(FA1(pat),found);
3657: found = nfnode_pvars(FA2(pat),found);
3658: return found;
3659:
3660: case I_FUNC:
3661: t = (NODE)FA0((FNODE)FA1(pat));
3662: for ( ; t; t = NEXT(t) )
3663: found = nfnode_pvars(BDY(t),found);
3664: return found;
3665:
3666: case I_NARYOP:
3667: t = (NODE)FA1(pat);
3668: for ( ; t; t = NEXT(t) )
3669: found = nfnode_pvars(BDY(t),found);
3670: return found;
3671:
3672: default:
3673: error("nfnode_match : invalid pattern");
1.88 noro 3674: }
3675: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>