root/trunk/pst-map3d/pst-algparser.pro

Revision 5, 28.2 kB (checked in by jms, 8 months ago)

Déplacement des fichiers de Manuel dans le répertoire pst-map3d.

Line 
1 % $Id: pst-algparser.pro 7 2007-12-29 22:21:13Z herbert $
2 %
3 % PostScript prologue for PSTricks algorithm parser
4 % Version 0.01, 2008/01/01
5 % For distribution and copyright, see pstricks.tex.   hv@pstricks.de
6 %
7 %-----------------------------------------------------------------------------%
8 /AlgParser { tx@AlgToPs begin AlgToPs end } def  % Dominique Rodriguez
9 %
10 /tx@CoreAnalyzerDict 100 dict def tx@CoreAnalyzerDict begin
11 %
12 % PS ANALYZER FOR ALGEBRAIC EXPRESSION V1.12
13 % E->T|E+T
14 % T->FS|T*FS
15 % FS -> F | +FS | -FS
16 % F->P|F^SF
17 % P->(E)|literal
18 % literal->number|var|var[E]|func(params)
19 % params->E|E,param
20 % number->TOBEFINISHED
21 %
22 %% E expression, T term, SF signed factor, F factor, P power
23 %
24 %% parser
25 %
26 %% str
27 %
28 %% C->E<condition_operators>E
29 %% STR index -> STR index+lenExpr
30 /AnalyzeCond { AnalyzeExpr ReadCondOp AnalyzeExpr EvalCondOp  } def
31 %
32 %% analyze Expression List (separator , or | )
33 %% STR index -> STR index+lenExpr
34 %% /AnalyzeListOfE {
35 %%   { NextNonBlankChar pop AnalyzeExpr%%dup Strlen eq { exit } if NextNonBlankChar
36 %%     NextNonBlankChar dup 0 eq { pop exit } if
37 %%     dup 44 ne 1 index 124 ne and { dup 41 ne { PROBLEMCONTACTBILLOU } { pop exit } ifelse } if
38 %%     pop NextNonBlankChar dup 0 eq { exit } if 124 ne { PROBLEMCONTACTBILLOU } if 1 add NextNonBlankChar 0 eq {toto} if } loop
39 %%   AnalyzeListOfEPostHook
40 %% } def
41 /AnalyzeListOfE {
42   /NotFirst false def
43   { NextNonBlankChar pop AnalyzeExpr
44     NotFirst { EvalListOfExpr } { /NotFirst true def } ifelse
45     dup Strlen eq { exit } if NextNonBlankChar
46     dup 44 ne 1 index 124 ne and
47     { dup 41 ne { PROBLEMCONTACTBILLOU } { pop exit } ifelse }
48     if  pop 1 add } loop
49   AnalyzeListOfEPostHook
50 } def
51 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
52 %% E->T|E+T
53 %% STR index -> STR index+lenExpr
54 /AnalyzeExpr {
55   AnalyzePreHook AnalyzeTerm IsEndingExpr
56   { dup 0 ne { 32 eq { NextNonBlankChar } if } { pop } ifelse }
57   { { RollOp 1 add NextNonBlankChar pop AnalyzeTerm PreEvalHook EvalAddSub IsEndingExpr { pop exit } if } loop }
58   ifelse
59   AnalyzePostHook
60 } def
61 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
62 %% T->FS|T*FS
63 %% STR index
64 /AnalyzeTerm {
65   AnalyzePreHook AnalyzeSignedFactor IsEndingTerm
66   { dup 0 ne { 32 eq { NextNonBlankChar } if } { pop } ifelse }
67   { { RollOp 1 add NextNonBlankChar pop AnalyzeSignedFactor PreEvalHook EvalMulDiv IsEndingTerm { pop exit } if} loop }
68   ifelse
69   AnalyzePostHook
70 } def
71 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
72 %% FS -> F | +FS | -FS
73 %% STR index
74 /AnalyzeSignedFactor {
75   AnalyzePreHook 2 copy get dup IsUnaryOp
76   { RollOp 1 add NextNonBlankChar pop AnalyzeSignedFactor EvalUnaryOp }
77   { pop AnalyzeFactor }
78   ifelse AnalyzePostHook
79 } def
80 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
81 %% F->P|F^P
82 %% STR index
83 /AnalyzeFactor {
84   AnalyzePreHook AnalyzePower IsEndingFactor
85   { dup 0 ne { 32 eq { NextNonBlankChar } if } { pop } ifelse }
86   { { RollOp 1 add NextNonBlankChar pop AnalyzePower PreEvalHook EvalPower IsEndingFactor { pop exit } if} loop }
87   ifelse  AnalyzePostHook
88 } def
89 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
90 %% P->(E)|literal
91 %% STR index
92 /AnalyzePower {
93   %% depending of first char either a number, or a literal
94   2 copy get dup 40 eq%%an open par
95   { pop 1 add NextNonBlankChar pop AnalyzeExpr 1 add NextNonBlankChar pop }
96   { AnalyzeLiteral }
97   ifelse
98 } def
99 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
100 %% STR index STR[index] -> STR index
101 %/AnalyzeLiteral { IsNumber { EvalNumber } { EvalLiteral } ifelse } def
102 /AnalyzeLiteral { dup IsUnaryOp exch IsNumber or { EvalNumber } { EvalLiteral } ifelse } def%%dr 09102006
103 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
104 %% recognize + or -
105 %% chr -> T/F
106 /IsUnaryOp { dup 43 eq exch 45 eq or } bind def
107 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
108 %% a number can contain only : 0123456789.
109 %% chr -> T/F
110 /IsNumber { dup 48 ge exch dup 57 le 3 -1 roll and exch 46 eq or } bind def
111 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
112 %% STR index -> STR index number
113 %% a number can be of the form [0-9]*.[0-9]*\([eE][+-]?[0-9]+\)?
114 %% STR index -> STR index' number
115 /ReadNumber {
116   exch dup 3 -1 roll dup 3 1 roll
117   %%read mantissa
118   { 1 add  2 copy dup Strlen eq { pop pop 0 exit } if get dup IsNumber not { exit } if pop } loop
119   dup 101 eq exch 69 eq or
120   %%% there is a "e" or "E" -> read exponant
121   { 1 add 2 copy get dup IsUnaryOp
122     { pop 1 add 2 copy get } if
123     { IsNumber not { exit } if 1 add 2 copy get } loop }
124   if
125   dup 4 1 roll
126   3 -1 roll exch 1 index sub getinterval
127 } def
128 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
129 %% a number can contain only : 0123456789.
130 %% chr -> T/F
131 /IsCondOp { dup 30 eq exch dup 60 ge exch 62 le and or } bind def
132 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
133 %% STR index -> STR index number
134 %% a number can be of the form [0-9]*.[0-9]*\([eE][+-]?[0-9]+\)?
135 %% STR index -> STR index' number
136 /ReadCondOp {
137   NextNonBlankChar 1 index 4 1 roll
138   { IsCondOp not { exit } if 1 add  2 copy get } loop
139   2 copy 5 -1 roll
140   exch 1 index sub getinterval 3 1 roll
141 } def
142 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
143 %% a literal can contain only : 0123456789.
144 %% chr -> T/F
145 /IsLiteral {%
146   dup 48 ge exch dup  57 le 3 -1 roll and exch
147   dup 65 ge exch dup  90 le 3 -1 roll and 3 -1 roll or exch
148   dup 97 ge exch     122 le and or } bind def
149 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
150 %% a literal can be of the form [a-zA-Z][a-zA-Z0-9]*\(\((Expression)\)|\(\[Expression\]\)\)?
151 %% STR index -> literal STR index' nextchr
152 /ReadLiteral {
153   exch dup 3 -1 roll dup 3 1 roll
154   %%read literal core
155   { 2 copy dup Strlen eq { pop pop 0 exit } if get dup IsLiteral not { exit } if pop 1 add } loop
156   4 1 roll dup 5 1 roll 3 -1 roll exch 1 index sub getinterval 4 1 roll
157 } def
158 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
159 %% expr is ended by end of str or a clpar
160 %% STR index -> STR index STR[index] T/F
161 /IsEndingExpr {%
162   2 copy dup Strlen eq
163   %% if end of str is reached -> end !
164   { pop pop 0 true }
165   %% ending chr -> clpar, comma, |, <, >, =, !,
166   {get dup  dup  41 eq
167        exch dup 124 eq
168        exch dup  93 eq
169        exch dup  44 eq
170        exch dup  30 eq
171        exch dup  60 ge exch 62 le and or or or or or}
172   ifelse } def
173 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
174 %% expr is ended by end of str or a +-
175 %% STR index -> STR index STR[index] T/F
176 /IsEndingTerm { IsEndingExpr { true } { dup dup 43 eq exch 45 eq or } ifelse } def
177 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
178 %% expr is ended by end of str or */
179 %% STR index -> STR index STR[index] T/F
180 /IsEndingFactor { IsEndingTerm { true } { dup dup 42 eq exch 47 eq or } ifelse } def
181 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
182 %% expr is ended by end of str or ^
183 %% STR index -> STR index STR[index] T/F
184 /IsEndingPower { IsEndingFactor { true } { dup 94 eq } ifelse } def
185 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
186 %% STR index -> STR index STR[index]
187 /NextNonBlankChar { { dup Strlen eq { 0 exit } if 2 copy get dup neBlkChar { exit } if pop 1 add } loop } bind def
188 /neBlkChar { dup 32 ne exch dup 10 ne exch 9 ne and and } bind def
189 %%%%%%%%%%%%%%%%%%%%%%%%
190 %% DEBUG
191 /BRK {false} def
192 /BRKtrue {/BRK true def} def
193 /BRKStop {BRK {BRKtoto} if } def
194 /BRKEvalStop {BRK exch if } def
195 /BRKBRK2true {BRK {BRK2true} if } def
196 /BRK2 {false} def
197 /BRK2true {/BRK2 true def} def
198 /BRK2Stop {BRK2 {BRK2toto} if } def/BRK {false} def
199 end
200 %
201 %-------------------------------------------------------------------------------%
202 %
203 /tx@AlgToPs 12 dict def tx@AlgToPs begin
204 %
205 %% algExpr -> PSVector
206 /AlgToPs { tx@CoreAnalyzerDict begin InitParser AnalyzeListOfE pop pop EndingSequence end } def
207 /EndingSequence { ExpressionVector aload length /end cvx exch 1 add array astore } def
208 /InitParser { /ExpressionVector [ /tx@AddMathFunc cvx /begin cvx ] def dup length /Strlen exch def 0 } def
209 /Strlen 0 def
210 /EvalListOfExpr {} def%
211 /EvalNumber {%
212     ReadNumber  cvr /ExpressionVector ExpressionVector aload length dup 3 add -1 roll cvx
213     exch 1 add array astore def NextNonBlankChar pop } def
214 /EvalAddSub {%
215   /ExpressionVector ExpressionVector aload length dup 5 add -1 roll
216   43 eq { /add } { /sub } ifelse cvx exch 1 add array astore def
217 } def
218 /EvalMulDiv {%
219   /ExpressionVector ExpressionVector aload length dup 5 add -1 roll
220   42 eq { /mul } { /div } ifelse cvx exch 1 add array astore def
221 } def
222 /EvalPower {%
223   /ExpressionVector ExpressionVector aload length dup 5 add -1 roll
224   pop /exp cvx exch 1 add array astore def
225 } def
226 /EvalLiteral {%
227   ReadLiteral
228   dup 40 eq%%% there is an open par -> function call
229   { pop 2 index
230     dup (Sum) eq { EvalSum }
231     { dup (IfTE) eq { EvalCond }
232       { dup (Derive) eq { pop EvalDerive }
233         { pop 1 add NextNonBlankChar pop AnalyzeListOfE 2 index TrigoFunc
234           /ExpressionVector ExpressionVector aload length dup 5 add -1 roll cvn cvx
235           exch 1 add array astore def 1 add NextNonBlankChar pop } ifelse } ifelse} ifelse }
236   { /ExpressionVector ExpressionVector aload length dup 6 add -1 roll cvn cvx exch 1 add array astore def
237     dup 91 eq%%% there is an open bracket -> vector element
238     { pop 1 add NextNonBlankChar pop AnalyzeExpr
239       /ExpressionVector ExpressionVector aload length /cvi cvx exch /get cvx exch 2 add array astore def 1 add }
240     { pop NextNonBlankChar pop }
241     ifelse}
242   ifelse
243 } def
244 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
245 %% the derive function : Derive(n,f(x))
246 %% firstparindex lastparindex ->
247 /EvalDerive {
248   %% manage the function descripiton
249   1 add ReadNumber 3 1 roll NextNonBlankChar
250   44 ne { ANALYZER_ERROR_missing_second_comma_in_Sum } if
251   1 add NextNonBlankChar pop
252   3 -1 roll cvi
253   dup 0 eq
254   { pop AnalyzeExpr 3 -1 roll pop 1 add }
255   { 1 sub 3 1 roll (x)  exch tx@Derive begin DeriveIndexed end 4 -1 roll
256     { (x) tx@Derive begin Derive end } repeat
257     ExpressionVector exch /ExpressionVector [] def
258     AlgToPs aload length
259     /ExpressionVector 1 index 3 add -1 roll aload length dup 3 add -1 roll  /l2 exch def /l1 exch def
260     l1 l2 add 1 add l2 neg roll l1 l2 add array astore def 3 -1 roll pop 1 add
261     1 index length /Strlen exch def } ifelse
262 } def
263 /EvalSum {%
264   pop 1 add NextNonBlankChar pop
265   %% read the variable name
266   ReadLiteral pop NextNonBlankChar
267   44 ne { ANALYZER_ERROR_missing_first_comma_in_Sum } if
268   %% read the initial value
269   1 add NextNonBlankChar pop ReadNumber cvi 3 1 roll
270   2 copy get 44 ne { ANALYZER_ERROR_missing_second_comma_in_Sum } if
271   %% read the increment value
272   1 add NextNonBlankChar pop ReadNumber cvi 3 1 roll
273   2 copy get 44 ne { ANALYZER_ERROR_missing_second_comma_in_Sum } if
274   %% read the limit value
275   1 add NextNonBlankChar pop ReadNumber cvi 3 1 roll
276   2 copy get 44 ne { ANALYZER_ERROR_missing_second_comma_in_Sum } if
277   /ExpressionVector ExpressionVector aload length dup 7 add -3 roll 0 4 1 roll
278   5 -1 roll 4 add array astore def
279   %% keep ExpressionVector for later and create a new one for internal Sum computation
280   ExpressionVector 3 1 roll /ExpressionVector [ 6 -1 roll cvn /exch cvx /def cvx ] def
281   1 add NextNonBlankChar pop AnalyzeExpr
282   %% add each term
283   /ExpressionVector ExpressionVector aload length 1 add /add cvx exch array astore def
284   /ExpressionVector 4 -1 roll aload length ExpressionVector cvx /for cvx 3 -1 roll 2 add
285   array astore def 3 -1 roll pop 1 add
286 } def
287 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
288 %% Convert to radians if trigo function call
289 %% (name) ->
290 /TrigoFunc {
291   dup (cos) eq 1 index (sin) eq or exch (tan) eq or
292   { /ExpressionVector ExpressionVector aload length Pi /div cvx 180 /mul cvx 5 -1 roll 4 add
293     array astore def
294   } if
295 } def
296 /EvalCond {%
297   pop 1 add AnalyzeCond NextNonBlankChar
298   44 ne { ANALYZER_ERROR_missing_first_comma_in_IfTE } if
299   ExpressionVector 3 1 roll /ExpressionVector [] def
300   1 add AnalyzeExpr ExpressionVector 3 1 roll /ExpressionVector [] def
301   NextNonBlankChar 44 ne { ANALYZER_ERROR_missing_second_comma_in_IfTE } if
302   1 add AnalyzeExpr
303   NextNonBlankChar 41 ne { ANALYZER_ERROR_missing_ending parenthesis_in_IfTE } if
304   ExpressionVector
305   /ExpressionVector 6 -1 roll aload length dup
306   6 add -1 roll cvx exch dup 4 add -1 roll cvx /ifelse cvx 3 -1 roll 3 add array astore def
307   1 add 3 -1 roll pop
308 } def
309 %% CondOp STR index
310 /EvalCondOp {%
311   3 -1 roll
312   dup (=) eq  { /eq } {%
313   dup (<) eq  { /lt } {%
314   dup (>) eq  { /gt } {%
315   dup (>=) eq { /ge } {%
316   dup (<=) eq { /ge } {%
317   dup (!=) eq { /ne } { ERROR_non_valid_conditional_operator }
318   ifelse } ifelse } ifelse } ifelse } ifelse } ifelse
319   cvx exch pop
320   /ExpressionVector ExpressionVector aload length dup 3 add -1 roll exch 1 add array astore def } def
321 /EvalUnaryOp {
322   3 -1 roll 45 eq { /ExpressionVector ExpressionVector aload length /neg cvx exch 1 add array astore def } if
323 } def
324 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
325 %% H O O K S
326 /AnalyzePreHook {} bind def
327 /PreEvalHook {} bind def
328 /AnalyzeListOfEPostHook {} bind def
329 /AnalyzePostHook {} def
330 /RollOp { 3 1 roll } bind def
331 end   %tx@CoreAnalyzerDict
332 %
333 %--------------------------------------------------------------------%
334 %
335 /tx@Derive 41 dict def tx@Derive begin
336 %%increase ^^ for each function added
337 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
338 %% algExpr variable -> PSVector
339 /Derive {%
340   10240 string 3 1 roll 0 3 1 roll
341   /Variable exch def
342   tx@CoreAnalyzerDict begin InitParser AnalyzeListOfE end
343 } def
344 /Strlen 0 def
345 /InitParser { dup length /Strlen exch def 0 } def
346 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
347 %% algExpr variable index -> PSVector
348 /DeriveIndexed {%
349   3 1 roll 10240 string 3 1 roll 0 3 1 roll
350   /Variable exch def
351   tx@CoreAnalyzerDict begin InitParser pop 4 -1 roll AnalyzeExpr 4 -2 roll pop pop 4 -2 roll exch pop end
352 } def
353 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
354 %% (u,v)'=-(u',v')
355 /EvalListOfExpr {%
356   4 2 roll 2 copy 9 -1 roll dup length 4 1 roll putinterval add AddPipe
357            2 copy 7 -1 roll dup length 4 1 roll putinterval add
358   6 -2 roll pop pop
359   2 copy pop 0 6 2 roll GetIntervalNewStr 5 1 roll 2 copy 0 exch getinterval 6 1 roll } def
360 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
361 %% (-u)'=-(u')
362 /EvalUnaryOp {
363   4 -2 roll 4 index (0) eq
364   { (0) StrConcat 7 -1 roll pop }
365   { 7 -1 roll 45 eq
366     { AddSub AddOpPar true } { false } ifelse
367     3 1 roll 5 index StrConcat 3 -1 roll { AddClPar } if } ifelse
368   2 copy pop 0 6 2 roll GetIntervalNewStr
369   7 -2 roll pop pop 2 index 6 index dup 4 index exch sub getinterval exch 6 2 roll
370 } def
371 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
372 %% (number)'=0
373 /EvalNumber { ReadNumber (0) 6 2 roll } def
374 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
375 %% (u+v)'=u'+v'
376 /EvalAddSub {%
377   7 index dup (0) eq
378   { pop true }%% du=0 nothing added
379   { dup length exch 5 index 5 index 3 -1 roll putinterval 4 -1 roll add 3 1 roll false }
380   ifelse
381   5 index dup (0) eq
382   { pop { (0) } { 4 -2 roll 2 copy pop 0  6 2 roll GetIntervalNewStr } ifelse }%%dv=0
383   { exch
384     { 5 -2 roll 7 index 45 eq { AddSub } if false } %%nothing yet added
385     { 5 -2 roll 7 index 43 eq%%something yet added
386       { AddAdd false } { AddSub AddOpPar true } ifelse }
387     ifelse 11 1 roll
388     3 -1 roll StrConcat 10 -1 roll { AddClPar } if
389     2 copy pop 0 6 2 roll GetIntervalNewStr }
390   ifelse
391   mark 11 -5 roll cleartomark 2 index 6 index dup 4 index exch sub getinterval exch 6 2 roll
392 } def
393 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
394 %% (u*v)' or (u/v)'
395 /EvalMulDiv { 6 index 42 eq {EvalMul} {EvalDiv} ifelse } def
396 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
397 %% (u*v)'=u'*v+u*v'
398 /EvalMul {%
399   4 -2 roll 7 index dup (0) eq
400   { pop false }%%du=0
401   { (1) eq%%du=1
402     { false }
403     { AddOpPar 7 index StrConcat AddClPar AddMul AddOpPar true } ifelse
404     3 1 roll 6 index StrConcat 3 -1 roll { AddClPar } if
405     true }%%du!=0
406   ifelse
407   5 1 roll 5 index (0) eq
408   { 5 -1 roll not { (0) StrConcat } if }%%dv=0
409   { 5 -1 roll { AddAdd } if
410     4 index (1) eq
411     { 8 index StrConcat }
412     { AddOpPar 8 index StrConcat AddClPar AddMul AddOpPar 4 index StrConcat AddClPar }
413     ifelse
414   }%%dv!=0
415   ifelse
416   2 copy pop 0 6 2 roll GetIntervalNewStr
417   mark 11 -5 roll cleartomark 2 index 6 index dup 4 index exch sub getinterval exch 6 2 roll
418 } def
419 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
420 %% (u/v)'=(u'*v-u*v')/v^2
421 /EvalDiv {%
422   4 -2 roll
423   4 index (0) eq%%dv=0 -> u'/v
424   { 7 index (0) eq { (0) StrConcat } { AddOpPar 7 index StrConcat AddClPar AddDiv 5 index StrConcat } ifelse }
425   { 7 index dup (0) eq
426     { pop }%%du=0
427     { (1) eq%%du=1
428       { false }
429       { AddOpPar 7 index StrConcat AddClPar AddMul AddOpPar true } ifelse
430       3 1 roll 6 index StrConcat 3 -1 roll { AddClPar } if}%%du!=0
431     ifelse
432       AddSub
433       4 index (1) eq
434       { 8 index StrConcat }
435       { AddOpPar 8 index StrConcat AddClPar AddMul AddOpPar 4 index StrConcat AddClPar }
436       ifelse
437     %}%%dv!=0
438     2 copy GetIntervalNewStr 3 1 roll pop 0 AddOpPar 3 -1 roll StrConcat AddClPar
439     AddDiv AddOpPar 5 index StrConcat AddClPar 2 copy (^2) putinterval 2 add }
440   ifelse
441   2 copy pop 0 6 2 roll GetIntervalNewStr
442   mark 11 -5 roll cleartomark 2 index 6 index dup 4 index exch sub getinterval exch 6 2 roll
443 } def
444 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
445 %% str1 index str2 -> str1 index
446 /StrConcat { dup length 4 2 roll 2 copy 6 -1 roll putinterval 3 -1 roll add } bind def
447 /GetIntervalNewStr { 0 exch getinterval dup length string copy } bind def
448 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
449 %% (u^v)'=(u^v)'=u'vu^(v-1)+v'u^(v)ln(u)
450 /EvalPower {%
451   4 -2 roll 7 index (0) eq
452   {%%if du=0 then (u^v)'=v'ln(u)u^v
453     4 index (0) eq
454     { (0) StrConcat }%%if dv=0 then (u^v)'=0
455     { 4 index (1) ne { AddOpPar 4 index StrConcat (\)*) StrConcat } if
456       8 index (e) ne { (ln\() StrConcat 8 index StrConcat (\)*) StrConcat } if
457       AddOpPar 8 index StrConcat (\)^\() StrConcat 5 index StrConcat AddClPar } ifelse
458   }
459   {%%du!=0
460     4 index (0) eq
461     {%%if dv=0 then (u^v)'=vu'u^(v-1)
462       5 index dup IsStrNumber
463       { dup (0) eq
464         { StrConcat }
465         { dup dup (1) eq exch (1.0) eq or
466           { StrConcat  }
467           { StrConcat
468             7 index dup (1) ne exch (1.0) ne and%%%dr 09102006 insert du if <> 1
469             { (*\() StrConcat 7 index StrConcat (\)) StrConcat } if%%%dr 09102006
470             (*\() StrConcat 8 index StrConcat (\)) StrConcat
471             5 index  dup dup (2) eq exch (2.0) eq or
472             { pop } { cvr 1 sub 20 string cvs 3 1 roll (^) StrConcat 3 -1 roll StrConcat } ifelse } ifelse } ifelse }
473       { pop AddOpPar 5 index StrConcat (\)*\() StrConcat 8 index StrConcat (\)^\() StrConcat
474         5 index StrConcat (-1\)) StrConcat } ifelse
475     }
476     {%%if dv!=0 and du!=0 then (u^v)'=u'vu^(v-1)+v'u^(v)ln(u)
477       7 index (1) ne { AddOpPar 7 index StrConcat (\)*) StrConcat } if
478       AddOpPar 5 index StrConcat (\)*\() StrConcat
479       8 index StrConcat (\)^\() StrConcat
480       5 index StrConcat (-1\)+\() StrConcat
481       4 index (1) ne { 4 index StrConcat (\)*\() StrConcat } if
482       8 index StrConcat (\)^\() StrConcat
483       5 index StrConcat (\)*ln\() StrConcat
484       8 index StrConcat AddClPar
485     } ifelse
486   } ifelse
487   2 copy pop 0 6 2 roll GetIntervalNewStr
488   mark 11 -5 roll cleartomark 2 index 6 index dup 4 index exch sub getinterval exch 6 2 roll
489 } def
490 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
491 %% str -> true/false
492 /IsStrNumber {%
493   true exch
494   { dup 48 lt exch dup 57 gt 3 -1 roll or
495     exch dup 46 ne%%.
496     exch dup 43 ne%%+
497     exch 45 ne%%-
498     and and and { pop false } if } forall
499 } def
500 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
501 %% literal switch -> func call, vector, variables
502 /EvalLiteral {%
503   ReadLiteral dup 40 eq%%% there is an open par -> function call
504   { pop (EvalFunc_             ) 9 4 index StrConcat 0 exch getinterval cvn cvx exec }
505   { dup 91 eq%%% there is an open bracket -> vector element
506     { ERROR_vector_not_yet_implemented }
507     { pop EvalVariable }
508     ifelse }
509   ifelse
510 } def
511 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
512 %% first last parpos Expr[first:parpos-1] ->
513 /EvalVariable { 2 index Variable eq { (1) } { (0) } ifelse 4 -1 roll exch 6 2 roll } def
514 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
515 %% (f(u))'=u'f'(u)
516 /EvalFunc {
517   4 2 roll 4 index (1) ne
518   { AddOpPar 4 index StrConcat (\)*) StrConcat } if
519   (Eval             ) 4 8 index StrConcat 0 exch getinterval cvn cvx exec
520   2 copy pop 0 6 2 roll GetIntervalNewStr
521   mark 9 -3 roll cleartomark 2 index 6 index dup 4 index exch sub getinterval exch 6 2 roll
522 } def
523 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
524 %% Func derivative -> Eval<func>
525 /EvalFunc_sin {%
526   PreCommonFunc
527   { (cos\() StrConcat 5 index StrConcat AddClPar } if
528   PostCommonFunc } def
529 /EvalFunc_cos {%
530   PreCommonFunc
531   { (\(-sin\() StrConcat 5 index StrConcat (\)\)) StrConcat } if
532   PostCommonFunc } def
533 /EvalFunc_tan {%
534   PreCommonFunc
535   {  dup 0 eq { (1) StrConcat } { 1 sub } ifelse  (/cos\() StrConcat 5 index StrConcat (\)^2) StrConcat } if
536   PostCommonFunc } def
537 /EvalFunc_asin {%
538   PreCommonFunc
539   { (1/sqrt\(1-\() StrConcat 5 index StrConcat (\)^2\)\)) StrConcat } if
540   PostCommonFunc } def
541 /EvalFunc_acos {%
542   PreCommonFunc
543   { (-1/sqrt\(1-\() StrConcat 5 index StrConcat (\)^2\)\)) StrConcat } if
544   PostCommonFunc } def
545 /EvalFunc_atg {%
546   PreCommonFunc
547   { (1/\(1+\() StrConcat 5 index StrConcat (\)^2\)\)) StrConcat } if
548   PostCommonFunc } def
549 /EvalFunc_ln {%
550   PreCommonFunc
551   {  dup 0 eq { (1) StrConcat } { 1 sub } ifelse (/\() StrConcat 5 index StrConcat AddClPar } if
552   PostCommonFunc } def
553 /EvalFunc_exp {%
554   PreCommonFunc
555   {  (exp\() StrConcat 5 index StrConcat AddClPar } if
556   PostCommonFunc } def
557 /EvalFunc_sqrt {%
558   PreCommonFunc
559   { dup 0 eq { (1) StrConcat } { 1 sub } ifelse (/\(2*sqrt\() StrConcat 5 index StrConcat (\)\)) StrConcat } if
560   PostCommonFunc } def
561 /EvalFunc_Fact {%
562   PreCommonFunc { ERROR_no_variable_expression_in_Fact } if
563   PostCommonFunc } def
564 /EvalFunc_sh {%
565   PreCommonFunc
566   { (ch\() StrConcat 5 index StrConcat AddClPar } if
567   PostCommonFunc } def
568 /EvalFunc_ch {%
569   PreCommonFunc
570   { (sh\() StrConcat 5 index StrConcat AddClPar } if
571   PostCommonFunc } def
572 /EvalFunc_th {%
573   PreCommonFunc
574   {  dup 0 eq { (1) StrConcat } { 1 sub } ifelse  (/ch\() StrConcat 5 index StrConcat (\)^2) StrConcat } if
575   PostCommonFunc } def
576 /EvalFunc_Argsh {%
577   PreCommonFunc
578   { (1/sqrt\(1+\() StrConcat 5 index StrConcat (\)^2\)\)) StrConcat } if
579   PostCommonFunc } def
580 /EvalFunc_Argch {%
581   PreCommonFunc
582   { (1/sqrt\(\() StrConcat 5 index StrConcat (\)^2-1\)\)) StrConcat } if
583   PostCommonFunc } def
584 /EvalFunc_Argth {%
585   PreCommonFunc
586   { (1/\(1-\() StrConcat 5 index StrConcat (\)^2\)\)) StrConcat } if
587   PostCommonFunc } def
588 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
589 /PreCommonFunc {
590   1 add NextNonBlankChar pop 3 -1 roll 5 1 roll AnalyzeExpr 1 add NextNonBlankChar pop
591   4 2 roll 4 index (0) eq
592   { (0) StrConcat false }
593   { 4 index (1)  ne { AddOpPar 4 index StrConcat (\)*) StrConcat } if true } ifelse
594 } def
595 /PostCommonFunc {
596   2 copy pop 0 6 2 roll GetIntervalNewStr
597   mark 9 -3 roll cleartomark 2 index 6 index dup 4 index exch sub getinterval exch 6 2 roll
598 } def
599 /EvalFunc_Derive {%
600   1 add ReadNumber cvi 1 add dup cvr log 1 add cvi string cvs
601   4 -1 roll pop 5 1 roll 1 add NextNonBlankChar pop AnalyzeExpr 1 add
602   4 -2 roll (Derive\() StrConcat 7 -1 roll StrConcat (,) StrConcat 6 -1 roll StrConcat AddClPar
603   2 copy pop 0 6 2 roll GetIntervalNewStr 6 -1 roll pop 2 index 6 index dup 4 index exch sub getinterval
604   exch 6 2 roll } def
605 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
606 %% literal switch -> func call, vector, variables
607 /EvalFunc_Sum {%
608   1 add NextNonBlankChar pop
609   %% read the variable name
610   ReadLiteral pop 3 -1 roll pop NextNonBlankChar
611   44 ne { ANALYZER_ERROR_missing_first_comma_in_Sum } if
612   %% read the initial value
613   1 add NextNonBlankChar pop ReadNumber pop
614   2 copy get 44 ne { ANALYZER_ERROR_missing_second_comma_in_Sum } if
615   %% read the increment value
616   1 add NextNonBlankChar pop ReadNumber pop
617   2 copy get 44 ne { ANALYZER_ERROR_missing_third_comma_in_Sum } if
618   %% read the limit value
619   1 add NextNonBlankChar pop ReadNumber pop
620   2 copy get 44 ne { ANALYZER_ERROR_missing_fourth_comma_in_Sum } if
621   1 add NextNonBlankChar pop dup 6 1 roll 3 -1 roll pop AnalyzeExpr 1 add NextNonBlankChar pop
622   4 -2 roll 3 index 8 index dup 9 index exch sub getinterval StrConcat
623   4 index StrConcat AddClPar
624   2 copy pop 0 6 2 roll GetIntervalNewStr
625   mark 9 -3 roll cleartomark 2 index 6 index dup 4 index exch sub getinterval exch 6 2 roll
626 } def
627 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
628 %% literal switch -> func call, vector, variables
629 /EvalFunc_IfTE {%
630   3 -1 roll pop 1 add NextNonBlankChar pop SkipCond
631   NextNonBlankChar
632   44 ne { ANALYZER_ERROR_missing_first_comma_in_IfTE } if
633   1 add NextNonBlankChar pop dup 5 1 roll
634   AnalyzeExpr NextNonBlankChar
635   44 ne { ANALYZER_ERROR_missing_second_comma_in_IfTE } if
636   1 add NextNonBlankChar pop
637   AnalyzeExpr 1 add NextNonBlankChar pop
638   4 -2 roll 3 index 10 index dup 11 index exch sub getinterval StrConcat
639   6 index StrConcat (,) StrConcat 4 index StrConcat AddClPar
640   2 copy pop 0 6 2 roll GetIntervalNewStr
641   mark 11 -5 roll cleartomark 2 index 6 index dup 4 index exch sub getinterval exch 6 2 roll
642 } def
643 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
644 %% advance in str until a comma is found (no error detection!)
645 %% str index -> str index'
646 /SkipCond { { 1 add 2 copy get 44 eq {exit } if } loop } bind def
647 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
648 %% Convert to radians if trigo function call
649 %% (name) ->
650 /TrigoFunc {
651   dup (cos) eq 1 index (sin) eq or exch (tan) eq or
652   { /ExpressionVector ExpressionVector aload length Pi /div cvx 180 /mul cvx 5 -1 roll 4 add
653     array astore def
654   } if
655 } def
656 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
657 %% No derivative for condition....
658 /EvalCondOp { 3 -1 roll pop } bind def
659 /PutIntervalOneAdd {putinterval 1 add} bind def
660 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
661 %% Add open parenthesis in string at the given index
662 %% str index -> str index+1
663 /AddOpPar {2 copy (\() PutIntervalOneAdd} bind def
664 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
665 %% Add close parenthesis in string at the given index
666 %% str index -> str index+1
667 /AddClPar {2 copy (\)) PutIntervalOneAdd} bind def
668 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
669 %% Add 0 in string at the given index
670 %% str index -> str index+1
671 /AddZero {2 copy (0) PutIntervalOneAdd} bind def
672 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
673 %% Add open parenthesis in string at the given index
674 %% str index -> str index+1
675 /AddMul {2 copy (*) PutIntervalOneAdd} bind def
676 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
677 %% Add open parenthesis in string at the given index
678 %% str index -> str index+1
679 /AddDiv {2 copy (/) PutIntervalOneAdd} bind def
680 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
681 %% Add a plus sign in string at the given index
682 %% str index -> str index+1
683 /AddAdd {2 copy (+) PutIntervalOneAdd} bind def
684 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
685 %% Add a minus sign in string at the given index
686 %% str index -> str index+1
687 /AddSub {2 copy (-) PutIntervalOneAdd} bind def
688 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
689 %% Add a pipe sign in string at the given index
690 %% str index -> str index+1
691 /AddPipe {2 copy (|) PutIntervalOneAdd} bind def
692 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
693 %% H O O K S
694 /AnalyzePreHook { dup 5 1 roll } bind def
695 /PreEvalHook {} def
696 /AnalyzePostHook { 7 -1 roll pop } bind def
697 /AnalyzeListOfEPostHook { 6 -1 roll mark 6 1 roll cleartomark } bind def
698 /RollOp { 5 1 roll } bind def
699 end%%%tx@CoreAnalyzerDict
700 /tx@AddMathFunc 12 dict def tx@AddMathFunc begin
701 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
702 %% NEW FUNC
703 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
704 %% function arcsine in radians asin(x)=atan(x/sqrt(1-x^2))
705 %% x -> theta
706 /asin {%
707   dup abs 1 gt { EQDFasinrangeerror  } if
708   dup dup dup mul 1 exch sub sqrt atan exch 0 lt { 360 sub } if DegtoRad
709 } def
710 %% function arccosine in radians acos(x)=atan(sqrt(1-x^2)/x)
711 %% x -> theta
712 /acos {%
713   dup abs 1 gt { EQDFacosrangeerror  } if
714   dup dup mul 1 exch sub sqrt exch atan DegtoRad
715 } def
716 %% function arctangent in radians
717 %% x -> theta
718 /atg { 1 atan dup 90 gt { 360 sub } if DegtoRad } bind def
719 %% HYPERBOLIC FUNCTIONS
720 /sh { dup Ex exch neg Ex sub 2 div } def
721 /ch { dup Ex exch neg Ex add 2 div } def
722 /th { dup sh exch ch div } def
723 /Argsh { dup dup mul 1 add sqrt add ln } def
724 /Argch { dup dup mul 1 sub sqrt add ln } def
725 /Argth { dup 1 add exch 1 exch sub div ln 2 div } def
726 %% modified exponential funtion for 0
727 %% x n -> x^n
728 /Exp { dup 0 eq { pop pop 1 } { exp } ifelse } bind def
729 %% modified exponential funtion for 0
730 %% x -> e^x
731 /Ex { Euler exch exp } bind def
732 %%
733 %% factorial function
734 %% n -> n!
735 /Fact { 1 exch 2 exch 1 exch { mul } for } bind def
736 /fact { Fact } bind def
737 end
738
739 % END pstricks.pro
Note: See TracBrowser for help on using the browser.