Commit | Line | Data |
---|---|---|
53047a66 | 1 | /******************************************************************************* |
ed902a2b | 2 | * Copyright (c) 2011, 2014 Ericsson, Ecole Polytechnique de Montreal and others |
53047a66 MK |
3 | * |
4 | * All rights reserved. This program and the accompanying materials are made | |
5 | * available under the terms of the Eclipse Public License v1.0 which | |
6 | * accompanies this distribution, and is available at | |
7 | * http://www.eclipse.org/legal/epl-v10.html | |
8 | * | |
9 | * Contributors: Matthew Khouzam - Initial API and implementation | |
10 | *******************************************************************************/ | |
fd74e6c1 | 11 | |
f357bcd4 | 12 | package org.eclipse.tracecompass.ctf.core.event.types; |
53047a66 MK |
13 | |
14 | import java.nio.ByteOrder; | |
15 | ||
f78eb6a7 MK |
16 | import org.eclipse.jdt.annotation.NonNullByDefault; |
17 | import org.eclipse.jdt.annotation.Nullable; | |
680f9173 | 18 | import org.eclipse.tracecompass.ctf.core.CTFException; |
f357bcd4 AM |
19 | import org.eclipse.tracecompass.ctf.core.event.io.BitBuffer; |
20 | import org.eclipse.tracecompass.ctf.core.event.scope.IDefinitionScope; | |
a4fa4e36 | 21 | |
9ac2eb62 | 22 | /** |
d37aaa7f | 23 | * A CTF float declaration. |
056ebaf1 | 24 | * |
d37aaa7f | 25 | * The declaration of a floating point basic data type. |
9ac2eb62 | 26 | * |
d37aaa7f | 27 | * @version 1.0 |
9ac2eb62 | 28 | * @author Matthew Khouzam |
9ac2eb62 | 29 | */ |
f78eb6a7 | 30 | @NonNullByDefault |
8fa270f6 | 31 | public final class FloatDeclaration extends Declaration implements ISimpleDatatypeDeclaration { |
53047a66 MK |
32 | |
33 | // ------------------------------------------------------------------------ | |
34 | // Attributes | |
35 | // ------------------------------------------------------------------------ | |
36 | ||
a4fa4e36 MK |
37 | private final int fMantissa; |
38 | private final int fExponent; | |
39 | private final ByteOrder fByteOrder; | |
40 | private final long fAlignement; | |
53047a66 MK |
41 | |
42 | // ------------------------------------------------------------------------ | |
43 | // Constructors | |
44 | // ------------------------------------------------------------------------ | |
45 | ||
9ac2eb62 MK |
46 | /** |
47 | * Constructor | |
056ebaf1 AM |
48 | * |
49 | * @param exponent | |
50 | * The exponent size in bits | |
51 | * @param mantissa | |
52 | * The mantissa size in bits (+1 for sign) (see CTF spec) | |
53 | * @param byteOrder | |
54 | * The byte order | |
55 | * @param alignment | |
ab04fc6b | 56 | * The alignment. Should be ≥ 1 |
9ac2eb62 | 57 | */ |
f78eb6a7 | 58 | public FloatDeclaration(int exponent, int mantissa, @Nullable ByteOrder byteOrder, |
07002e0a | 59 | long alignment) { |
a4fa4e36 MK |
60 | fMantissa = mantissa; |
61 | fExponent = exponent; | |
f78eb6a7 MK |
62 | ByteOrder byteOrder2 = (byteOrder == null) ? ByteOrder.nativeOrder() : byteOrder; |
63 | if (byteOrder2 == null) { | |
64 | throw new IllegalStateException("ByteOrder cannot be null"); //$NON-NLS-1$ | |
65 | } | |
66 | fByteOrder = byteOrder2; | |
a4fa4e36 | 67 | fAlignement = Math.max(alignment, 1); |
53047a66 MK |
68 | |
69 | } | |
70 | ||
71 | // ------------------------------------------------------------------------ | |
a511da0d | 72 | // Getters/Setters/Predicates |
53047a66 MK |
73 | // ------------------------------------------------------------------------ |
74 | ||
53047a66 MK |
75 | /** |
76 | * @return the mant | |
77 | */ | |
78 | public int getMantissa() { | |
a4fa4e36 | 79 | return fMantissa; |
53047a66 MK |
80 | } |
81 | ||
82 | /** | |
83 | * @return the exp | |
84 | */ | |
85 | public int getExponent() { | |
a4fa4e36 | 86 | return fExponent; |
53047a66 MK |
87 | } |
88 | ||
89 | /** | |
90 | * @return the byteOrder | |
91 | */ | |
92 | public ByteOrder getByteOrder() { | |
a4fa4e36 | 93 | return fByteOrder; |
53047a66 MK |
94 | } |
95 | ||
81c8e6f7 | 96 | @Override |
fd74e6c1 | 97 | public long getAlignment() { |
a4fa4e36 MK |
98 | return fAlignement; |
99 | } | |
100 | ||
a4fa4e36 MK |
101 | @Override |
102 | public int getMaximumSize() { | |
103 | return fMantissa + fExponent + 1; | |
fd74e6c1 MK |
104 | } |
105 | ||
53047a66 MK |
106 | // ------------------------------------------------------------------------ |
107 | // Operations | |
108 | // ------------------------------------------------------------------------ | |
109 | ||
110 | @Override | |
f78eb6a7 | 111 | public FloatDefinition createDefinition(@Nullable IDefinitionScope definitionScope, |
680f9173 | 112 | String fieldName, BitBuffer input) throws CTFException { |
733c614c MK |
113 | ByteOrder byteOrder = input.getByteOrder(); |
114 | input.setByteOrder(fByteOrder); | |
a4fa4e36 | 115 | double value = read(input); |
733c614c | 116 | input.setByteOrder(byteOrder); |
a4fa4e36 | 117 | return new FloatDefinition(this, definitionScope, fieldName, value); |
53047a66 MK |
118 | } |
119 | ||
120 | @Override | |
121 | public String toString() { | |
122 | /* Only used for debugging */ | |
123 | return "[declaration] float[" + Integer.toHexString(hashCode()) + ']'; //$NON-NLS-1$ | |
124 | } | |
a4fa4e36 | 125 | |
680f9173 | 126 | private double read(BitBuffer input) throws CTFException { |
a4fa4e36 MK |
127 | /* Offset the buffer position wrt the current alignment */ |
128 | alignRead(input); | |
129 | final int exp = getExponent(); | |
130 | final int mant = getMantissa(); | |
131 | double value = Double.NaN; | |
132 | if ((exp + mant) == 32) { | |
133 | value = readRawFloat32(input, mant, exp); | |
134 | } else if ((exp + mant) == 64) { | |
135 | value = readRawFloat64(input, mant, exp); | |
136 | } | |
137 | return value; | |
138 | } | |
139 | ||
140 | private static double readRawFloat32(BitBuffer input, final int manBits, | |
680f9173 | 141 | final int expBits) throws CTFException { |
a4fa4e36 MK |
142 | long temp = input.get(32, false); |
143 | return createFloat(temp, manBits - 1, expBits); | |
144 | } | |
145 | ||
146 | private static double readRawFloat64(BitBuffer input, final int manBits, | |
680f9173 | 147 | final int expBits) throws CTFException { |
a4fa4e36 MK |
148 | long temp = input.get(64, false); |
149 | return createFloat(temp, manBits - 1, expBits); | |
150 | } | |
151 | ||
152 | /** | |
153 | * Create a float from the raw value, Mathematicians beware. | |
154 | * | |
155 | * @param rawValue | |
156 | * The raw value( up to 64 bits) | |
157 | * @param manBits | |
158 | * number of bits in the mantissa | |
159 | * @param expBits | |
160 | * number of bits in the exponent | |
161 | */ | |
162 | private static double createFloat(long rawValue, final int manBits, | |
163 | final int expBits) { | |
164 | long manShift = 1L << (manBits); | |
165 | long manMask = manShift - 1; | |
166 | long expMask = (1L << expBits) - 1; | |
167 | ||
168 | int exp = (int) ((rawValue >> (manBits)) & expMask) + 1; | |
169 | long man = (rawValue & manMask); | |
170 | final int offsetExponent = exp - (1 << (expBits - 1)); | |
171 | double expPow = Math.pow(2.0, offsetExponent); | |
172 | double ret = man * 1.0f; | |
173 | ret /= manShift; | |
174 | ret += 1.0; | |
175 | ret *= expPow; | |
176 | return ret; | |
177 | } | |
e00e6663 MK |
178 | |
179 | @Override | |
180 | public int hashCode() { | |
181 | final int prime = 31; | |
182 | int result = 1; | |
183 | result = prime * result + (int) (fAlignement ^ (fAlignement >>> 32)); | |
f068c622 | 184 | result = prime * result + fByteOrder.toString().hashCode(); // don't evaluate object but string |
e00e6663 MK |
185 | result = prime * result + fExponent; |
186 | result = prime * result + fMantissa; | |
187 | return result; | |
188 | } | |
189 | ||
190 | @Override | |
191 | public boolean equals(@Nullable Object obj) { | |
192 | if (this == obj) { | |
193 | return true; | |
194 | } | |
195 | if (obj == null) { | |
196 | return false; | |
197 | } | |
198 | if (getClass() != obj.getClass()) { | |
199 | return false; | |
200 | } | |
201 | FloatDeclaration other = (FloatDeclaration) obj; | |
202 | if (fAlignement != other.fAlignement) { | |
203 | return false; | |
204 | } | |
205 | if (!fByteOrder.equals(other.fByteOrder)) { | |
206 | return false; | |
207 | } | |
208 | if (fExponent != other.fExponent) { | |
209 | return false; | |
210 | } | |
211 | if (fMantissa != other.fMantissa) { | |
212 | return false; | |
213 | } | |
214 | return true; | |
215 | } | |
216 | ||
66aa25f0 MK |
217 | @Override |
218 | public boolean isBinaryEquivalent(@Nullable IDeclaration obj) { | |
219 | return equals(obj); | |
220 | } | |
53047a66 | 221 | } |