1559b0622e53a8d295f992b34f50f6a017bbde36
[vxquery.git] / vxquery-core / src / main / java / org / apache / vxquery / datamodel / accessors / atomic / XSDecimalPointable.java
1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.vxquery.datamodel.accessors.atomic;
18
19 import org.apache.hyracks.api.dataflow.value.ITypeTraits;
20 import org.apache.hyracks.data.std.api.AbstractPointable;
21 import org.apache.hyracks.data.std.api.IComparable;
22 import org.apache.hyracks.data.std.api.IHashable;
23 import org.apache.hyracks.data.std.api.INumeric;
24 import org.apache.hyracks.data.std.api.IPointable;
25 import org.apache.hyracks.data.std.api.IPointableFactory;
26 import org.apache.hyracks.data.std.primitive.BytePointable;
27 import org.apache.hyracks.data.std.primitive.LongPointable;
28
29 public class XSDecimalPointable extends AbstractPointable implements IHashable, IComparable, INumeric {
30 private final static int DECIMAL_PLACE_OFFSET = 0;
31 private final static int VALUE_OFFSET = 1;
32 public final static int PRECISION = 18;
33
34 public static final ITypeTraits TYPE_TRAITS = new ITypeTraits() {
35 private static final long serialVersionUID = 1L;
36
37 @Override
38 public boolean isFixedLength() {
39 return true;
40 }
41
42 @Override
43 public int getFixedLength() {
44 return 9;
45 }
46 };
47
48 public static final IPointableFactory FACTORY = new IPointableFactory() {
49 private static final long serialVersionUID = 1L;
50
51 @Override
52 public IPointable createPointable() {
53 return new XSDecimalPointable();
54 }
55
56 @Override
57 public ITypeTraits getTypeTraits() {
58 return TYPE_TRAITS;
59 }
60 };
61
62 @Override
63 public int compareTo(byte[] bytes, int start, int length) {
64 long v = getDecimalValue();
65 byte p = getDecimalPlace();
66 long ov = getDecimalValue(bytes, start);
67 byte op = getDecimalPlace(bytes, start);
68
69 // Make both long values have the decimal point at the same place.
70 // TODO double check that precision is not being lost.
71 int diff = p - op;
72 if (diff > 0) {
73 ov = (long) (ov * Math.pow(10, diff));
74 } else if (diff < 0) {
75 v = (long) (v * Math.pow(10, Math.abs(diff)));
76 }
77
78 return v < ov ? -1 : (v > ov ? 1 : 0);
79 }
80
81 @Override
82 public int compareTo(IPointable pointer) {
83 return compareTo(pointer.getByteArray(), pointer.getStartOffset(), pointer.getLength());
84 }
85
86 public void setDecimal(long value, byte decimalPlace) {
87 BytePointable.setByte(bytes, start + DECIMAL_PLACE_OFFSET, decimalPlace);
88 LongPointable.setLong(bytes, start + VALUE_OFFSET, value);
89 normalize();
90 }
91
92 public void normalize() {
93 normalize(bytes, start);
94 }
95
96 public static void normalize(byte[] bytes, int start) {
97 byte decimalPlace = getDecimalPlace(bytes, start);
98 long value = getDecimalValue(bytes, start);
99 // Normalize the value and take off trailing zeros.
100 while (value != 0 && value % 10 == 0) {
101 value /= 10;
102 --decimalPlace;
103 }
104 BytePointable.setByte(bytes, start + DECIMAL_PLACE_OFFSET, decimalPlace);
105 LongPointable.setLong(bytes, start + VALUE_OFFSET, value);
106 }
107
108 public byte getDecimalPlace() {
109 return BytePointable.getByte(bytes, start);
110 }
111
112 public static byte getDecimalPlace(byte[] bytes, int start) {
113 return BytePointable.getByte(bytes, start + DECIMAL_PLACE_OFFSET);
114 }
115
116 public long getDecimalValue() {
117 return getDecimalValue(bytes, start);
118 }
119
120 public static long getDecimalValue(byte[] bytes, int start) {
121 return LongPointable.getLong(bytes, start + VALUE_OFFSET);
122 }
123
124 @Override
125 public int hash() {
126 long v = getDecimalValue();
127 return (int) (v ^ (v >>> 32));
128 }
129
130 public long getBeforeDecimalPlaceRounded() {
131 return getBeforeDecimalPlaceRounded(bytes, start);
132 }
133
134 public static long getBeforeDecimalPlaceRounded(byte[] bytes, int start) {
135 if (getDecimalPlace(bytes, start) != 0) {
136 return Math.round(getDecimalValue(bytes, start) / Math.pow(10, getDecimalPlace(bytes, start)));
137 } else {
138 return getDecimalValue(bytes, start);
139 }
140 }
141
142 public long getBeforeDecimalPlace() {
143 return getBeforeDecimalPlace(bytes, start);
144 }
145
146 public static long getBeforeDecimalPlace(byte[] bytes, int start) {
147 if (getDecimalPlace(bytes, start) != 0) {
148 return (long) (getDecimalValue(bytes, start) / Math.pow(10, getDecimalPlace(bytes, start)));
149 } else {
150 return getDecimalValue(bytes, start);
151 }
152
153 }
154
155 public byte getDigitCount() {
156 return getDigitCount(bytes, start);
157 }
158
159 public static byte getDigitCount(byte[] bytes, int start) {
160 long value = getDecimalValue(bytes, start);
161 if (value < 0) {
162 value *= -1;
163 }
164 long check = 10;
165 for (byte i = 1; i < PRECISION; i++) {
166 if (value < check)
167 return i;
168 check *= 10;
169 }
170 return PRECISION;
171 }
172
173 @Override
174 public byte byteValue() {
175 return (byte) getBeforeDecimalPlace();
176 }
177
178 @Override
179 public short shortValue() {
180 return (short) getBeforeDecimalPlace();
181 }
182
183 @Override
184 public int intValue() {
185 return (int) getBeforeDecimalPlace();
186 }
187
188 @Override
189 public long longValue() {
190 return getBeforeDecimalPlace();
191 }
192
193 @Override
194 public float floatValue() {
195 return (float) (getDecimalValue() / Math.pow(10, getDecimalPlace()));
196 }
197
198 @Override
199 public double doubleValue() {
200 return ((double) getDecimalValue()) / Math.pow(10, getDecimalPlace());
201 }
202
203 }

Copyright 2016, The Apache Software Foundation.