Subversion Repositories wimsdev

Rev

Rev 8568 | Rev 9147 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
10 reyssat 1
/*    Copyright (C) 1998-2003 XIAO, Gang of Universite de Nice - Sophia Antipolis
2
 *
3
 *  This program is free software; you can redistribute it and/or modify
4
 *  it under the terms of the GNU General Public License as published by
5
 *  the Free Software Foundation; either version 2 of the License, or
6
 *  (at your option) any later version.
7
 *
8
 *  This program is distributed in the hope that it will be useful,
9
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
 *  GNU General Public License for more details.
12
 *
13
 *  You should have received a copy of the GNU General Public License
14
 *  along with this program; if not, write to the Free Software
15
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
16
 */
5502 bpr 17
/* subroutines for texmath */
8185 bpr 18
#include "wims.h"
10 reyssat 19
 
8185 bpr 20
/* Careful! increasing this number risks stack overflow. */
10 reyssat 21
#define MAX_FACTORS 256
22
 
23
enum {
24
    type_integer, type_numeric, type_var,
25
      type_poly, type_transcend
26
};
27
 
28
typedef struct afactor{
29
    char *beg, *end;
30
    int type, side;
31
} afactor;
32
 
33
char texmathbuf[MAX_LINELEN+1];
34
char *find_term_end(char *p);
35
void t_onestring(char *p);
36
void t_oneterm(char *p, int num);
37
void t_onefactor(struct afactor *p, int num);
5516 bpr 38
/* never used or defined ?? */
10 reyssat 39
void n_onestring(char *p);
40
void n_oneterm(char *p, int num);
41
void n_onefactor(struct afactor *p, int num);
5516 bpr 42
/* */
10 reyssat 43
void texmath(char *p);
44
 
5502 bpr 45
/* print to texmathbuf */
10 reyssat 46
void tprint(char *s,...)
47
{
48
    va_list vp;
49
    char buf[MAX_LINELEN+1];
50
 
51
    va_start(vp,s); vsnprintf(buf,sizeof(buf),s,vp); va_end(vp);
7673 bpr 52
    if(strlen(buf)+strlen(texmathbuf)>=MAX_LINELEN)
10 reyssat 53
      user_error("cmd_output_too_long");
54
    strcat(texmathbuf,buf);
55
}
5458 bpr 56
/* transforms sum(n,n=1..infinity) , product(n/(n+1),n=1..infinity). */
10 reyssat 57
void _tex_sums(char *p, char *name, int type)
58
{
59
    char *p1,*p2,*p3;
60
    p1=find_item_end(p); if(*p1) *(p1++)=0;
61
    p2=find_item_end(p1); p3=strparstr(p1,"=");
62
    if(p3<p2) p2=p3; if(*p2) *(p2++)=0;
63
    p3=find_item_end(p2);
64
    if(*p3) *(p3++)=0;
65
    tprint("\\%s ",name);
66
    if(type) {
5502 bpr 67
      if(*p2) {
68
        tprint("_{"); t_onestring(p2); tprint("}");
69
      }
10 reyssat 70
    }
71
    else if(*p1) {
5502 bpr 72
      tprint("_{%s",p1);
73
      if(*p2) { tprint("="); t_onestring(p2); }
74
      tprint("}");
10 reyssat 75
    }
76
    if(*p3) {
5502 bpr 77
      tprint("^{"); t_onestring(p3); tprint("}");
10 reyssat 78
    }
79
    strip_trailing_spaces(p); if(find_term_end(p)<p+strlen(p)) {
5502 bpr 80
      tprint("\\left("); t_onestring(p); tprint("\\right)");
10 reyssat 81
    }
82
    else t_onestring(p);
83
    if(type && *p1) {
5502 bpr 84
      strip_trailing_spaces(p1); tprint("d"); // case of the integrale
85
      if(find_term_end(p1)<p1+strlen(p1)) {
86
        tprint("\\left("); t_onestring(p1); tprint("\\right)");
87
      }
88
      else t_onestring(p1);
10 reyssat 89
    }
90
}
91
 
5502 bpr 92
/* integration, sum and product */
10 reyssat 93
void tex_int(char *p) {  _tex_sums(p,"int",1); }
94
void tex_sum(char *p) {  _tex_sums(p,"sum",0); }
95
void tex_prod(char *p) { _tex_sums(p,"prod",0);}
96
 
8185 bpr 97
struct tmathfn tmathfn[]={
5502 bpr 98
      {"Arg",      1,  "\\rm{Arg}",      "\\right)"},
99
      {"Int",      2,  "","",        tex_int},
100
      {"Prod",     2,  "","",        tex_prod},
101
      {"Sum",      2,  "","",        tex_sum},
102
      {"abs",      0,  "\\left|",      "\\right|"},
103
      {"acos",     1,  "\\rm{arccos}",  "\\right)"},
104
      {"acosh",    1,  "\\rm{Argch}",      "\\right)"},
105
      {"arg",      1,  "\\rm{Arg}",      "\\right)"},
106
      {"asin",     1,  "\\rm{arcsin}",  "\\right)"},
107
      {"asinh",    1,  "\\rm{Argsh}",      "\\right)"},
108
      {"atan",     1,  "\\rm{arctg}",      "\\right)"},
109
      {"atanh",    1,  "\\rm{Argth}",      "\\right)"},
110
      {"ch",       1,  "\\rm{ch}",      "\\right)"},
111
      {"conj",     0,  "\\overline{",      "}"},
112
      {"conjugate",0,  "\\overline{",      "}"},
113
      {"cos",      1,  "\\cos",      "\\right)"},
114
      {"cosh",     1,  "\\rm{ch}",      "\\right)"},
115
      {"cot",      1,  "\\rm{ctg}",      "\\right)"},
116
      {"cotan",    1,  "\\rm{ctg}",      "\\right)"},
117
      {"cotanh",   1,  "\\rm{cth}",      "\\right)"},
118
      {"csc",      1,  "\\rm{csc}",      "\\right)"},
119
      {"ctg",      1,  "\\rm{ctg}",      "\\right)"},
120
      {"cth",      1,  "\\rm{cth}",      "\\right)"},
121
      {"det",      1,  "\\rm{det}",      "\\right)"},
122
      {"erf",      1,  "\\rm{erf}",      "\\right)"},
123
      {"exp",      1,  "\\exp",      "\\right)"},
124
      {"int",      2,  "","",        tex_int},
125
      {"integrate",2,  "","",        tex_int},
126
      {"lg",       1,  "\\rm{lg}",      "\\right)"},
127
      {"ln",       1,  "\\ln",        "\\right)"},
128
      {"log",      1,  "\\log",      "\\right)"},
129
      {"prod",     2,  "","",        tex_prod},
130
      {"product",  2,  "","",        tex_prod},
131
      {"sec",      1,  "\\rm{sec}",      "\\right)"},
132
      {"sgn",      1,  "\\rm{sgn}",      "\\right)"},
133
      {"sh",       1,  "\\rm{sh}",      "\\right)"},
134
      {"sign",     1,  "\\rm{sign}",      "\\right)"},
135
      {"sin",      1,  "\\sin",      "\\right)"},
136
      {"sinh",     1,  "\\rm{sh}",      "\\right)"},
137
      {"sqrt",     0,  "\\sqrt{",      "}"},
138
      {"sum",      2,  "","",        tex_sum},
139
      {"tan",      1,  "\\tan",      "\\right)"},
140
      {"tanh",     1,  "\\rm{th}",      "\\right)"},
141
      {"tg",       1,  "\\rm{tg}",      "\\right)"},
142
      {"th",       1,  "\\rm{th}",      "\\right)"}
10 reyssat 143
};
144
 
8185 bpr 145
int tmathfn_no=(sizeof(tmathfn)/sizeof(tmathfn[0]));
10 reyssat 146
 
8185 bpr 147
struct tmathvar tmathvar[]={
5502 bpr 148
      {"CC",      "\\mathbb{C}"},
149
      {"Delta",   "\\Delta"},
150
      {"Gamma",   "\\Gamma"},
151
      {"Inf",     "\\infty"},
152
      {"Lambda",  "\\Lambda"},
153
      {"NN",      "\\mathbb{N}"},
154
      {"Omega",   "\\Omega"},
155
      {"PI",      "\\pi"},
156
      {"Phi",     "\\Phi"},
157
      {"Pi",      "\\Pi"},
158
      {"Psi",     "\\Psi"},
159
      {"QQ",      "\\mathbb{Q}"},
160
      {"RR",      "\\mathbb{R}"},
161
      {"Sigma",   "\\Sigma"},
162
      {"Theta",   "\\Theta"},
163
      {"Upsilon", "\\Upsilon"},
164
      {"Xi",      "\\Xi"},
165
      {"ZZ",      "\\mathbb{Z}"},
166
      {"aleph",   "\\aleph"},
167
      {"alpha",   "\\alpha"},
168
      {"beta",   "\\beta"},
169
      {"chi",    "\\chi"},
170
      {"delta",  "\\delta"},
171
      {"epsilon","\\epsilon"},
172
      {"eta",    "\\eta"},
173
      {"gamma",  "\\gamma"},
174
      {"inf",    "\\infty"},
175
      {"infinity","\\infty"},
176
      {"infty",  "\\infty"},
177
      {"iota",   "\\iota"},
178
      {"kappa",  "\\kappa"},
179
      {"lambda", "\\lambda"},
180
      {"mu",     "\\mu"},
181
      {"neq",    "\\neq"},
182
      {"nu",     "\\nu"},
183
      {"omega",  "\\omega"},
184
      {"phi",    "\\phi"},
185
      {"pi",     "\\pi"},
186
      {"psi",    "\\psi"},
187
      {"rho",    "\\rho"},
188
      {"sigma",  "\\sigma"},
189
      {"tau",    "\\tau"},
190
      {"theta",  "\\theta"},
191
      {"xi",     "\\xi"},
192
      {"zeta",   "\\zeta"}
10 reyssat 193
};
194
 
8185 bpr 195
int tmathvar_no=(sizeof(tmathvar)/sizeof(tmathvar[0]));
10 reyssat 196
 
197
 
5502 bpr 198
/* find the end of an additive term. */
10 reyssat 199
char *find_term_end(char *p)
200
{
201
    char *pp;
7673 bpr 202
    pp=p;
10 reyssat 203
    if(*pp==',' || *pp==';' || *pp=='=' || *pp=='<') pp++;
204
    while(*pp=='+' || *pp=='-' || *pp=='=' || *pp=='>') pp++;
205
    for(;*pp;pp++) {
5502 bpr 206
      switch(*pp) {
207
        case '(': pp=find_matching(pp+1,')'); goto loopend;
208
        case '[': pp=find_matching(pp+1,']'); goto loopend;
209
/*     case '{': pp=find_matching(pp+1,'}'); goto loopend;*/
7673 bpr 210
 
5502 bpr 211
        case 0:
212
        case '<':
213
        case '>':
214
        case ',':
215
        case ';':
216
        case '=':
217
        case ')':
218
        case ']':
219
        case '}':
220
        case '-':
221
        case '+': return pp;
222
 
223
        case '*':
224
        case '/':
225
        case '^': {
226
          while(*(pp+1)=='+' || *(pp+1)=='-') pp++;
227
          goto loopend;
228
        }
229
      }
230
      if(isalnum(*pp) || *pp=='.') {
231
        pp=find_mathvar_end(pp); pp--; continue;
232
      }
233
      continue;
234
      loopend:
235
      if(pp==NULL) module_error("unmatched_parentheses");
10 reyssat 236
    }
237
    return pp;
238
}
239
 
5502 bpr 240
/* find the end of an multiplicative factor. */
10 reyssat 241
char *find_factor_end(char *p)
242
{
243
    char *pp;
244
    pp=p; if(*pp==',' || *pp==';' || *pp=='=') pp++;
245
    while(*pp=='+' || *pp=='-' || *pp=='*' || *pp=='/') pp++;
246
    for(;*pp;pp++) {
5502 bpr 247
      switch(*pp) {
248
        case '(': pp=find_matching(pp+1,')'); goto loopend;
249
        case '[': pp=find_matching(pp+1,']'); goto loopend;
250
/*    case '{': pp=find_matching(pp+1,'}'); goto loopend;*/
7673 bpr 251
 
5502 bpr 252
        case 0:
253
        case '<':
254
        case '>':
255
        case ',':
256
        case ';':
257
        case '=':
258
        case ')':
259
        case ']':
260
        case '}':
261
        case '+':
262
        case '-':
263
        case '*':
264
        case '/': return pp;
7673 bpr 265
 
5502 bpr 266
        case '^': {
267
          while(*(pp+1)=='+' || *(pp+1)=='-') pp++;
268
          goto loopend;
269
        }
270
      }
271
      if(isalnum(*pp) || *pp=='.') {
272
        pp=find_mathvar_end(pp); pp--; continue;
273
      }
274
      continue;
275
      loopend:
276
      if(pp==NULL) module_error("unmatched_parentheses");
10 reyssat 277
    }
278
    return pp;
279
}
280
 
5502 bpr 281
    /* returns the number of terms */
10 reyssat 282
int term_cnt(char *p)
283
{
284
    char *pe, *pp;
285
    int i;
7673 bpr 286
 
10 reyssat 287
    pe=p+strlen(p);
288
    for(i=0,pp=p;pp<pe;pp=find_term_end(pp),i++);
289
    return i;
290
}
291
 
5460 bpr 292
/* Print a number: transform 4E+05 in 4 \times 10^{5} and  4E-05 in 4 \times 10^{-5}
5822 bpr 293
suppress multiple + or 0 ; see rawmath.c
5460 bpr 294
*/
10 reyssat 295
void putnumber(char *p)
5822 bpr 296
 {
297
     char *sgn = "", *pp = strpbrk(p,"Ee");
298
     if (pp == NULL) { tprint("%s",p); return; }
299
     *pp++ = 0;
300
     if (*pp == '-') { sgn = "-"; pp++; }
301
     while (*pp == '0' || *pp == '+') pp++;
302
     tprint("%s \\times 10^{%s%s}", p, sgn, pp);
303
 }
7673 bpr 304
 
5502 bpr 305
/* Print a variable name ; transform abc475 in abc_475 */
10 reyssat 306
void putvar(char *p)
307
{
308
    char vbuf[1024];
309
    char *pp, *p2;
310
    int i;
7673 bpr 311
 
10 reyssat 312
    vbuf[0]=0;
313
    if(*(p+1)==0) {tprint("%c",*p); return;}
314
    for(pp=p;isalpha(*pp);pp++);
315
    if(myisdigit(*pp)) {
5502 bpr 316
    for(p2=pp+1;myisdigit(*p2);p2++);
317
    if(*p2==0) {/* subscript */
318
        mystrncpy(vbuf,pp,sizeof(vbuf));*pp=0;
10 reyssat 319
    }
5502 bpr 320
    }
10 reyssat 321
    i=search_list(tmathvar, tmathvar_no, sizeof(tmathvar[0]), p);
322
    if(i>=0) tprint("%s ",tmathvar[i].tex);
323
    else tprint("%s ",p);
324
    if(vbuf[0]) {
5502 bpr 325
    if(vbuf[1]==0) tprint("_%c ",vbuf[0]);
326
    else tprint("_{%s} ",vbuf);
10 reyssat 327
    }
328
}
5514 bpr 329
 
5512 bpr 330
/* sort according to type */
10 reyssat 331
int fsort(const void *p1, const void *p2)
332
{
333
    struct afactor *t1, *t2;
334
    int i1,i2;
7673 bpr 335
 
10 reyssat 336
    t1=*(struct afactor **) p1; t2=*(struct afactor **) p2;
337
    i1=t1->type; i2=t2->type;
338
    if(i1>type_var) i1=type_var; if(i2>type_var) i2=type_var;
339
    return i1-i2;
340
}
341
 
342
void t_oneterm(char *p, int num)
343
{
344
    int sign, fcnt, s, i, dentype, rel;
345
    char *pp, *pe, *pt;
346
    struct afactor factors[MAX_FACTORS];
7673 bpr 347
    struct afactor *numerator[MAX_FACTORS],
348
      *denominator[MAX_FACTORS],
10 reyssat 349
      *neutral[MAX_FACTORS];
350
    int numcnt,dencnt,neucnt;
5502 bpr 351
/* interpret some arrows */
10 reyssat 352
    rel=0; switch(*p) {
5502 bpr 353
      case '<': {
7673 bpr 354
        rel++; p++; if(*p!='=') {tprint(" < "); break;} // <
5502 bpr 355
        do p++; while(*p=='=');
356
        if(*p!='>') {tprint("\\le ");break;} // <= , <===
7673 bpr 357
        else {tprint("\\iff ");p++; break;} // <==>
5502 bpr 358
      }
359
      case '>': {
360
        rel++; p++; if(*p!='=') {tprint(" > "); rel=1; break;} // >
361
        while(*p=='=') p++; tprint("\\ge "); // >=
362
        break;
363
      }
364
      case '-': {
365
        for(pp=p;*pp=='-';pp++);
366
        if(*pp!='>') break;
367
        rel++; tprint("\\to "); p=++pp; //->
368
        break;
369
      }
370
     case '=': {
371
        rel++; for(pp=p;*pp=='=';pp++);
372
        if(*pp!='>') break;
373
        tprint("\\Rightarrow "); p=++pp; // =>
374
        break;
375
      }
10 reyssat 376
    }
377
    if(*p==',' || *p==';' || *p=='=') {tprint("%c",*p); p++; num=0;}
378
    sign=1; while(*p=='+' || *p=='-') {
5502 bpr 379
      if(*p=='-') sign*=-1;
380
      p++;
10 reyssat 381
    }
382
    for(fcnt=0, pp=p; fcnt<MAX_FACTORS && *pp; fcnt++, pp=pe) {
5502 bpr 383
      s=1;
384
      while(*pp=='*' || *pp=='/') {
7673 bpr 385
        if(*pp=='/') s=-1;
5502 bpr 386
        pp++;
387
      }
388
      factors[fcnt].side=s;
389
      while(*pp=='+' || *pp=='-') {
390
        if(*pp=='-') sign*=-1;
391
        pp++;
392
      }
393
      pe=find_factor_end(pp); if(pe<=pp) break;
394
      factors[fcnt].beg=pp; factors[fcnt].end=pe;
395
      if(pe-pp==1 && *pp=='1') fcnt--;
396
      if(*pp=='(') {
397
        char *pt, *pe2, buf[MAX_LINELEN+1];
398
        int ss;
399
        pp++; pt=find_matching(pp,')');
400
        if(pt>=pe-1) {
401
          memmove(buf,pp,pt-pp); buf[pt-pp]=0;
402
          i=term_cnt(buf);
403
          if(i==1) { /* remove parentheses */
404
              for(;pp<pt && fcnt<MAX_FACTORS;pp=pe2,fcnt++) {
405
                ss=s; while(*pp=='*' || *pp=='/') {
8568 reyssat 406
                    if(*pp=='/') ss=-s;
5502 bpr 407
                    pp++;
408
                }
409
                factors[fcnt].side=ss;
410
                while(*pp=='+' || *pp=='-') {
411
                    if(*pp=='-') sign*=-1;
412
                    pp++;
413
                }
414
                pe2=find_factor_end(pp);
415
                if(pe2<=pp) goto bailout;
416
                factors[fcnt].beg=pp; factors[fcnt].end=pe2;
417
                if(pe2-pp==1 && *pp=='1') fcnt--;
418
              }
419
              fcnt--;
420
          }
421
        }
422
      }
10 reyssat 423
    }
424
    bailout:
7673 bpr 425
/* decide if the factor is of type numeric, integer, poly, transcend or variable
5512 bpr 426
*  (see priorities)
427
*/
10 reyssat 428
    for(i=0;i<fcnt;i++) {
5502 bpr 429
      pp=factors[i].beg; pe=factors[i].end;
430
      if(myisdigit(*pp) || *pp=='.') {
431
        for(pt=pp;pt<pe && myisdigit(*pt);pt++);
5512 bpr 432
        if(pt<pe) factors[i].type=type_numeric; // digits with a point
433
        else factors[i].type=type_integer;  // digits without point
5502 bpr 434
        continue;
435
      }
436
      if(*pp=='(') {
5512 bpr 437
        factors[i].type=type_poly; continue; //there exists a parenthesis
5502 bpr 438
      }
7673 bpr 439
      pt=strchr(pp,'(');
5512 bpr 440
      if(pt!=NULL && pt<pe) factors[i].type=type_transcend; //??
441
      else factors[i].type=type_var;  // variable in other cases
10 reyssat 442
    }
443
    dentype=-1;
444
    for(i=0;i<fcnt;i++) if(factors[i].side<0 && factors[i].type>dentype)
5512 bpr 445
      dentype=factors[i].type; // denominator type will be compared to the type of the factors
10 reyssat 446
    dencnt=numcnt=neucnt=0;
447
    for(i=0;i<fcnt;i++) {
5502 bpr 448
      if(factors[i].type>dentype) neutral[neucnt++]=factors+i;
449
      else {
450
        if(factors[i].side>0) numerator[numcnt++]=factors+i;
451
        else denominator[dencnt++]=factors+i;
452
      }
10 reyssat 453
    }
454
    if(dencnt>0) qsort(denominator,dencnt,sizeof(denominator[0]),fsort);
455
    if(numcnt>0) qsort(numerator,numcnt,sizeof(numerator[0]),fsort);
456
    if(neucnt>0) qsort(neutral,neucnt,sizeof(neutral[0]),fsort);
457
    if(sign>0 && num>0 && rel==0) tprint(" +");
458
    if(sign<0) tprint(" -");
7673 bpr 459
    if(fcnt<1) tprint("1 "); // no factors why 1 - don't remove the 1 if [1,2;3,4], the 1 is useful?
10 reyssat 460
    if(dencnt>0) {
5502 bpr 461
      tprint(" {");
5512 bpr 462
      if(numcnt==0) tprint(" 1"); // no numerator ? will write {1 over denominator}
463
      else {/* numerator */
7673 bpr 464
        if(numcnt==1 && *numerator[0]->beg=='(' &&
5502 bpr 465
           find_matching(numerator[0]->beg+1,')')==(numerator[0]->end)-1) {
466
          *(numerator[0]->end-1)=0;
467
          t_onestring(numerator[0]->beg+1);
468
          *(numerator[0]->end-1)=')';
469
        }
9146 reyssat 470
        else for(i=0; i<numcnt; i++) {t_onefactor(numerator[i],i);
471
                if(i<numcnt-1) tprint(" ");} /* add space between factors */
5512 bpr 472
      }
473
      tprint(" \\over ");      /* Now denominator */
7673 bpr 474
      if(dencnt==1 && *denominator[0]->beg=='(' &&
5512 bpr 475
        find_matching(denominator[0]->beg+1,')')==(denominator[0]->end)-1) {
476
         *(denominator[0]->end-1)=0;
477
         t_onestring(denominator[0]->beg+1);
478
         *(denominator[0]->end-1)=')';
479
      }
9146 reyssat 480
      else for(i=0;i<dencnt;i++) {t_onefactor(denominator[i],i);
481
                        if(i<dencnt-1) tprint(" ");} /* add space between factors */
5512 bpr 482
      tprint("} ");
10 reyssat 483
    }
484
    for(i=0;i<neucnt;i++) t_onefactor(neutral[i],i+dencnt);
485
}
486
 
8155 bpr 487
/* put exponential */
10 reyssat 488
void t_exponential(char *pp)
489
{
490
    char *pe, *pt;
491
    int t=0;
7673 bpr 492
 
10 reyssat 493
    while(*pp && strchr("!'\"",*pp)!=NULL) {
5502 bpr 494
      tprint("%c",*pp); pp++;
10 reyssat 495
    }
496
    if(*pp=='^') pp++; else return;
497
    if(*pp=='(') {
5502 bpr 498
      pe=find_matching(pp+1,')');
499
      if(*(pe+1)==0) {
500
        pp++;*pe=0;
501
        for(pt=pp;*pt && (isalnum(*pt) || *pt=='.');pt++);
502
        if(*pt==0) t=1;
503
      }
10 reyssat 504
    }
505
    if(strlen(pp)==1 && t==0) tprint("^%s ",pp);
506
    else {
5502 bpr 507
      tprint(" ^{"); if(t) tprint("(");
508
      t_onestring(pp);
509
      if(t) tprint(")"); tprint("} ");
10 reyssat 510
    }
511
}
512
 
513
void t_onefactor(struct afactor *fb, int num)
514
{
515
    char *p, *pe, lp, *rp, rp2, rpbuf[128];
516
    char fbuf[MAX_LINELEN+1], pbuf[MAX_LINELEN+1];
517
    int i;
518
 
519
    memmove(pbuf,fb->beg,fb->end-fb->beg);
520
    pbuf[fb->end-fb->beg]=0;
521
    if(num>0 && (myisdigit(pbuf[0]) || pbuf[0]=='.'))
522
      tprint("\\times ");
523
    rp2=')'; p=pbuf;
524
    if(strchr("({[",*p)!=NULL) {
5502 bpr 525
    lp=*p; switch(lp) {
526
        case '(': rp2=')';  break;
527
        case '[': { /* verify for matrices */
528
          char *pt;
529
          pe=find_matching(p+1,']');
530
          for(pt=p+1;pt<pe;pt++) {
531
              switch(*pt) {
532
                case '(': pt=find_matching(pt+1,')'); break;
533
                case '[': pt=find_matching(pt+1,']'); break;
534
                case '{': pt=find_matching(pt+1,'}'); break;
535
                case '|': pt=find_matching(pt+1,'|'); break;
7673 bpr 536
 
5502 bpr 537
                case ',':
538
                case ';': goto out;
539
              }
540
          }
541
          out: if(*pt==';' || *pt==',') { /* is matrix of the form [ 1,2;5,6] */
542
              char mbuf[MAX_LINELEN+1];
543
              char *pp, *pt;
544
 
545
              p++; if(*pe) *pe++=0;
546
              tprint(" \\begin{pmatrix}");
547
              for(pp=p,i=0;*pp;pp=pt,i++) {
548
                pt=find_term_end(pp);
549
                memmove(mbuf,pp,pt-pp); mbuf[pt-pp]=0;
550
                t_oneterm(mbuf,i);
551
                if(*pt==',') {
552
                    tprint(" &"); pt++; i=-1;
553
                }
554
                if(*pt==';') {
555
                    tprint("\\cr "); pt++; i=-1;
556
                }
557
              }
558
              tprint(" \\end{pmatrix}"); goto expon;
559
          }
560
          rp2=']'; break;
561
        }
562
        case '{': { /* protected */
563
          pe=find_matching(p+1,'}');
564
          *pe=0;tprint(" %s} ",p);
565
          goto expon;
566
        }
10 reyssat 567
    }
7673 bpr 568
    tprint(" \\left%c",lp);
5502 bpr 569
    snprintf(rpbuf,sizeof(rpbuf),"\\right%c ",rp2); rp=rpbuf;
570
    paren: p++;pe=find_matching(p,rp2); *pe=0;
571
    t_onestring(p); tprint(rp); pe++; goto expon;
572
    }
10 reyssat 573
    pe=find_mathvar_end(p); while(*pe && strchr("'\"!",*pe)!=NULL) pe++;
574
    memmove(fbuf,p,pe-p); fbuf[pe-p]=0;
575
    if(myisdigit(*p) || *p=='.') putnumber(fbuf);
576
    if(isalpha(*p)) {
5502 bpr 577
    pe=find_mathvar_end(p); while(*pe && strchr("'\"!",*pe)!=NULL) pe++;
578
    if(*pe=='(') {
579
        p=pe;
580
/* search in list of math functions*/
581
        i=search_list(tmathfn, tmathfn_no, sizeof(tmathfn[0]), fbuf);
582
        if(i>=0) {
583
          switch(tmathfn[i].expind) {
584
              case 0: {
585
                tprint(" %s",tmathfn[i].left);
586
                rp=tmathfn[i].right; break;
587
              }
588
              case 1: {
589
                tprint(" %s",tmathfn[i].left);
590
                pe=find_matching(pe+1,')')+1;
591
                if(*pe && strchr("^'\"!",*pe)!=NULL) {
592
                    t_exponential(pe); *pe=0;
593
                }
594
                tprint(" \\left("); rp=tmathfn[i].right;
595
                break;
596
              }
597
              case 2: {  /* routine */
598
                p++;pe=find_matching(p,rp2); *pe=0;
599
                tmathfn[i].routine(p);
600
                pe++; goto expon;
601
              }
602
              default: rp=""; break;
603
          }
604
        }
605
        else {
606
          putvar(fbuf);
607
          rp="\\right) "; tprint(" \\left(");
608
        }
609
        rp2=')'; goto paren;
10 reyssat 610
    }
5502 bpr 611
    else {
612
        putvar(fbuf);
613
        if(*pe=='_') {
614
          char *ptt, buff[256];
615
          tprint("_"); pe++;
616
          if(*pe=='(') {
617
              ptt=find_matching(pe+1,')'); if(ptt) ptt++;
618
          }
619
          else {
620
              if(*pe=='{') {
621
                ptt=find_matching(pe+1,'}'); if(ptt) ptt++;
622
              }
623
              else ptt=find_mathvar_end(pe);
624
          }
625
          if(ptt==NULL || ptt-pe>128) goto expon;
626
          memmove(buff,pe,ptt-pe); buff[ptt-pe]=0; pe=ptt;
627
          strip_enclosing_par(buff);
628
          tprint("{%s}",buff);
629
        }
630
    }
631
    }
632
    /* exponential */
10 reyssat 633
    expon: if(*pe && strchr("^'\"!",*pe)!=NULL) t_exponential(pe);
634
}
635
 
636
void t_onestring(char *p)
637
{
638
    char termbuf[MAX_LINELEN+1];
639
    char *pp, *pe;
640
    int i;
641
 
642
    for(pp=p,i=0;*pp;pp=pe,i++) {
5502 bpr 643
    pe=find_term_end(pp);
644
    memmove(termbuf,pp,pe-pp); termbuf[pe-pp]=0;
645
    t_oneterm(termbuf,i);
10 reyssat 646
    }
647
}
5459 bpr 648
/* replace \pmatrix{  } by latex syntax \begin{pmatrix} .. \end{pmatrix} */
649
 
650
void _replace_matrix ( char *p , char *s_mat1, char *s_mat2 )
7673 bpr 651
{ char pbuf[MAX_LINELEN];
5459 bpr 652
  while ( (p = strstr(p,s_mat1)) )
653
  { char *p2 = find_matching(p+strlen(s_mat1),'}');
654
    long len = p2-p-strlen(s_mat1);
655
    if (!p2) { module_error("unmatched_parentheses"); return; }
656
    memcpy(pbuf, p+strlen(s_mat1), len); pbuf[len]= 0;
657
    p2 ++ ;
658
    string_modify(p, p, p2, "\\begin{%s}%s\\end{%s}",s_mat2,pbuf,s_mat2);
659
  }
660
}
661
 
5502 bpr 662
/* translate raw math expression into TeX source */
10 reyssat 663
void texmath(char *p)
664
{
665
    char *pp;
7673 bpr 666
    _replace_matrix (p,"\\matrix{","matrix");
5459 bpr 667
    _replace_matrix (p,"\\pmatrix{","pmatrix");
10 reyssat 668
    if(strpbrk(p,"{}\\")!=NULL) return;
669
    for(pp=strstr(p,"!="); pp; pp=strstr(pp+1,"!=")) {
5502 bpr 670
      if(pp>p && !isspace(*(pp-1))) continue;
671
      string_modify(p,pp,pp+2,"*neq*");
10 reyssat 672
    }
5502 bpr 673
/* remove spaces */
10 reyssat 674
    for(pp=p; *pp; pp++) {
5502 bpr 675
    if(isspace(*pp)) {ovlstrcpy(pp,pp+1); pp--;}
10 reyssat 676
    }
8155 bpr 677
/* replace ** by ^  see __replace_badchar(p,"**", "^");*/
10 reyssat 678
    for(pp=strstr(p,"**"); pp!=NULL; pp=strstr(pp,"**")) {
3718 reyssat 679
      *pp='^'; ovlstrcpy(pp+1,pp+2);
10 reyssat 680
    }
681
    if(check_parentheses(p,1)!=0) module_error("unmatched_parentheses");
682
    texmathbuf[0]=0; t_onestring(p);
683
    mystrncpy(p,texmathbuf,MAX_LINELEN);
684
}