1 | /* |
2 | * Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0, |
3 | * and the EPL 1.0 (http://h2database.com/html/license.html). |
4 | * Initial Developer: H2 Group |
5 | */ |
6 | package org.h2.value; |
7 | |
8 | import java.sql.PreparedStatement; |
9 | import java.sql.SQLException; |
10 | |
11 | import org.h2.api.ErrorCode; |
12 | import org.h2.message.DbException; |
13 | |
14 | /** |
15 | * Implementation of the DOUBLE data type. |
16 | */ |
17 | public class ValueDouble extends Value { |
18 | |
19 | /** |
20 | * The precision in digits. |
21 | */ |
22 | public static final int PRECISION = 17; |
23 | |
24 | /** |
25 | * The maximum display size of a double. |
26 | * Example: -3.3333333333333334E-100 |
27 | */ |
28 | public static final int DISPLAY_SIZE = 24; |
29 | |
30 | /** |
31 | * Double.doubleToLongBits(0.0) |
32 | */ |
33 | public static final long ZERO_BITS = Double.doubleToLongBits(0.0); |
34 | |
35 | private static final ValueDouble ZERO = new ValueDouble(0.0); |
36 | private static final ValueDouble ONE = new ValueDouble(1.0); |
37 | private static final ValueDouble NAN = new ValueDouble(Double.NaN); |
38 | |
39 | private final double value; |
40 | |
41 | private ValueDouble(double value) { |
42 | this.value = value; |
43 | } |
44 | |
45 | @Override |
46 | public Value add(Value v) { |
47 | ValueDouble v2 = (ValueDouble) v; |
48 | return ValueDouble.get(value + v2.value); |
49 | } |
50 | |
51 | @Override |
52 | public Value subtract(Value v) { |
53 | ValueDouble v2 = (ValueDouble) v; |
54 | return ValueDouble.get(value - v2.value); |
55 | } |
56 | |
57 | @Override |
58 | public Value negate() { |
59 | return ValueDouble.get(-value); |
60 | } |
61 | |
62 | @Override |
63 | public Value multiply(Value v) { |
64 | ValueDouble v2 = (ValueDouble) v; |
65 | return ValueDouble.get(value * v2.value); |
66 | } |
67 | |
68 | @Override |
69 | public Value divide(Value v) { |
70 | ValueDouble v2 = (ValueDouble) v; |
71 | if (v2.value == 0.0) { |
72 | throw DbException.get(ErrorCode.DIVISION_BY_ZERO_1, getSQL()); |
73 | } |
74 | return ValueDouble.get(value / v2.value); |
75 | } |
76 | |
77 | @Override |
78 | public ValueDouble modulus(Value v) { |
79 | ValueDouble other = (ValueDouble) v; |
80 | if (other.value == 0) { |
81 | throw DbException.get(ErrorCode.DIVISION_BY_ZERO_1, getSQL()); |
82 | } |
83 | return ValueDouble.get(value % other.value); |
84 | } |
85 | |
86 | @Override |
87 | public String getSQL() { |
88 | if (value == Double.POSITIVE_INFINITY) { |
89 | return "POWER(0, -1)"; |
90 | } else if (value == Double.NEGATIVE_INFINITY) { |
91 | return "(-POWER(0, -1))"; |
92 | } else if (Double.isNaN(value)) { |
93 | return "SQRT(-1)"; |
94 | } |
95 | String s = getString(); |
96 | if (s.equals("-0.0")) { |
97 | return "-CAST(0 AS DOUBLE)"; |
98 | } |
99 | return s; |
100 | } |
101 | |
102 | @Override |
103 | public int getType() { |
104 | return Value.DOUBLE; |
105 | } |
106 | |
107 | @Override |
108 | protected int compareSecure(Value o, CompareMode mode) { |
109 | ValueDouble v = (ValueDouble) o; |
110 | return Double.compare(value, v.value); |
111 | } |
112 | |
113 | @Override |
114 | public int getSignum() { |
115 | return value == 0 ? 0 : (value < 0 ? -1 : 1); |
116 | } |
117 | |
118 | @Override |
119 | public double getDouble() { |
120 | return value; |
121 | } |
122 | |
123 | @Override |
124 | public String getString() { |
125 | return String.valueOf(value); |
126 | } |
127 | |
128 | @Override |
129 | public long getPrecision() { |
130 | return PRECISION; |
131 | } |
132 | |
133 | @Override |
134 | public int getScale() { |
135 | return 0; |
136 | } |
137 | |
138 | @Override |
139 | public int hashCode() { |
140 | long hash = Double.doubleToLongBits(value); |
141 | return (int) (hash ^ (hash >> 32)); |
142 | } |
143 | |
144 | @Override |
145 | public Object getObject() { |
146 | return Double.valueOf(value); |
147 | } |
148 | |
149 | @Override |
150 | public void set(PreparedStatement prep, int parameterIndex) |
151 | throws SQLException { |
152 | prep.setDouble(parameterIndex, value); |
153 | } |
154 | |
155 | /** |
156 | * Get or create double value for the given double. |
157 | * |
158 | * @param d the double |
159 | * @return the value |
160 | */ |
161 | public static ValueDouble get(double d) { |
162 | if (d == 1.0) { |
163 | return ONE; |
164 | } else if (d == 0.0) { |
165 | // unfortunately, -0.0 == 0.0, but we don't want to return |
166 | // 0.0 in this case |
167 | if (Double.doubleToLongBits(d) == ZERO_BITS) { |
168 | return ZERO; |
169 | } |
170 | } else if (Double.isNaN(d)) { |
171 | return NAN; |
172 | } |
173 | return (ValueDouble) Value.cache(new ValueDouble(d)); |
174 | } |
175 | |
176 | @Override |
177 | public int getDisplaySize() { |
178 | return DISPLAY_SIZE; |
179 | } |
180 | |
181 | @Override |
182 | public boolean equals(Object other) { |
183 | if (!(other instanceof ValueDouble)) { |
184 | return false; |
185 | } |
186 | return compareSecure((ValueDouble) other, null) == 0; |
187 | } |
188 | |
189 | } |