1 package calculator.functions;
2
3 import java.math.BigDecimal;
4 import java.math.MathContext;
5 import java.util.ArrayList;
6
7 import calculator.Expression;
8 import calculator.IllegalConstruction;
9 import calculator.atoms.*;
10 import calculator.operations.Divides;
11 import ch.obermuhlner.math.big.BigDecimalMath;
12
13
14
15
16 public class Log extends BinaryFunction {
17
18 public Log(Expression base, Expression number) throws IllegalConstruction {
19 super(base, number);
20 symbol = "log";
21 }
22
23 @Override
24 public Real op(Real base, Real n) {
25
26 if (base.isNan() || n.isNan()) {
27 return Real.nan();
28 }
29
30 if (n.isMinusInf() || n.getValue().doubleValue() < 0
31 || base.isMinusInf() || base.getValue().doubleValue() < 0) {
32 throw new IllegalArgumentException("Logarithm of negative number");
33 }
34
35 int precision = 0;
36 if (base.getValue().precision() > n.getValue().precision())
37 precision = base.getValue().precision();
38 else
39 precision = n.getValue().precision();
40
41 Real logBase, logN = null;
42 if (base.isPlusInf()) {
43 logBase = Real.plusInf();
44 } else {
45 logBase = new Real(BigDecimalMath.log(base.getValue(), new MathContext(precision)));
46 }
47
48 if (n.isPlusInf()) {
49 logN = Real.plusInf();
50 } else {
51 logN = new Real(BigDecimalMath.log(n.getValue(), new MathContext(precision)));
52 }
53
54
55
56 Divides d;
57 try {
58 d = new Divides(new ArrayList<>());
59
60 return d.op(logN, logBase);
61 } catch (IllegalConstruction e) {
62
63 }
64 return Real.nan();
65
66 }
67
68 @Override
69 public Complex op(Complex base, Complex n) {
70
71
72
73 org.apache.commons.numbers.complex.Complex logBase = base.getValue().log();
74 org.apache.commons.numbers.complex.Complex logN = n.getValue().log();
75
76 return new Complex(logN.divide(logBase));
77
78 }
79
80 @Override
81 public Real op(IntegerAtom base, IntegerAtom n) {
82
83
84 if (base.getValue() <= 0 || n.getValue() <= 0) {
85 throw new IllegalArgumentException("Logarithm of negative number");
86 }
87
88 BigDecimal logBase = BigDecimalMath.log(new BigDecimal(base.getValue()), Real.context);
89 BigDecimal logN = BigDecimalMath.log(new BigDecimal(n.getValue()), Real.context);
90
91 return new Real(logN.divide(logBase, Real.context));
92
93 }
94
95 @Override
96 public Real op(Rationnal base, Rationnal n) {
97
98 if (base.getValue().doubleValue() <= 0 || n.getValue().doubleValue() <= 0) {
99 throw new IllegalArgumentException("Logarithm of negative number");
100 }
101
102
103 BigDecimal logBase = BigDecimalMath.log(new BigDecimal(base.getValue().doubleValue()), Real.context);
104 BigDecimal logN = BigDecimalMath.log(new BigDecimal(n.getValue().doubleValue()), Real.context);
105
106 return new Real(logN.divide(logBase, Real.context));
107 }
108 }