LCOV - code coverage report
Current view: top level - lib - fractexpr.dart (source / functions) Hit Total Coverage
Test: lcov.info Lines: 82 123 66.7 %
Date: 2024-05-20 13:51:31 Functions: 0 0 -

          Line data    Source code
       1             : import 'dart:math';
       2             : import 'package:clc/fract.dart';
       3             : import 'package:clc/rpn.dart';
       4             : 
       5             : class FractRpn extends RPN<Fraction> {
       6           6 :   static RegExp numberExp = RegExp(r"[0-9]+(\.[0-9]+)?(e[\+\-])?[0-9]*");
       7           6 :   static RegExp funcExp = RegExp(r"[a-zA-Z][a-zA-Z0-9]*");
       8           0 :   static Map<String, Fraction> constants = {
       9           0 :     "pi": Fraction.fromDouble(pi),
      10           0 :     "e": Fraction.fromDouble(e),
      11             :   };
      12             : 
      13           2 :   @override
      14             :   void exec1(String v) {
      15             :     Set<String> ary1 = {
      16           2 :       "S-",
      17           2 :       "S+",
      18           2 :       "S!",
      19           2 :       "log",
      20           2 :       "log2",
      21           2 :       "log10",
      22           2 :       "sqrt",
      23           2 :       "exp"
      24             :     };
      25          18 :     Set<String> ary2 = {"+", "-", "*", "×", "/", "÷", "<<", ">>", "%"};
      26           4 :     if (numberExp.matchAsPrefix(v) != null) {
      27           4 :       push(Fraction.fromString(v));
      28           2 :     } else if (ary1.contains(v)) {
      29           1 :       var a = pop();
      30             :       if (a == null) {
      31           0 :         log.e("pop null(1)");
      32             :         return;
      33             :       }
      34           1 :       if (v == "S-") {
      35           2 :         push(-a);
      36           1 :       } else if (v == "S+") {
      37           1 :         push(a);
      38           1 :       } else if (v == "S!") {
      39           1 :         var res = BigInt.one;
      40           5 :         for (var i = a.toBigInt(); i > BigInt.one; i -= BigInt.one) {
      41           1 :           res *= i;
      42             :         }
      43           2 :         push(Fraction.fromBigInt(res));
      44           0 :       } else if (v == "log") {
      45           0 :         push(a.log());
      46           0 :       } else if (v == "log2") {
      47           0 :         push(a.log2());
      48           0 :       } else if (v == "log10") {
      49           0 :         push(a.log10());
      50           0 :       } else if (v == "exp") {
      51           0 :         push(a.exp());
      52           0 :       } else if (v == "sqrt") {
      53           0 :         push(a.sqrt());
      54             :       } else {
      55           0 :         throw Exception("no such unary op: $v");
      56             :       }
      57           2 :     } else if (ary2.contains(v)) {
      58           2 :       var a = pop();
      59             :       if (a == null) {
      60           0 :         log.e("pop null(a)");
      61             :         return;
      62             :       }
      63           2 :       var b = pop();
      64             :       if (b == null) {
      65           2 :         log.e("pop null(b)");
      66             :         return;
      67             :       }
      68           2 :       if (v == "+") {
      69           4 :         push(b + a);
      70           2 :       } else if (v == "-") {
      71           2 :         push(b - a);
      72           4 :       } else if (v == "*" || v == "×") {
      73           2 :         push(b * a);
      74           4 :       } else if (v == "/" || v == "÷") {
      75           4 :         push(b / a);
      76           1 :       } else if (v == "<<") {
      77           4 :         push(b << a.toBigInt().toInt());
      78           1 :       } else if (v == ">>") {
      79           4 :         push(b >> a.toBigInt().toInt());
      80           0 :       } else if (v == "%") {
      81           0 :         push(b % a);
      82             :       } else {
      83           0 :         throw Exception("no such binary op: $v");
      84             :       }
      85             :     }
      86             :   }
      87             : 
      88           2 :   Fraction? eval(String s) {
      89           6 :     fromInfixString(s, numberExp, funcExp);
      90           2 :     return evaluate();
      91             :   }
      92             : 
      93             :   List<String> exprStack = [];
      94             : 
      95           2 :   void toExpr1(String v) {
      96             :     Set<String> ary1 = {
      97           2 :       "S-",
      98           2 :       "S+",
      99           2 :       "S!",
     100           2 :       "log",
     101           2 :       "log2",
     102           2 :       "log10",
     103           2 :       "sqrt",
     104           2 :       "exp"
     105             :     };
     106          18 :     Set<String> ary2 = {"+", "-", "*", "×", "/", "÷", "<<", ">>", "%"};
     107           4 :     if (numberExp.matchAsPrefix(v) != null) {
     108           8 :       exprStack.add(Fraction.fromString(v).toExpr());
     109           2 :     } else if (ary1.contains(v)) {
     110           2 :       var a = exprStack.removeLast();
     111           1 :       if (a.contains(" ")) {
     112           1 :         a = "($a)";
     113             :       }
     114           1 :       if (v == "S-") {
     115           0 :         exprStack.add("-$a");
     116           1 :       } else if (v == "S+") {
     117           0 :         exprStack.add("+$a");
     118           1 :       } else if (v == "S!") {
     119           3 :         exprStack.add("$a!");
     120           1 :       } else if (v == "log") {
     121           3 :         exprStack.add("\\log $a");
     122           0 :       } else if (v == "log2") {
     123           0 :         exprStack.add("\\log_2 $a");
     124           0 :       } else if (v == "log10") {
     125           0 :         exprStack.add("\\log_10 $a");
     126           0 :       } else if (v == "exp") {
     127           0 :         exprStack.add("e^{$a}");
     128           0 :       } else if (v == "sqrt") {
     129           0 :         exprStack.add("\\sqrt{$a}");
     130             :       } else {
     131           0 :         throw Exception("no such unary op: $v");
     132             :       }
     133           2 :     } else if (ary2.contains(v)) {
     134           4 :       var a = exprStack.removeLast();
     135           4 :       var b = exprStack.removeLast();
     136           2 :       if (a.contains(" ")) {
     137           0 :         a = "($a)";
     138             :       }
     139           2 :       if (b.contains(" ")) {
     140           0 :         b = "($b)";
     141             :       }
     142           2 :       if (v == "+") {
     143           6 :         exprStack.add("$b + $a");
     144           2 :       } else if (v == "-") {
     145           0 :         exprStack.add("$b - $a");
     146           4 :       } else if (v == "*" || v == "×") {
     147           0 :         exprStack.add("$b \\times $a");
     148           3 :       } else if (v == "/" || v == "÷") {
     149           6 :         exprStack.add("\\frac{$b}{$a}");
     150           0 :       } else if (v == "<<") {
     151           0 :         exprStack.add("$b << $a");
     152           0 :       } else if (v == ">>") {
     153           0 :         exprStack.add("$b >> $a");
     154           0 :       } else if (v == "%") {
     155           0 :         exprStack.add("$b \\bmod $a");
     156             :       } else {
     157           0 :         throw Exception("no such binary op: $v");
     158             :       }
     159             :     }
     160             :   }
     161             : 
     162           2 :   String toExpr() {
     163           4 :     exprStack = [];
     164           4 :     for (var x in expression) {
     165           2 :       toExpr1(x);
     166             :     }
     167           4 :     return exprStack.last;
     168             :   }
     169             : }

Generated by: LCOV version 1.14