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 REAL data type. |
16 | */ |
17 | public class ValueFloat extends Value { |
18 | |
19 | /** |
20 | * Float.floatToIntBits(0.0F). |
21 | */ |
22 | public static final int ZERO_BITS = Float.floatToIntBits(0.0F); |
23 | |
24 | /** |
25 | * The precision in digits. |
26 | */ |
27 | static final int PRECISION = 7; |
28 | |
29 | /** |
30 | * The maximum display size of a float. |
31 | * Example: -1.12345676E-20 |
32 | */ |
33 | static final int DISPLAY_SIZE = 15; |
34 | |
35 | private static final ValueFloat ZERO = new ValueFloat(0.0F); |
36 | private static final ValueFloat ONE = new ValueFloat(1.0F); |
37 | |
38 | private final float value; |
39 | |
40 | private ValueFloat(float value) { |
41 | this.value = value; |
42 | } |
43 | |
44 | @Override |
45 | public Value add(Value v) { |
46 | ValueFloat v2 = (ValueFloat) v; |
47 | return ValueFloat.get(value + v2.value); |
48 | } |
49 | |
50 | @Override |
51 | public Value subtract(Value v) { |
52 | ValueFloat v2 = (ValueFloat) v; |
53 | return ValueFloat.get(value - v2.value); |
54 | } |
55 | |
56 | @Override |
57 | public Value negate() { |
58 | return ValueFloat.get(-value); |
59 | } |
60 | |
61 | @Override |
62 | public Value multiply(Value v) { |
63 | ValueFloat v2 = (ValueFloat) v; |
64 | return ValueFloat.get(value * v2.value); |
65 | } |
66 | |
67 | @Override |
68 | public Value divide(Value v) { |
69 | ValueFloat v2 = (ValueFloat) v; |
70 | if (v2.value == 0.0) { |
71 | throw DbException.get(ErrorCode.DIVISION_BY_ZERO_1, getSQL()); |
72 | } |
73 | return ValueFloat.get(value / v2.value); |
74 | } |
75 | |
76 | @Override |
77 | public Value modulus(Value v) { |
78 | ValueFloat other = (ValueFloat) v; |
79 | if (other.value == 0) { |
80 | throw DbException.get(ErrorCode.DIVISION_BY_ZERO_1, getSQL()); |
81 | } |
82 | return ValueFloat.get(value % other.value); |
83 | } |
84 | |
85 | @Override |
86 | public String getSQL() { |
87 | if (value == Float.POSITIVE_INFINITY) { |
88 | return "POWER(0, -1)"; |
89 | } else if (value == Float.NEGATIVE_INFINITY) { |
90 | return "(-POWER(0, -1))"; |
91 | } else if (Double.isNaN(value)) { |
92 | // NaN |
93 | return "SQRT(-1)"; |
94 | } |
95 | String s = getString(); |
96 | if (s.equals("-0.0")) { |
97 | return "-CAST(0 AS REAL)"; |
98 | } |
99 | return s; |
100 | } |
101 | |
102 | @Override |
103 | public int getType() { |
104 | return Value.FLOAT; |
105 | } |
106 | |
107 | @Override |
108 | protected int compareSecure(Value o, CompareMode mode) { |
109 | ValueFloat v = (ValueFloat) o; |
110 | return Float.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 float getFloat() { |
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 = Float.floatToIntBits(value); |
141 | return (int) (hash ^ (hash >> 32)); |
142 | } |
143 | |
144 | @Override |
145 | public Object getObject() { |
146 | return Float.valueOf(value); |
147 | } |
148 | |
149 | @Override |
150 | public void set(PreparedStatement prep, int parameterIndex) |
151 | throws SQLException { |
152 | prep.setFloat(parameterIndex, value); |
153 | } |
154 | |
155 | /** |
156 | * Get or create float value for the given float. |
157 | * |
158 | * @param d the float |
159 | * @return the value |
160 | */ |
161 | public static ValueFloat get(float d) { |
162 | if (d == 1.0F) { |
163 | return ONE; |
164 | } else if (d == 0.0F) { |
165 | // unfortunately, -0.0 == 0.0, but we don't want to return |
166 | // 0.0 in this case |
167 | if (Float.floatToIntBits(d) == ZERO_BITS) { |
168 | return ZERO; |
169 | } |
170 | } |
171 | return (ValueFloat) Value.cache(new ValueFloat(d)); |
172 | } |
173 | |
174 | @Override |
175 | public int getDisplaySize() { |
176 | return DISPLAY_SIZE; |
177 | } |
178 | |
179 | @Override |
180 | public boolean equals(Object other) { |
181 | if (!(other instanceof ValueFloat)) { |
182 | return false; |
183 | } |
184 | return compareSecure((ValueFloat) other, null) == 0; |
185 | } |
186 | |
187 | } |