home *** CD-ROM | disk | FTP | other *** search
/ Turbo Toolbox / Turbo_Toolbox.iso / spezial / 04 / calcderi.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1989-04-26  |  16.6 KB  |  461 lines

  1. (*****************************************************************************)
  2. (*                               CACLDERI.PAS                                *)
  3. (*                                                                           *)
  4. (*                     Symbolisches Differenzieren mit Calc                  *)
  5. (*****************************************************************************)
  6.  
  7.  
  8. FUNCTION calcderivation(pptr : calc_prog; vartab : calc_vartab; nach :
  9.                           calc_idstr) : calc_prog;
  10.  
  11. CONST pi_durch_180 = 1.745329252e-2;
  12.  
  13. VAR pptrstart,pptr1 : calc_prog;
  14.     ok : boolean;
  15.  
  16.   PROCEDURE uppercase(VAR varid : calc_idstr);
  17.  
  18.   VAR i : INTEGER;
  19.  
  20.   BEGIN
  21.     FOR i := 1 TO Length(varid) DO
  22.       varid[i] := Upcase(varid[i])
  23.   END;
  24.  
  25.   PROCEDURE newconst(x : calc_operand);
  26.  
  27.   VAR pptr : calc_prog;
  28.  
  29.   BEGIN
  30.     IF heapavail > 160
  31.       THEN
  32.         BEGIN
  33.           New(pptr);
  34.           pptr^.instruct := calc_const;
  35.           pptr^.operand := x;
  36.           pptr^.nextinst := pptrstart^.nextinst;
  37.           pptrstart^.nextinst := pptr
  38.         END
  39.       ELSE
  40.         calcresult := FALSE
  41.   END;
  42.  
  43.   PROCEDURE newop(id : calc_symbols);
  44.  
  45.   VAR pptr : calc_prog;
  46.  
  47.   BEGIN
  48.     IF heapavail > 160
  49.       THEN
  50.         BEGIN
  51.           New(pptr);
  52.           pptr^.instruct := id;
  53.           pptr^.nextinst := pptrstart^.nextinst;
  54.           pptrstart^.nextinst := pptr;
  55.         END
  56.       ELSE
  57.         calcresult := FALSE
  58.   END;
  59.  
  60.   PROCEDURE push(pptr : calc_prog);
  61.  
  62.   VAR pptr1 : calc_prog;
  63.       op : INTEGER;
  64.  
  65.   BEGIN
  66.     op := 1;
  67.     REPEAT
  68.       IF heapavail > 160
  69.         THEN
  70.           BEGIN
  71.             IF pptr^.instruct IN [calc_add..calc_pow]
  72.               THEN
  73.                 op := op + 1
  74.               ELSE
  75.                 IF NOT (pptr^.instruct IN [calc_neg,calc_sqr..calc_fak])
  76.                   THEN
  77.                     op := op - 1;
  78.             New(pptr1);
  79.             pptr1^ := pptr^;
  80.             pptr1^.nextinst := pptrstart^.nextinst;
  81.             pptrstart^.nextinst := pptr1;
  82.             pptr := pptr^.nextinst
  83.           END
  84.         ELSE
  85.           calcresult := FALSE
  86.     UNTIL (op = 0) OR NOT calcresult;
  87.   END;
  88.  
  89.   PROCEDURE derive(pptr : calc_prog);
  90.  
  91.   VAR pptra,pptrb : calc_prog;
  92.  
  93.   BEGIN
  94.     IF calcresult
  95.       THEN
  96.         BEGIN
  97.           pptra := pptr^.nextinst;
  98.           IF (pptra <> nil)
  99.             THEN
  100.               BEGIN
  101.                 pptrb := endof(pptra);
  102.                 pptrb := pptrb^.nextinst
  103.               END;
  104.           CASE pptr^.instruct OF
  105.             calc_neg   : BEGIN
  106.                            newop(calc_neg);
  107.                            derive(pptra)
  108.                          END;
  109.             calc_const,calc_div..calc_kgv,calc_fak : BEGIN
  110.                                                       newconst(0.0);
  111.                                                      END;
  112.             calc_var  : BEGIN
  113.                           IF nach = vartab^[pptr^.varindex].varid
  114.                             THEN
  115.                               newconst(1.0)
  116.                             ELSE
  117.                               newconst(0.0);
  118.                         END;
  119.             calc_add  : BEGIN
  120.                           IF calc_const IN[pptra^.instruct,pptrb^.instruct]
  121.                             THEN
  122.                               IF pptra^.instruct = calc_const
  123.                                 THEN
  124.                                   derive(pptrb)
  125.                                 ELSE
  126.                                   derive(pptra)
  127.                             ELSE
  128.                               BEGIN
  129.                                 newop(calc_add);
  130.                                 derive(pptra);
  131.                                 derive(pptrb)
  132.                               END
  133.                         END;
  134.             calc_sub  : BEGIN
  135.                           IF calc_const IN [pptra^.instruct,pptrb^.instruct
  136.                               ]
  137.                             THEN
  138.                               IF pptra^.instruct = calc_const
  139.                                 THEN
  140.                                   derive(pptrb)
  141.                                 ELSE
  142.                                   BEGIN
  143.                                     newop(calc_neg);
  144.                                     derive(pptra)
  145.                                   END
  146.                             ELSE
  147.                               BEGIN
  148.                                 newop(calc_sub);
  149.                                 derive(pptra);
  150.                                 derive(pptrb)
  151.                               END
  152.                         END;
  153.             calc_mul : BEGIN
  154.                          IF calc_const IN [pptra^.instruct,pptrb^.instruct]
  155.                            THEN
  156.                              IF pptra^.instruct = calc_const
  157.                                THEN
  158.                                  BEGIN
  159.                                    newop(calc_mul);
  160.                                    push(pptra);
  161.                                    derive(pptrb)
  162.                                  END
  163.                                ELSE
  164.                                  BEGIN
  165.                                    newop(calc_mul);
  166.                                    push(pptrb);
  167.                                    derive(pptra)
  168.                                  END
  169.                            ELSE
  170.                              BEGIN
  171.                                newop(calc_add);
  172.                                newop(calc_mul);
  173.                                derive(pptra);
  174.                                push(pptrb);
  175.                                newop(calc_mul);
  176.                                push(pptra);
  177.                                derive(pptrb);
  178.                              END
  179.                        END;
  180.             calc_dvd : BEGIN
  181.                          IF pptra^.instruct = calc_const
  182.                            THEN
  183.                              BEGIN
  184.                                newop(calc_dvd);
  185.                                push(pptra);
  186.                                derive(pptrb)
  187.                              END
  188.                            ELSE
  189.                              BEGIN
  190.                                newop(calc_dvd);
  191.                                newop(calc_sqr);
  192.                                push(pptra);
  193.                                newop(calc_sub);
  194.                                newop(calc_mul);
  195.                                derive(pptra);
  196.                                push(pptrb);
  197.                                newop(calc_mul);
  198.                                push(pptra);
  199.                                derive(pptrb)
  200.                              END
  201.                        END;
  202.             calc_pow  : BEGIN
  203.                           if (pptrb^.instruct = calc_const)
  204.                            and (pptrb^.operand < 0.0)
  205.                                   THEN calcresult := false
  206.                               ELSE
  207.                               BEGIN
  208.                           ok := false;
  209.                           case pptra^.instruct of
  210.                             calc_const : ok := true;
  211.                             calc_var   : ok := nach <> vartab^[pptra^.varindex].varid
  212.                           end;
  213.                           IF ok
  214.                             THEN
  215.                               BEGIN
  216.                                 newop(calc_mul);
  217.                                 newop(calc_mul);
  218.                                 newop(calc_pow);
  219.                                 newop(calc_sub);
  220.                                 newconst(1.0);
  221.                                 push(pptra);
  222.                                 push(pptrb);
  223.                                 push(pptra);
  224.                                 derive(pptrb)
  225.                               END
  226.                             ELSE
  227.                               BEGIN
  228.                                 newop(calc_mul);
  229.                                 newop(calc_pow);
  230.                                 push(pptra);
  231.                                 push(pptrb);
  232.                                 newop(calc_add);
  233.                                 newop(calc_dvd);
  234.                                 push(pptrb);
  235.                                 newop(calc_mul);
  236.                                 push(pptra);
  237.                                 derive(pptrb);
  238.                                 newop(calc_mul);
  239.                                 derive(pptra);
  240.                                 newop(calc_ln);
  241.                                 push(pptrb)
  242.                               END
  243.                               END
  244.                         END;
  245.             calc_abs  : BEGIN
  246.                           newop(calc_mul);
  247.                           newop(calc_sign);       (* calc_sig ??? *)
  248.                           push(pptra);
  249.                           derive(pptra)
  250.                         END;
  251.             calc_int, calc_sign  : newconst(0.0);
  252.             calc_sqr  : BEGIN
  253.                           newop(calc_mul);
  254.                           newop(calc_mul);
  255.                           push(pptra);
  256.                           derive(pptra);
  257.                           newconst(2.0);
  258.                         END;
  259.             calc_sqrt : BEGIN
  260.                           newop(calc_dvd);
  261.                           newop(calc_mul);
  262.                           newconst(2.0);
  263.                           newop(calc_sqrt);
  264.                           push(pptra);
  265.                           derive(pptra);
  266.                         END;
  267.             calc_exp  : BEGIN
  268.                           newop(calc_mul);
  269.                           newop(calc_exp);
  270.                           push(pptra);
  271.                           derive(pptra);
  272.                         END;
  273.             calc_ln  : BEGIN
  274.                          newop(calc_dvd);
  275.                          push(pptra);
  276.                          derive(pptra)
  277.                        END;
  278.             calc_lg : BEGIN
  279.                         newop(calc_dvd);
  280.                         newop(calc_mul);
  281.                         newop(calc_ln);
  282.                         newconst(10.0);
  283.                         push(pptra);
  284.                         derive(pptra)
  285.                       END;
  286.             calc_ld : BEGIN
  287.                         newop(calc_dvd);
  288.                         newop(calc_mul);
  289.                         newop(calc_ln);
  290.                         newconst(2.0);
  291.                         push(pptra);
  292.                         derive(pptra)
  293.                       END;
  294.             calc_sin : BEGIN
  295.                          newop(calc_mul);
  296.                          newop(calc_cos);
  297.                          push(pptra);
  298.                          derive(pptra);
  299.                        END;
  300.             calc_cos : BEGIN
  301.                          newop(calc_mul);
  302.                          newop(calc_neg);
  303.                          newop(calc_sin);
  304.                          push(pptra);
  305.                          derive(pptra);
  306.                        END;
  307.             calc_tan : BEGIN
  308.                          newop(calc_dvd);
  309.                          newop(calc_sqr);
  310.                          newop(calc_cos);
  311.                          push(pptra);
  312.                          derive(pptra);
  313.                        END;
  314.             calc_cot : BEGIN
  315.                          newop(calc_neg);
  316.                          newop(calc_dvd);
  317.                          newop(calc_sqr);
  318.                          newop(calc_sin);
  319.                          push(pptra);
  320.                          derive(pptra);
  321.                        END;
  322.             calc_arcsin : BEGIN
  323.                             newop(calc_dvd);
  324.                             newop(calc_sqrt);
  325.                             newop(calc_sub);
  326.                             newop(calc_sqr);
  327.                             push(pptra);
  328.                             newconst(1.0);
  329.                             derive(pptra);
  330.                           END;
  331.             calc_arccos : BEGIN
  332.                             newop(calc_neg);
  333.                             newop(calc_dvd);
  334.                             newop(calc_sqrt);
  335.                             newop(calc_sub);
  336.                             newop(calc_sqr);
  337.                             push(pptra);
  338.                             newconst(1.0);
  339.                             derive(pptra);
  340.                           END;
  341.             calc_arctan : BEGIN
  342.                             newop(calc_dvd);
  343.                             newop(calc_add);
  344.                             newop(calc_sqr);
  345.                             push(pptra);
  346.                             newconst(1.0);
  347.                             derive(pptra);
  348.                           END;
  349.             calc_arccot : BEGIN
  350.                             newop(calc_neg);
  351.                             newop(calc_dvd);
  352.                             newop(calc_add);
  353.                             newop(calc_sqr);
  354.                             push(pptra);
  355.                             newconst(1.0);
  356.                             derive(pptra);
  357.                           END;
  358.             calc_sinh  : BEGIN
  359.                            newop(calc_mul);
  360.                            newop(calc_cosh);
  361.                            push(pptra);
  362.                            derive(pptra)
  363.                          END;
  364.             calc_cosh  : BEGIN
  365.                            newop(calc_mul);
  366.                            newop(calc_sinh);
  367.                            push(pptra);
  368.                            derive(pptra)
  369.                          END;
  370.             calc_tanh  : BEGIN
  371.                            newop(calc_dvd);
  372.                            newop(calc_sqr);
  373.                            newop(calc_cosh);
  374.                            push(pptra);
  375.                            derive(pptra)
  376.                          END;
  377.             calc_coth  : BEGIN
  378.                            newop(calc_neg);
  379.                            newop(calc_dvd);
  380.                            newop(calc_sqr);
  381.                            newop(calc_sinh);
  382.                            push(pptra);
  383.                            derive(pptra)
  384.                          END;
  385.             calc_arcsinh : BEGIN
  386.                              newop(calc_dvd);
  387.                              newop(calc_sqrt);
  388.                              newop(calc_add);
  389.                              newconst(1.0);
  390.                              newop(calc_sqr);
  391.                              push(pptra);
  392.                              derive(pptra)
  393.                            END;
  394.             calc_arccosh : BEGIN
  395.                              newop(calc_dvd);
  396.                              newop(calc_sqrt);
  397.                              newop(calc_sub);
  398.                              newconst(1.0);
  399.                              newop(calc_sqr);
  400.                              push(pptra);
  401.                              derive(pptra)
  402.                            END;
  403.             calc_arctanh,calc_arccoth : BEGIN
  404.                                           newop(calc_dvd);
  405.                                           newop(calc_sub);
  406.                                           newop(calc_sqr);
  407.                                           push(pptra);
  408.                                           newconst(1.0);
  409.                                           derive(pptra)
  410.                                         END;
  411.             calc_deg     : BEGIN
  412.                              newop(calc_dvd);
  413.                              newconst(pi_durch_180);
  414.                              derive(pptra)
  415.                            END;
  416.             calc_rad     : BEGIN
  417.                              newop(calc_mul);
  418.                              newconst(pi_durch_180);
  419.                              derive(pptra)
  420.                            END;
  421.             ELSE
  422.               calcresult := FALSE
  423.           END;
  424.         END
  425.   END;
  426.  
  427. BEGIN
  428.   IF pptr <> nil
  429.     THEN
  430.       BEGIN
  431.         uppercase(nach);
  432.         invert(pptr);
  433.         pptr1 := pptr;
  434.         New(pptrstart);
  435.         pptrstart^.nextinst := nil;
  436.         pptr := pptr^.nextinst;
  437.         calcresult := TRUE;
  438.         derive(pptr);
  439.         IF calcresult
  440.           THEN
  441.             BEGIN
  442.               calcsimplify(pptrstart);
  443.               calcderivation := pptrstart
  444.             END
  445.           ELSE
  446.             BEGIN
  447.               killexpression(pptrstart);
  448.               calcderivation := nil;
  449.               CalcError(4,'Die Ableitung der Funktion kann'+
  450.                           ' nicht ermittelt werden');
  451.             END;
  452.         invert(pptr1);
  453.       END
  454.     ELSE
  455.       BEGIN
  456.         calcderivation := nil;
  457.         CalcResult := FALSE
  458.       END
  459. END;
  460.  
  461.