Rev 5822 | Rev 8155 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 5822 | Rev 7673 | ||
---|---|---|---|
Line 46... | Line 46... | ||
46 | { |
46 | { |
47 | va_list vp; |
47 | va_list vp; |
48 | char buf[MAX_LINELEN+1]; |
48 | char buf[MAX_LINELEN+1]; |
49 | 49 | ||
50 | va_start(vp,s); vsnprintf(buf,sizeof(buf),s,vp); va_end(vp); |
50 | va_start(vp,s); vsnprintf(buf,sizeof(buf),s,vp); va_end(vp); |
51 | if(strlen(buf)+strlen(texmathbuf)>=MAX_LINELEN) |
51 | if(strlen(buf)+strlen(texmathbuf)>=MAX_LINELEN) |
52 | user_error("cmd_output_too_long"); |
52 | user_error("cmd_output_too_long"); |
53 | strcat(texmathbuf,buf); |
53 | strcat(texmathbuf,buf); |
54 | } |
54 | } |
55 | /* transforms sum(n,n=1..infinity) , product(n/(n+1),n=1..infinity). */ |
55 | /* transforms sum(n,n=1..infinity) , product(n/(n+1),n=1..infinity). */ |
56 | void _tex_sums(char *p, char *name, int type) |
56 | void _tex_sums(char *p, char *name, int type) |
Line 203... | Line 203... | ||
203 | 203 | ||
204 | /* find the end of an additive term. */ |
204 | /* find the end of an additive term. */ |
205 | char *find_term_end(char *p) |
205 | char *find_term_end(char *p) |
206 | { |
206 | { |
207 | char *pp; |
207 | char *pp; |
208 | pp=p; |
208 | pp=p; |
209 | if(*pp==',' || *pp==';' || *pp=='=' || *pp=='<') pp++; |
209 | if(*pp==',' || *pp==';' || *pp=='=' || *pp=='<') pp++; |
210 | while(*pp=='+' || *pp=='-' || *pp=='=' || *pp=='>') pp++; |
210 | while(*pp=='+' || *pp=='-' || *pp=='=' || *pp=='>') pp++; |
211 | for(;*pp;pp++) { |
211 | for(;*pp;pp++) { |
212 | switch(*pp) { |
212 | switch(*pp) { |
213 | case '(': pp=find_matching(pp+1,')'); goto loopend; |
213 | case '(': pp=find_matching(pp+1,')'); goto loopend; |
214 | case '[': pp=find_matching(pp+1,']'); goto loopend; |
214 | case '[': pp=find_matching(pp+1,']'); goto loopend; |
215 | /* case '{': pp=find_matching(pp+1,'}'); goto loopend;*/ |
215 | /* case '{': pp=find_matching(pp+1,'}'); goto loopend;*/ |
216 | 216 | ||
217 | case 0: |
217 | case 0: |
218 | case '<': |
218 | case '<': |
219 | case '>': |
219 | case '>': |
220 | case ',': |
220 | case ',': |
221 | case ';': |
221 | case ';': |
Line 252... | Line 252... | ||
252 | for(;*pp;pp++) { |
252 | for(;*pp;pp++) { |
253 | switch(*pp) { |
253 | switch(*pp) { |
254 | case '(': pp=find_matching(pp+1,')'); goto loopend; |
254 | case '(': pp=find_matching(pp+1,')'); goto loopend; |
255 | case '[': pp=find_matching(pp+1,']'); goto loopend; |
255 | case '[': pp=find_matching(pp+1,']'); goto loopend; |
256 | /* case '{': pp=find_matching(pp+1,'}'); goto loopend;*/ |
256 | /* case '{': pp=find_matching(pp+1,'}'); goto loopend;*/ |
257 | 257 | ||
258 | case 0: |
258 | case 0: |
259 | case '<': |
259 | case '<': |
260 | case '>': |
260 | case '>': |
261 | case ',': |
261 | case ',': |
262 | case ';': |
262 | case ';': |
Line 266... | Line 266... | ||
266 | case '}': |
266 | case '}': |
267 | case '+': |
267 | case '+': |
268 | case '-': |
268 | case '-': |
269 | case '*': |
269 | case '*': |
270 | case '/': return pp; |
270 | case '/': return pp; |
271 | 271 | ||
272 | case '^': { |
272 | case '^': { |
273 | while(*(pp+1)=='+' || *(pp+1)=='-') pp++; |
273 | while(*(pp+1)=='+' || *(pp+1)=='-') pp++; |
274 | goto loopend; |
274 | goto loopend; |
275 | } |
275 | } |
276 | } |
276 | } |
Line 281... | Line 281... | ||
281 | loopend: |
281 | loopend: |
282 | if(pp==NULL) module_error("unmatched_parentheses"); |
282 | if(pp==NULL) module_error("unmatched_parentheses"); |
283 | } |
283 | } |
284 | return pp; |
284 | return pp; |
285 | } |
285 | } |
286 | 286 | ||
287 | /* returns the number of terms */ |
287 | /* returns the number of terms */ |
288 | int term_cnt(char *p) |
288 | int term_cnt(char *p) |
289 | { |
289 | { |
290 | char *pe, *pp; |
290 | char *pe, *pp; |
291 | int i; |
291 | int i; |
292 | 292 | ||
293 | pe=p+strlen(p); |
293 | pe=p+strlen(p); |
294 | for(i=0,pp=p;pp<pe;pp=find_term_end(pp),i++); |
294 | for(i=0,pp=p;pp<pe;pp=find_term_end(pp),i++); |
295 | return i; |
295 | return i; |
296 | } |
296 | } |
297 | 297 | ||
298 | /* Print a number: transform 4E+05 in 4 \times 10^{5} and 4E-05 in 4 \times 10^{-5} |
298 | /* Print a number: transform 4E+05 in 4 \times 10^{5} and 4E-05 in 4 \times 10^{-5} |
299 | suppress multiple + or 0 ; see rawmath.c |
299 | suppress multiple + or 0 ; see rawmath.c |
300 | */ |
300 | */ |
301 | void putnumber(char *p) |
301 | void putnumber(char *p) |
Line 305... | Line 305... | ||
305 | *pp++ = 0; |
305 | *pp++ = 0; |
306 | if (*pp == '-') { sgn = "-"; pp++; } |
306 | if (*pp == '-') { sgn = "-"; pp++; } |
307 | while (*pp == '0' || *pp == '+') pp++; |
307 | while (*pp == '0' || *pp == '+') pp++; |
308 | tprint("%s \\times 10^{%s%s}", p, sgn, pp); |
308 | tprint("%s \\times 10^{%s%s}", p, sgn, pp); |
309 | } |
309 | } |
310 | 310 | ||
311 | /* Print a variable name ; transform abc475 in abc_475 */ |
311 | /* Print a variable name ; transform abc475 in abc_475 */ |
312 | void putvar(char *p) |
312 | void putvar(char *p) |
313 | { |
313 | { |
314 | char vbuf[1024]; |
314 | char vbuf[1024]; |
315 | char *pp, *p2; |
315 | char *pp, *p2; |
316 | int i; |
316 | int i; |
317 | 317 | ||
318 | vbuf[0]=0; |
318 | vbuf[0]=0; |
319 | if(*(p+1)==0) {tprint("%c",*p); return;} |
319 | if(*(p+1)==0) {tprint("%c",*p); return;} |
320 | for(pp=p;isalpha(*pp);pp++); |
320 | for(pp=p;isalpha(*pp);pp++); |
321 | if(myisdigit(*pp)) { |
321 | if(myisdigit(*pp)) { |
322 | for(p2=pp+1;myisdigit(*p2);p2++); |
322 | for(p2=pp+1;myisdigit(*p2);p2++); |
Line 336... | Line 336... | ||
336 | /* sort according to type */ |
336 | /* sort according to type */ |
337 | int fsort(const void *p1, const void *p2) |
337 | int fsort(const void *p1, const void *p2) |
338 | { |
338 | { |
339 | struct afactor *t1, *t2; |
339 | struct afactor *t1, *t2; |
340 | int i1,i2; |
340 | int i1,i2; |
341 | 341 | ||
342 | t1=*(struct afactor **) p1; t2=*(struct afactor **) p2; |
342 | t1=*(struct afactor **) p1; t2=*(struct afactor **) p2; |
343 | i1=t1->type; i2=t2->type; |
343 | i1=t1->type; i2=t2->type; |
344 | if(i1>type_var) i1=type_var; if(i2>type_var) i2=type_var; |
344 | if(i1>type_var) i1=type_var; if(i2>type_var) i2=type_var; |
345 | return i1-i2; |
345 | return i1-i2; |
346 | } |
346 | } |
Line 348... | Line 348... | ||
348 | void t_oneterm(char *p, int num) |
348 | void t_oneterm(char *p, int num) |
349 | { |
349 | { |
350 | int sign, fcnt, s, i, dentype, rel; |
350 | int sign, fcnt, s, i, dentype, rel; |
351 | char *pp, *pe, *pt; |
351 | char *pp, *pe, *pt; |
352 | struct afactor factors[MAX_FACTORS]; |
352 | struct afactor factors[MAX_FACTORS]; |
353 | struct afactor *numerator[MAX_FACTORS], |
353 | struct afactor *numerator[MAX_FACTORS], |
354 | *denominator[MAX_FACTORS], |
354 | *denominator[MAX_FACTORS], |
355 | *neutral[MAX_FACTORS]; |
355 | *neutral[MAX_FACTORS]; |
356 | int numcnt,dencnt,neucnt; |
356 | int numcnt,dencnt,neucnt; |
357 | /* interpret some arrows */ |
357 | /* interpret some arrows */ |
358 | rel=0; switch(*p) { |
358 | rel=0; switch(*p) { |
359 | case '<': { |
359 | case '<': { |
360 | rel++; p++; if(*p!='=') {tprint(" < "); break;} // < |
360 | rel++; p++; if(*p!='=') {tprint(" < "); break;} // < |
361 | do p++; while(*p=='='); |
361 | do p++; while(*p=='='); |
362 | if(*p!='>') {tprint("\\le ");break;} // <= , <=== |
362 | if(*p!='>') {tprint("\\le ");break;} // <= , <=== |
363 | else {tprint("\\iff ");p++; break;} // <==> |
363 | else {tprint("\\iff ");p++; break;} // <==> |
364 | } |
364 | } |
365 | case '>': { |
365 | case '>': { |
366 | rel++; p++; if(*p!='=') {tprint(" > "); rel=1; break;} // > |
366 | rel++; p++; if(*p!='=') {tprint(" > "); rel=1; break;} // > |
367 | while(*p=='=') p++; tprint("\\ge "); // >= |
367 | while(*p=='=') p++; tprint("\\ge "); // >= |
368 | break; |
368 | break; |
Line 386... | Line 386... | ||
386 | p++; |
386 | p++; |
387 | } |
387 | } |
388 | for(fcnt=0, pp=p; fcnt<MAX_FACTORS && *pp; fcnt++, pp=pe) { |
388 | for(fcnt=0, pp=p; fcnt<MAX_FACTORS && *pp; fcnt++, pp=pe) { |
389 | s=1; |
389 | s=1; |
390 | while(*pp=='*' || *pp=='/') { |
390 | while(*pp=='*' || *pp=='/') { |
391 | if(*pp=='/') s=-1; |
391 | if(*pp=='/') s=-1; |
392 | pp++; |
392 | pp++; |
393 | } |
393 | } |
394 | factors[fcnt].side=s; |
394 | factors[fcnt].side=s; |
395 | while(*pp=='+' || *pp=='-') { |
395 | while(*pp=='+' || *pp=='-') { |
396 | if(*pp=='-') sign*=-1; |
396 | if(*pp=='-') sign*=-1; |
Line 407... | Line 407... | ||
407 | memmove(buf,pp,pt-pp); buf[pt-pp]=0; |
407 | memmove(buf,pp,pt-pp); buf[pt-pp]=0; |
408 | i=term_cnt(buf); |
408 | i=term_cnt(buf); |
409 | if(i==1) { /* remove parentheses */ |
409 | if(i==1) { /* remove parentheses */ |
410 | for(;pp<pt && fcnt<MAX_FACTORS;pp=pe2,fcnt++) { |
410 | for(;pp<pt && fcnt<MAX_FACTORS;pp=pe2,fcnt++) { |
411 | ss=s; while(*pp=='*' || *pp=='/') { |
411 | ss=s; while(*pp=='*' || *pp=='/') { |
412 | if(*pp=='/') ss=-1; |
412 | if(*pp=='/') ss=-1; |
413 | pp++; |
413 | pp++; |
414 | } |
414 | } |
415 | factors[fcnt].side=ss; |
415 | factors[fcnt].side=ss; |
416 | while(*pp=='+' || *pp=='-') { |
416 | while(*pp=='+' || *pp=='-') { |
417 | if(*pp=='-') sign*=-1; |
417 | if(*pp=='-') sign*=-1; |
Line 426... | Line 426... | ||
426 | } |
426 | } |
427 | } |
427 | } |
428 | } |
428 | } |
429 | } |
429 | } |
430 | bailout: |
430 | bailout: |
431 | /* decide if the factor is of type numeric, integer, poly, transcend or variable |
431 | /* decide if the factor is of type numeric, integer, poly, transcend or variable |
432 | * (see priorities) |
432 | * (see priorities) |
433 | */ |
433 | */ |
434 | for(i=0;i<fcnt;i++) { |
434 | for(i=0;i<fcnt;i++) { |
435 | pp=factors[i].beg; pe=factors[i].end; |
435 | pp=factors[i].beg; pe=factors[i].end; |
436 | if(myisdigit(*pp) || *pp=='.') { |
436 | if(myisdigit(*pp) || *pp=='.') { |
Line 440... | Line 440... | ||
440 | continue; |
440 | continue; |
441 | } |
441 | } |
442 | if(*pp=='(') { |
442 | if(*pp=='(') { |
443 | factors[i].type=type_poly; continue; //there exists a parenthesis |
443 | factors[i].type=type_poly; continue; //there exists a parenthesis |
444 | } |
444 | } |
445 | pt=strchr(pp,'('); |
445 | pt=strchr(pp,'('); |
446 | if(pt!=NULL && pt<pe) factors[i].type=type_transcend; //?? |
446 | if(pt!=NULL && pt<pe) factors[i].type=type_transcend; //?? |
447 | else factors[i].type=type_var; // variable in other cases |
447 | else factors[i].type=type_var; // variable in other cases |
448 | } |
448 | } |
449 | dentype=-1; |
449 | dentype=-1; |
450 | for(i=0;i<fcnt;i++) if(factors[i].side<0 && factors[i].type>dentype) |
450 | for(i=0;i<fcnt;i++) if(factors[i].side<0 && factors[i].type>dentype) |
Line 453... | Line 453... | ||
453 | for(i=0;i<fcnt;i++) { |
453 | for(i=0;i<fcnt;i++) { |
454 | if(factors[i].type>dentype) neutral[neucnt++]=factors+i; |
454 | if(factors[i].type>dentype) neutral[neucnt++]=factors+i; |
455 | else { |
455 | else { |
456 | if(factors[i].side>0) numerator[numcnt++]=factors+i; |
456 | if(factors[i].side>0) numerator[numcnt++]=factors+i; |
457 | else denominator[dencnt++]=factors+i; |
457 | else denominator[dencnt++]=factors+i; |
458 | } |
458 | } |
459 | } |
459 | } |
460 | if(dencnt>0) qsort(denominator,dencnt,sizeof(denominator[0]),fsort); |
460 | if(dencnt>0) qsort(denominator,dencnt,sizeof(denominator[0]),fsort); |
461 | if(numcnt>0) qsort(numerator,numcnt,sizeof(numerator[0]),fsort); |
461 | if(numcnt>0) qsort(numerator,numcnt,sizeof(numerator[0]),fsort); |
462 | if(neucnt>0) qsort(neutral,neucnt,sizeof(neutral[0]),fsort); |
462 | if(neucnt>0) qsort(neutral,neucnt,sizeof(neutral[0]),fsort); |
463 | if(sign>0 && num>0 && rel==0) tprint(" +"); |
463 | if(sign>0 && num>0 && rel==0) tprint(" +"); |
464 | if(sign<0) tprint(" -"); |
464 | if(sign<0) tprint(" -"); |
465 | if(fcnt<1) tprint("1 "); // no factors why 1 - don't remove the 1 if [1,2;3,4], the 1 is useful? |
465 | if(fcnt<1) tprint("1 "); // no factors why 1 - don't remove the 1 if [1,2;3,4], the 1 is useful? |
466 | if(dencnt>0) { |
466 | if(dencnt>0) { |
467 | tprint(" {"); |
467 | tprint(" {"); |
468 | if(numcnt==0) tprint(" 1"); // no numerator ? will write {1 over denominator} |
468 | if(numcnt==0) tprint(" 1"); // no numerator ? will write {1 over denominator} |
469 | else {/* numerator */ |
469 | else {/* numerator */ |
470 | if(numcnt==1 && *numerator[0]->beg=='(' && |
470 | if(numcnt==1 && *numerator[0]->beg=='(' && |
471 | find_matching(numerator[0]->beg+1,')')==(numerator[0]->end)-1) { |
471 | find_matching(numerator[0]->beg+1,')')==(numerator[0]->end)-1) { |
472 | *(numerator[0]->end-1)=0; |
472 | *(numerator[0]->end-1)=0; |
473 | t_onestring(numerator[0]->beg+1); |
473 | t_onestring(numerator[0]->beg+1); |
474 | *(numerator[0]->end-1)=')'; |
474 | *(numerator[0]->end-1)=')'; |
475 | } |
475 | } |
476 | else for(i=0; i<numcnt; i++) t_onefactor(numerator[i],i); |
476 | else for(i=0; i<numcnt; i++) t_onefactor(numerator[i],i); |
477 | } |
477 | } |
478 | tprint(" \\over "); /* Now denominator */ |
478 | tprint(" \\over "); /* Now denominator */ |
479 | if(dencnt==1 && *denominator[0]->beg=='(' && |
479 | if(dencnt==1 && *denominator[0]->beg=='(' && |
480 | find_matching(denominator[0]->beg+1,')')==(denominator[0]->end)-1) { |
480 | find_matching(denominator[0]->beg+1,')')==(denominator[0]->end)-1) { |
481 | *(denominator[0]->end-1)=0; |
481 | *(denominator[0]->end-1)=0; |
482 | t_onestring(denominator[0]->beg+1); |
482 | t_onestring(denominator[0]->beg+1); |
483 | *(denominator[0]->end-1)=')'; |
483 | *(denominator[0]->end-1)=')'; |
484 | } |
484 | } |
Line 491... | Line 491... | ||
491 | /* put exponential */ |
491 | /* put exponential */ |
492 | void t_exponential(char *pp) |
492 | void t_exponential(char *pp) |
493 | { |
493 | { |
494 | char *pe, *pt; |
494 | char *pe, *pt; |
495 | int t=0; |
495 | int t=0; |
496 | 496 | ||
497 | while(*pp && strchr("!'\"",*pp)!=NULL) { |
497 | while(*pp && strchr("!'\"",*pp)!=NULL) { |
498 | tprint("%c",*pp); pp++; |
498 | tprint("%c",*pp); pp++; |
499 | } |
499 | } |
500 | if(*pp=='^') pp++; else return; |
500 | if(*pp=='^') pp++; else return; |
501 | if(*pp=='(') { |
501 | if(*pp=='(') { |
Line 535... | Line 535... | ||
535 | switch(*pt) { |
535 | switch(*pt) { |
536 | case '(': pt=find_matching(pt+1,')'); break; |
536 | case '(': pt=find_matching(pt+1,')'); break; |
537 | case '[': pt=find_matching(pt+1,']'); break; |
537 | case '[': pt=find_matching(pt+1,']'); break; |
538 | case '{': pt=find_matching(pt+1,'}'); break; |
538 | case '{': pt=find_matching(pt+1,'}'); break; |
539 | case '|': pt=find_matching(pt+1,'|'); break; |
539 | case '|': pt=find_matching(pt+1,'|'); break; |
540 | - | ||
- | 540 | ||
541 | case ',': |
541 | case ',': |
542 | case ';': goto out; |
542 | case ';': goto out; |
543 | } |
543 | } |
544 | } |
544 | } |
545 | out: if(*pt==';' || *pt==',') { /* is matrix of the form [ 1,2;5,6] */ |
545 | out: if(*pt==';' || *pt==',') { /* is matrix of the form [ 1,2;5,6] */ |
Line 567... | Line 567... | ||
567 | pe=find_matching(p+1,'}'); |
567 | pe=find_matching(p+1,'}'); |
568 | *pe=0;tprint(" %s} ",p); |
568 | *pe=0;tprint(" %s} ",p); |
569 | goto expon; |
569 | goto expon; |
570 | } |
570 | } |
571 | } |
571 | } |
572 | tprint(" \\left%c",lp); |
572 | tprint(" \\left%c",lp); |
573 | snprintf(rpbuf,sizeof(rpbuf),"\\right%c ",rp2); rp=rpbuf; |
573 | snprintf(rpbuf,sizeof(rpbuf),"\\right%c ",rp2); rp=rpbuf; |
574 | paren: p++;pe=find_matching(p,rp2); *pe=0; |
574 | paren: p++;pe=find_matching(p,rp2); *pe=0; |
575 | t_onestring(p); tprint(rp); pe++; goto expon; |
575 | t_onestring(p); tprint(rp); pe++; goto expon; |
576 | } |
576 | } |
577 | pe=find_mathvar_end(p); while(*pe && strchr("'\"!",*pe)!=NULL) pe++; |
577 | pe=find_mathvar_end(p); while(*pe && strchr("'\"!",*pe)!=NULL) pe++; |
Line 650... | Line 650... | ||
650 | } |
650 | } |
651 | } |
651 | } |
652 | /* replace \pmatrix{ } by latex syntax \begin{pmatrix} .. \end{pmatrix} */ |
652 | /* replace \pmatrix{ } by latex syntax \begin{pmatrix} .. \end{pmatrix} */ |
653 | 653 | ||
654 | void _replace_matrix ( char *p , char *s_mat1, char *s_mat2 ) |
654 | void _replace_matrix ( char *p , char *s_mat1, char *s_mat2 ) |
655 | { char pbuf[MAX_LINELEN]; |
655 | { char pbuf[MAX_LINELEN]; |
656 | while ( (p = strstr(p,s_mat1)) ) |
656 | while ( (p = strstr(p,s_mat1)) ) |
657 | { char *p2 = find_matching(p+strlen(s_mat1),'}'); |
657 | { char *p2 = find_matching(p+strlen(s_mat1),'}'); |
658 | long len = p2-p-strlen(s_mat1); |
658 | long len = p2-p-strlen(s_mat1); |
659 | if (!p2) { module_error("unmatched_parentheses"); return; } |
659 | if (!p2) { module_error("unmatched_parentheses"); return; } |
660 | memcpy(pbuf, p+strlen(s_mat1), len); pbuf[len]= 0; |
660 | memcpy(pbuf, p+strlen(s_mat1), len); pbuf[len]= 0; |
Line 665... | Line 665... | ||
665 | 665 | ||
666 | /* translate raw math expression into TeX source */ |
666 | /* translate raw math expression into TeX source */ |
667 | void texmath(char *p) |
667 | void texmath(char *p) |
668 | { |
668 | { |
669 | char *pp; |
669 | char *pp; |
670 | _replace_matrix (p,"\\matrix{","matrix"); |
670 | _replace_matrix (p,"\\matrix{","matrix"); |
671 | _replace_matrix (p,"\\pmatrix{","pmatrix"); |
671 | _replace_matrix (p,"\\pmatrix{","pmatrix"); |
672 | if(strpbrk(p,"{}\\")!=NULL) return; |
672 | if(strpbrk(p,"{}\\")!=NULL) return; |
673 | for(pp=strstr(p,"!="); pp; pp=strstr(pp+1,"!=")) { |
673 | for(pp=strstr(p,"!="); pp; pp=strstr(pp+1,"!=")) { |
674 | if(pp>p && !isspace(*(pp-1))) continue; |
674 | if(pp>p && !isspace(*(pp-1))) continue; |
675 | string_modify(p,pp,pp+2,"*neq*"); |
675 | string_modify(p,pp,pp+2,"*neq*"); |