447b2b5184ea107f2b4b0acb7d5ce9fbbb3dc623
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf / src / org / eclipse / linuxtools / tmf / event / TmfTimestamp.java
1 /*******************************************************************************
2 * Copyright (c) 2009 Ericsson
3 *
4 * All rights reserved. This program and the accompanying materials are
5 * made 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:
10 * Francois Chouinard - Initial API and implementation
11 *******************************************************************************/
12
13 package org.eclipse.linuxtools.tmf.event;
14
15 /**
16 * <b><u>TmfTimestamp</u></b>
17 * <p>
18 * The fundamental time reference in the TMF.
19 * <p>
20 * It provides a generic timestamp implementation in its most basic form:
21 * <ul>
22 * <li>an unstructured integer value
23 * <li>a time scale corresponding to the magnitude of the value wrt some
24 * application-specific base unit (e.g. the second)
25 * <li>a precision to indicate the error on the value (useful for comparing
26 * timestamps in different scales). Default: 0.
27 * </ul>
28 * To allow synchronization of timestamps from different reference clocks, there
29 * is a possibility to "adjust" the timestamp both by changing its scale (traces
30 * of different scale) and by adding an offset to its value (clock drift between
31 * traces).
32 * <p>
33 * Note that the adjusted timestamp value could be negative e.g. for events that
34 * occurred before t0 of the reference clock.
35 *
36 */
37 public class TmfTimestamp {
38
39 // ========================================================================
40 // Attributes
41 // ========================================================================
42
43 protected final long fValue; // The timestamp value
44 protected final byte fScale; // The time scale
45 protected final long fPrecision; // The value precision (tolerance)
46
47 // ========================================================================
48 // Constants
49 // ========================================================================
50
51 // The beginning and end of time
52 public static final TmfTimestamp BigBang = new TmfTimestamp(0, (byte) 0, 0);
53 public static final TmfTimestamp BigCrunch = new TmfTimestamp(Long.MAX_VALUE, Byte.MAX_VALUE, 0);
54
55 // ========================================================================
56 // Constructors
57 // ========================================================================
58
59 /**
60 * Default constructor.
61 */
62 public TmfTimestamp() {
63 this(0, (byte) 0, 0);
64 }
65
66 /**
67 * Simple constructor.
68 */
69 public TmfTimestamp(long value) {
70 this(value, (byte) 0, 0);
71 }
72
73 /**
74 * Simple constructor with default error value
75 *
76 * @param value
77 * @param scale
78 */
79 public TmfTimestamp(long value, byte scale) {
80 this(value, scale, 0);
81 }
82
83 /**
84 * Constructor with measurement error.
85 *
86 * @param value
87 * @param scale
88 * @param precision
89 */
90 public TmfTimestamp(long value, byte scale, long precision) {
91 fValue = value;
92 fScale = scale;
93 fPrecision = Math.abs(precision);
94 }
95
96 /**
97 * Copy constructor.
98 *
99 * @param other
100 */
101 public TmfTimestamp(TmfTimestamp other) {
102 this(other.fValue, other.fScale, other.fPrecision);
103 }
104
105 // ========================================================================
106 // Accessors
107 // ========================================================================
108
109 /**
110 * @return The timestamp value
111 */
112 public long getValue() {
113 return fValue;
114 }
115
116 /**
117 * @return The timestamp scale
118 */
119 public byte getScale() {
120 return fScale;
121 }
122
123 /**
124 * @return The timestamp value precision
125 */
126 public long getPrecision() {
127 return fPrecision;
128 }
129
130 // ========================================================================
131 // Operators
132 // ========================================================================
133
134 /**
135 * Return a shifted and scaled timestamp.
136 *
137 * Limitation: The scaling is limited to MAX_SCALING orders of magnitude.
138 * The main reason is that the 64 bits value starts to lose any significance
139 * meaning beyond that scale difference and it's not even worth the trouble
140 * to switch to BigDecimal arithmetics.
141 *
142 * @param offset
143 * - the shift value (in the same scale as newScale)
144 * @param newScale
145 * - the new scale
146 * @return The synchronized timestamp
147 */
148
149 /*
150 * A java <code>long</code> has a maximum of 19 significant digits.
151 * (-9,223,372,036,854,775,808 .. +9,223,372,036,854,775,807)
152 *
153 * It is therefore useless to try to synchronize 2 timestamps whose
154 * difference in scale exceeds that value.
155 */
156 private static int MAX_SCALING = 19;
157
158 public TmfTimestamp synchronize(long offset, byte newScale) throws ArithmeticException {
159 long newValue = fValue;
160 long newPrecision = fPrecision;
161
162 // Determine the scaling factor
163 if (fScale != newScale) {
164 int scaleDiff = Math.abs(fScale - newScale);
165 // Let's try to be realistic...
166 if (scaleDiff > MAX_SCALING) {
167 throw new ArithmeticException("Scaling exception");
168 }
169 // Not pretty...
170 long scalingFactor = 1;
171 for (int i = 0; i < scaleDiff; i++) {
172 scalingFactor *= 10;
173 }
174 if (newScale < fScale) {
175 newValue *= scalingFactor;
176 newPrecision *= scalingFactor;
177 } else {
178 newValue /= scalingFactor;
179 newPrecision /= scalingFactor;
180 }
181 }
182
183 return new TmfTimestamp(newValue + offset, newScale, newPrecision);
184 }
185
186 /**
187 * Compute the adjustment, in the reference scale, needed to synchronize
188 * this timestamp with a reference timestamp.
189 *
190 * @param reference
191 * - the reference timestamp to synchronize with
192 * @return The adjustment term in the reference time scale
193 * @throws TmfNumericalException
194 */
195 public long getAdjustment(TmfTimestamp reference) throws ArithmeticException {
196 TmfTimestamp ts = synchronize(0, reference.fScale);
197 return reference.fValue - ts.fValue;
198 }
199
200 /**
201 * Compare with another timestamp
202 *
203 * @param other
204 * - the other timestamp
205 * @param withinPrecision
206 * - indicates if precision is to be take into consideration
207 * @return <li>-1: this timestamp is lower <li>0: timestamps are equal
208 * (within precision if requested) <li>1: this timestamp is higher
209 * @throws TmfNumericalException
210 */
211 public int compareTo(final TmfTimestamp other, boolean withinPrecision) {
212
213 // If values have the same time scale, perform the comparison
214 if (fScale == other.fScale) {
215 if (withinPrecision) {
216 if ((fValue + fPrecision) < (other.fValue - other.fPrecision))
217 return -1;
218 if ((fValue - fPrecision) > (other.fValue + other.fPrecision))
219 return 1;
220 return 0;
221 }
222 return (fValue == other.fValue) ? 0 : (fValue < other.fValue) ? -1
223 : 1;
224 }
225
226 // If values have different time scales, adjust to the finest one and
227 // then compare. If the scaling difference is too large, revert to
228 // some heuristics. Hopefully, nobody will try to compare galactic and
229 // atomic clock events...
230 byte newScale = (fScale < other.fScale) ? fScale : other.fScale;
231 try {
232 TmfTimestamp ts1 = this.synchronize(0, newScale);
233 TmfTimestamp ts2 = other.synchronize(0, newScale);
234 return ts1.compareTo(ts2, withinPrecision);
235 } catch (ArithmeticException e) {
236 if ((fValue == 0) || (other.fValue == 0)) {
237 return (fValue == other.fValue) ? 0
238 : (fValue < other.fValue) ? -1 : 1;
239 }
240 if ((fValue > 0) && (other.fValue > 0)) {
241 return (fScale < other.fScale) ? -1 : 1;
242 }
243 if ((fValue < 0) && (other.fValue < 0)) {
244 return (fScale > other.fScale) ? -1 : 1;
245 }
246 return (fValue < 0) ? -1 : 1;
247 }
248 }
249
250 /*
251 * (non-Javadoc)
252 *
253 * @see java.lang.Object#equals(java.lang.Object)
254 */
255 @Override
256 public boolean equals(Object other) {
257 if (other instanceof TmfTimestamp)
258 return compareTo((TmfTimestamp) other, false) == 0;
259 return super.equals(other);
260 }
261
262 /* (non-Javadoc)
263 * @see java.lang.Object#toString()
264 */
265 @Override
266 public String toString() {
267 return "[TmfTimestamp:" + fValue + "," + fScale + "," + fPrecision + "]";
268 }
269
270 }
This page took 0.036883 seconds and 4 git commands to generate.