Subversion Repositories wimsdev

Rev

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*");