home *** CD-ROM | disk | FTP | other *** search
/ Turbo Toolbox / Turbo_Toolbox.iso / spezial / 04 / quellen / calcderi.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1979-12-31  |  16.6 KB  |  463 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. {$a-}
  89.  
  90.   PROCEDURE derive(pptr : calc_prog);
  91.  
  92.   VAR pptra,pptrb : calc_prog;
  93.  
  94.   BEGIN
  95.     IF calcresult
  96.       THEN
  97.         BEGIN
  98.           pptra := pptr^.nextinst;
  99.           IF (pptra <> nil)
  100.             THEN
  101.               BEGIN
  102.                 pptrb := endof(pptra);
  103.                 pptrb := pptrb^.nextinst
  104.               END;
  105.           CASE pptr^.instruct OF
  106.             calc_neg   : BEGIN
  107.                            newop(calc_neg);
  108.                            derive(pptra)
  109.                          END;
  110.             calc_const,calc_div..calc_kgv,calc_fak : BEGIN
  111.                                                       newconst(0.0);
  112.                                                      END;
  113.             calc_var  : BEGIN
  114.                           IF nach = vartab^[pptr^.varindex].varid
  115.                             THEN
  116.                               newconst(1.0)
  117.                             ELSE
  118.                               newconst(0.0);
  119.                         END;
  120.             calc_add  : BEGIN
  121.                           IF calc_const IN[pptra^.instruct,pptrb^.instruct]
  122.                             THEN
  123.                               IF pptra^.instruct = calc_const
  124.                                 THEN
  125.                                   derive(pptrb)
  126.                                 ELSE
  127.                                   derive(pptra)
  128.                             ELSE
  129.                               BEGIN
  130.                                 newop(calc_add);
  131.                                 derive(pptra);
  132.                                 derive(pptrb)
  133.                               END
  134.                         END;
  135.             calc_sub  : BEGIN
  136.                           IF calc_const IN [pptra^.instruct,pptrb^.instruct
  137.                               ]
  138.                             THEN
  139.                               IF pptra^.instruct = calc_const
  140.                                 THEN
  141.                                   derive(pptrb)
  142.                                 ELSE
  143.                                   BEGIN
  144.                                     newop(calc_neg);
  145.                                     derive(pptra)
  146.                                   END
  147.                             ELSE
  148.                               BEGIN
  149.                                 newop(calc_sub);
  150.                                 derive(pptra);
  151.                                 derive(pptrb)
  152.                               END
  153.                         END;
  154.             calc_mul : BEGIN
  155.                          IF calc_const IN [pptra^.instruct,pptrb^.instruct]
  156.                            THEN
  157.                              IF pptra^.instruct = calc_const
  158.                                THEN
  159.                                  BEGIN
  160.                                    newop(calc_mul);
  161.                                    push(pptra);
  162.                                    derive(pptrb)
  163.                                  END
  164.                                ELSE
  165.                                  BEGIN
  166.                                    newop(calc_mul);
  167.                                    push(pptrb);
  168.                                    derive(pptra)
  169.                                  END
  170.                            ELSE
  171.                              BEGIN
  172.                                newop(calc_add);
  173.                                newop(calc_mul);
  174.                                derive(pptra);
  175.                                push(pptrb);
  176.                                newop(calc_mul);
  177.                                push(pptra);
  178.                                derive(pptrb);
  179.                              END
  180.                        END;
  181.             calc_dvd : BEGIN
  182.                          IF pptra^.instruct = calc_const
  183.                            THEN
  184.                              BEGIN
  185.                                newop(calc_dvd);
  186.                                push(pptra);
  187.                                derive(pptrb)
  188.                              END
  189.                            ELSE
  190.                              BEGIN
  191.                                newop(calc_dvd);
  192.                                newop(calc_sqr);
  193.                                push(pptra);
  194.                                newop(calc_sub);
  195.                                newop(calc_mul);
  196.                                derive(pptra);
  197.                                push(pptrb);
  198.                                newop(calc_mul);
  199.                                push(pptra);
  200.                                derive(pptrb)
  201.                              END
  202.                        END;
  203.             calc_pow  : BEGIN
  204.                           if (pptrb^.instruct = calc_const)
  205.                            and (pptrb^.operand < 0.0)
  206.                                   THEN calcresult := false
  207.                               ELSE
  208.                               BEGIN
  209.                           ok := false;
  210.                           case pptra^.instruct of
  211.                             calc_const : ok := true;
  212.                             calc_var   : ok := nach <> vartab^[pptra^.varindex].varid
  213.                           end;
  214.                           IF ok
  215.                             THEN
  216.                               BEGIN
  217.                                 newop(calc_mul);
  218.                                 newop(calc_mul);
  219.                                 newop(calc_pow);
  220.                                 newop(calc_sub);
  221.                                 newconst(1.0);
  222.                                 push(pptra);
  223.                                 push(pptrb);
  224.                                 push(pptra);
  225.                                 derive(pptrb)
  226.                               END
  227.                             ELSE
  228.                               BEGIN
  229.                                 newop(calc_mul);
  230.                                 newop(calc_pow);
  231.                                 push(pptra);
  232.                                 push(pptrb);
  233.                                 newop(calc_add);
  234.                                 newop(calc_dvd);
  235.                                 push(pptrb);
  236.                                 newop(calc_mul);
  237.                                 push(pptra);
  238.                                 derive(pptrb);
  239.                                 newop(calc_mul);
  240.                                 derive(pptra);
  241.                                 newop(calc_ln);
  242.                                 push(pptrb)
  243.                               END
  244.                               END
  245.                         END;
  246.             calc_abs  : BEGIN
  247.                           newop(calc_mul);
  248.                           newop(calc_sig);
  249.                           push(pptra);
  250.                           derive(pptra)
  251.                         END;
  252.             calc_int,calc_sig  : newconst(0.0);
  253.             calc_sqr  : BEGIN
  254.                           newop(calc_mul);
  255.                           newop(calc_mul);
  256.                           push(pptra);
  257.                           derive(pptra);
  258.                           newconst(2.0);
  259.                         END;
  260.             calc_sqrt : BEGIN
  261.                           newop(calc_dvd);
  262.                           newop(calc_mul);
  263.                           newconst(2.0);
  264.                           newop(calc_sqrt);
  265.                           push(pptra);
  266.                           derive(pptra);
  267.                         END;
  268.             calc_exp  : BEGIN
  269.                           newop(calc_mul);
  270.                           newop(calc_exp);
  271.                           push(pptra);
  272.                           derive(pptra);
  273.                         END;
  274.             calc_ln  : BEGIN
  275.                          newop(calc_dvd);
  276.                          push(pptra);
  277.                          derive(pptra)
  278.                        END;
  279.             calc_lg : BEGIN
  280.                         newop(calc_dvd);
  281.                         newop(calc_mul);
  282.                         newop(calc_ln);
  283.                         newconst(10.0);
  284.                         push(pptra);
  285.                         derive(pptra)
  286.                       END;
  287.             calc_ld : BEGIN
  288.                         newop(calc_dvd);
  289.                         newop(calc_mul);
  290.                         newop(calc_ln);
  291.                         newconst(2.0);
  292.                         push(pptra);
  293.                         derive(pptra)
  294.                       END;
  295.             calc_sin : BEGIN
  296.                          newop(calc_mul);
  297.                          newop(calc_cos);
  298.                          push(pptra);
  299.                          derive(pptra);
  300.                        END;
  301.             calc_cos : BEGIN
  302.                          newop(calc_mul);
  303.                          newop(calc_neg);
  304.                          newop(calc_sin);
  305.                          push(pptra);
  306.                          derive(pptra);
  307.                        END;
  308.             calc_tan : BEGIN
  309.                          newop(calc_dvd);
  310.                          newop(calc_sqr);
  311.                          newop(calc_cos);
  312.                          push(pptra);
  313.                          derive(pptra);
  314.                        END;
  315.             calc_cot : BEGIN
  316.                          newop(calc_neg);
  317.                          newop(calc_dvd);
  318.                          newop(calc_sqr);
  319.                          newop(calc_sin);
  320.                          push(pptra);
  321.                          derive(pptra);
  322.                        END;
  323.             calc_arcsin : BEGIN
  324.                             newop(calc_dvd);
  325.                             newop(calc_sqrt);
  326.                             newop(calc_sub);
  327.                             newop(calc_sqr);
  328.                             push(pptra);
  329.                             newconst(1.0);
  330.                             derive(pptra);
  331.                           END;
  332.             calc_arccos : BEGIN
  333.                             newop(calc_neg);
  334.                             newop(calc_dvd);
  335.                             newop(calc_sqrt);
  336.                             newop(calc_sub);
  337.                             newop(calc_sqr);
  338.                             push(pptra);
  339.                             newconst(1.0);
  340.                             derive(pptra);
  341.                           END;
  342.             calc_arctan : BEGIN
  343.                             newop(calc_dvd);
  344.                             newop(calc_add);
  345.                             newop(calc_sqr);
  346.                             push(pptra);
  347.                             newconst(1.0);
  348.                             derive(pptra);
  349.                           END;
  350.             calc_arccot : BEGIN
  351.                             newop(calc_neg);
  352.                             newop(calc_dvd);
  353.                             newop(calc_add);
  354.                             newop(calc_sqr);
  355.                             push(pptra);
  356.                             newconst(1.0);
  357.                             derive(pptra);
  358.                           END;
  359.             calc_sinh  : BEGIN
  360.                            newop(calc_mul);
  361.                            newop(calc_cosh);
  362.                            push(pptra);
  363.                            derive(pptra)
  364.                          END;
  365.             calc_cosh  : BEGIN
  366.                            newop(calc_mul);
  367.                            newop(calc_sinh);
  368.                            push(pptra);
  369.                            derive(pptra)
  370.                          END;
  371.             calc_tanh  : BEGIN
  372.                            newop(calc_dvd);
  373.                            newop(calc_sqr);
  374.                            newop(calc_cosh);
  375.                            push(pptra);
  376.                            derive(pptra)
  377.                          END;
  378.             calc_coth  : BEGIN
  379.                            newop(calc_neg);
  380.                            newop(calc_dvd);
  381.                            newop(calc_sqr);
  382.                            newop(calc_sinh);
  383.                            push(pptra);
  384.                            derive(pptra)
  385.                          END;
  386.             calc_arcsinh : BEGIN
  387.                              newop(calc_dvd);
  388.                              newop(calc_sqrt);
  389.                              newop(calc_add);
  390.                              newconst(1.0);
  391.                              newop(calc_sqr);
  392.                              push(pptra);
  393.                              derive(pptra)
  394.                            END;
  395.             calc_arccosh : BEGIN
  396.                              newop(calc_dvd);
  397.                              newop(calc_sqrt);
  398.                              newop(calc_sub);
  399.                              newconst(1.0);
  400.                              newop(calc_sqr);
  401.                              push(pptra);
  402.                              derive(pptra)
  403.                            END;
  404.             calc_arctanh,calc_arccoth : BEGIN
  405.                                           newop(calc_dvd);
  406.                                           newop(calc_sub);
  407.                                           newop(calc_sqr);
  408.                                           push(pptra);
  409.                                           newconst(1.0);
  410.                                           derive(pptra)
  411.                                         END;
  412.             calc_deg     : BEGIN
  413.                              newop(calc_dvd);
  414.                              newconst(pi_durch_180);
  415.                              derive(pptra)
  416.                            END;
  417.             calc_rad     : BEGIN
  418.                              newop(calc_mul);
  419.                              newconst(pi_durch_180);
  420.                              derive(pptra)
  421.                            END;
  422.             ELSE
  423.               calcresult := FALSE
  424.           END;
  425.         END
  426.   END;
  427. {$a+}
  428.  
  429. BEGIN
  430.   IF pptr <> nil
  431.     THEN
  432.       BEGIN
  433.         uppercase(nach);
  434.         invert(pptr);
  435.         pptr1 := pptr;
  436.         New(pptrstart);
  437.         pptrstart^.nextinst := nil;
  438.         pptr := pptr^.nextinst;
  439.         calcresult := TRUE;
  440.         derive(pptr);
  441.         IF calcresult
  442.           THEN
  443.             BEGIN
  444.               calcsimplify(pptrstart);
  445.               calcderivation := pptrstart
  446.             END
  447.           ELSE
  448.             BEGIN
  449.               killexpression(pptrstart);
  450.               calcderivation := nil;
  451.               CalcError(4,'Die Ableitung der Funktion kann'+
  452.                           ' nicht ermittelt werden');
  453.             END;
  454.         invert(pptr1);
  455.       END
  456.     ELSE
  457.       BEGIN
  458.         calcderivation := nil;
  459.         CalcResult := FALSE
  460.       END
  461. END;
  462.  
  463.