Subversion Repositories wimsdev

Rev

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