View Javadoc
1   /*
2   Copyright (c) 2017 James Ahlborn
3   
4   Licensed under the Apache License, Version 2.0 (the "License");
5   you may not use this file except in compliance with the License.
6   You may obtain a copy of the License at
7   
8       http://www.apache.org/licenses/LICENSE-2.0
9   
10  Unless required by applicable law or agreed to in writing, software
11  distributed under the License is distributed on an "AS IS" BASIS,
12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  See the License for the specific language governing permissions and
14  limitations under the License.
15  */
16  
17  package com.healthmarketscience.jackcess.impl.expr;
18  
19  import java.math.BigDecimal;
20  
21  import com.healthmarketscience.jackcess.expr.EvalContext;
22  import com.healthmarketscience.jackcess.expr.EvalException;
23  import com.healthmarketscience.jackcess.expr.Function;
24  import com.healthmarketscience.jackcess.expr.Value;
25  import static com.healthmarketscience.jackcess.impl.expr.DefaultFunctions.*;
26  import static com.healthmarketscience.jackcess.impl.expr.FunctionSupport.*;
27  
28  /**
29   *
30   * @author James Ahlborn
31   */
32  public class DefaultNumberFunctions
33  {
34  
35    private DefaultNumberFunctions() {}
36  
37    static void init() {
38      // dummy method to ensure this class is loaded
39    }
40  
41    public static final Function ABS = registerFunc(new Func1NullIsNull("Abs") {
42      @Override
43      protected Value../com/healthmarketscience/jackcess/expr/Value.html#Value">Value eval1(EvalContext ctx, Value param1) {
44        Value.Type mathType = param1.getType();
45  
46        switch(mathType) {
47        case DATE:
48        case TIME:
49        case DATE_TIME:
50          // dates/times get converted to date doubles for arithmetic
51          double result = Math.abs(param1.getAsDouble(ctx));
52          return ValueSupport.toDateValueIfPossible(mathType, result);
53        case LONG:
54          return ValueSupport.toValue(Math.abs(param1.getAsLongInt(ctx)));
55        case DOUBLE:
56          return ValueSupport.toValue(Math.abs(param1.getAsDouble(ctx)));
57        case STRING:
58        case BIG_DEC:
59          return ValueSupport.toValue(param1.getAsBigDecimal(ctx).abs(
60                                              NumberFormatter.DEC_MATH_CONTEXT));
61        default:
62          throw new EvalException("Unexpected type " + mathType);
63        }
64      }
65    });
66  
67    public static final Function ATAN = registerFunc(new Func1("Atan") {
68      @Override
69      protected Value../com/healthmarketscience/jackcess/expr/Value.html#Value">Value eval1(EvalContext ctx, Value param1) {
70        return ValueSupport.toValue(Math.atan(param1.getAsDouble(ctx)));
71      }
72    });
73  
74    public static final Function COS = registerFunc(new Func1("Cos") {
75      @Override
76      protected Value../com/healthmarketscience/jackcess/expr/Value.html#Value">Value eval1(EvalContext ctx, Value param1) {
77        return ValueSupport.toValue(Math.cos(param1.getAsDouble(ctx)));
78      }
79    });
80  
81    public static final Function EXP = registerFunc(new Func1("Exp") {
82      @Override
83      protected Value../com/healthmarketscience/jackcess/expr/Value.html#Value">Value eval1(EvalContext ctx, Value param1) {
84        return ValueSupport.toValue(Math.exp(param1.getAsDouble(ctx)));
85      }
86    });
87  
88    public static final Function FIX = registerFunc(new Func1NullIsNull("Fix") {
89      @Override
90      protected Value../com/healthmarketscience/jackcess/expr/Value.html#Value">Value eval1(EvalContext ctx, Value param1) {
91        if(param1.getType().isIntegral()) {
92          return param1;
93        }
94        return ValueSupport.toValue(param1.getAsDouble(ctx).intValue());
95      }
96    });
97  
98    public static final Function INT = registerFunc(new Func1NullIsNull("Int") {
99      @Override
100     protected Value../com/healthmarketscience/jackcess/expr/Value.html#Value">Value eval1(EvalContext ctx, Value param1) {
101       if(param1.getType().isIntegral()) {
102         return param1;
103       }
104       return ValueSupport.toValue((int)Math.floor(param1.getAsDouble(ctx)));
105     }
106   });
107 
108   public static final Function LOG = registerFunc(new Func1("Log") {
109     @Override
110     protected Value../com/healthmarketscience/jackcess/expr/Value.html#Value">Value eval1(EvalContext ctx, Value param1) {
111       return ValueSupport.toValue(Math.log(param1.getAsDouble(ctx)));
112     }
113   });
114 
115   public static final Function RND = registerFunc(new FuncVar("Rnd", 0, 1) {
116     @Override
117     public boolean isPure() {
118       return false;
119     }
120     @Override
121     protected Value/com/healthmarketscience/jackcess/expr/Value.html#Value">Value evalVar(EvalContext ctx, Value[] params) {
122       Integer seed = ((params.length > 0) ? params[0].getAsLongInt(ctx) : null);
123       return ValueSupport.toValue(ctx.getRandom(seed));
124     }
125   });
126 
127   public static final Function ROUND = registerFunc(new FuncVar("Round", 1, 2) {
128     @Override
129     protected Value/com/healthmarketscience/jackcess/expr/Value.html#Value">Value evalVar(EvalContext ctx, Value[] params) {
130       Value param1 = params[0];
131       if(param1.isNull()) {
132         return ValueSupport.NULL_VAL;
133       }
134       if(param1.getType().isIntegral()) {
135         return param1;
136       }
137       int scale = 0;
138       if(params.length > 1) {
139         scale = params[1].getAsLongInt(ctx);
140       }
141       BigDecimal bd = param1.getAsBigDecimal(ctx)
142         .setScale(scale, NumberFormatter.ROUND_MODE);
143       return ValueSupport.toValue(bd);
144     }
145   });
146 
147   public static final Function SGN = registerFunc(new Func1NullIsNull("Sgn") {
148     @Override
149     protected Value../com/healthmarketscience/jackcess/expr/Value.html#Value">Value eval1(EvalContext ctx, Value param1) {
150       int val = 0;
151       if(param1.getType().isIntegral()) {
152         val = param1.getAsLongInt(ctx);
153       } else {
154         val = param1.getAsBigDecimal(ctx).signum();
155       }
156       return ((val > 0) ? ValueSupport.ONE_VAL :
157               ((val < 0) ? ValueSupport.NEG_ONE_VAL :
158                ValueSupport.ZERO_VAL));
159     }
160   });
161 
162   public static final Function SQR = registerFunc(new Func1("Sqr") {
163     @Override
164     protected Value../com/healthmarketscience/jackcess/expr/Value.html#Value">Value eval1(EvalContext ctx, Value param1) {
165       double dv = param1.getAsDouble(ctx);
166       if(dv < 0.0d) {
167         throw new EvalException("Invalid value '" + dv + "'");
168       }
169       return ValueSupport.toValue(Math.sqrt(dv));
170     }
171   });
172 
173   public static final Function SIN = registerFunc(new Func1("Sin") {
174     @Override
175     protected Value../com/healthmarketscience/jackcess/expr/Value.html#Value">Value eval1(EvalContext ctx, Value param1) {
176       return ValueSupport.toValue(Math.sin(param1.getAsDouble(ctx)));
177     }
178   });
179 
180   public static final Function TAN = registerFunc(new Func1("Tan") {
181     @Override
182     protected Value../com/healthmarketscience/jackcess/expr/Value.html#Value">Value eval1(EvalContext ctx, Value param1) {
183       return ValueSupport.toValue(Math.tan(param1.getAsDouble(ctx)));
184     }
185   });
186 }