Rename xxx.lttng to xxx.lttng.core
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf / src / org / eclipse / linuxtools / tmf / event / TmfTimestamp.java
CommitLineData
8c8bf09f 1/*******************************************************************************
cbd4ad82 2 * Copyright (c) 2009, 2010 Ericsson
8c8bf09f
ASL
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:
1f506a43 10 * Francois Chouinard - Initial API and implementation
023761c4 11 * Thomas Gatterweh - Updated scaling / synchronization
8c8bf09f
ASL
12 *******************************************************************************/
13
14package org.eclipse.linuxtools.tmf.event;
15
8c8bf09f
ASL
16/**
17 * <b><u>TmfTimestamp</u></b>
18 * <p>
19 * The fundamental time reference in the TMF.
20 * <p>
21 * It provides a generic timestamp implementation in its most basic form:
22 * <ul>
cbd4ad82
FC
23 * <li>timestamp = [value] * 10**[scale] +/- [precision]
24 * </ul>
25 * Where:
26 * <ul>
27 * <li>[value] is an unstructured integer value
28 * <li>[scale] is the magnitude of the value wrt some application-specific
29 * base unit (e.g. the second)
30 * <li>[precision] indicates the error on the value (useful for comparing
1f506a43 31 * timestamps in different scales). Default: 0.
8c8bf09f 32 * </ul>
cbd4ad82
FC
33 * In short:
34 * <ul>
35 * </ul>
28b94d61 36 * To allow synchronization of timestamps from different reference clocks,
cbd4ad82
FC
37 * there is a possibility to "adjust" the timestamp by changing its scale
38 * (traces of different time scale) and/or by adding an offset to its value
39 * (clock drift between traces).
8c8bf09f 40 * <p>
28b94d61
FC
41 * Notice that the adjusted timestamp value could be negative e.g. for events
42 * that occurred before t0 wrt the reference clock.
8c8bf09f 43 */
a79913eb 44public class TmfTimestamp implements Cloneable, Comparable<TmfTimestamp> {
98029bc9 45
cbd4ad82 46 // ------------------------------------------------------------------------
8c8bf09f 47 // Attributes
cbd4ad82 48 // ------------------------------------------------------------------------
8c8bf09f 49
cbd4ad82 50 protected long fValue; // The timestamp raw value
28b94d61
FC
51 protected byte fScale; // The time scale
52 protected long fPrecision; // The value precision (tolerance)
8c8bf09f 53
cbd4ad82 54 // ------------------------------------------------------------------------
8c8bf09f 55 // Constants
cbd4ad82 56 // ------------------------------------------------------------------------
8c8bf09f
ASL
57
58 // The beginning and end of time
146a887c 59 public static final TmfTimestamp BigBang = new TmfTimestamp(Long.MIN_VALUE, Byte.MAX_VALUE, 0);
8c8bf09f 60 public static final TmfTimestamp BigCrunch = new TmfTimestamp(Long.MAX_VALUE, Byte.MAX_VALUE, 0);
e31e01e8 61 public static final TmfTimestamp Zero = new TmfTimestamp(0, (byte) 0, 0);
8c8bf09f 62
cbd4ad82 63 // ------------------------------------------------------------------------
8c8bf09f 64 // Constructors
cbd4ad82 65 // ------------------------------------------------------------------------
8c8bf09f
ASL
66
67 /**
28b94d61 68 * Default constructor
8c8bf09f
ASL
69 */
70 public TmfTimestamp() {
71 this(0, (byte) 0, 0);
72 }
73
1f506a43 74 /**
28b94d61 75 * Simple constructor with value only
1f506a43
FC
76 */
77 public TmfTimestamp(long value) {
78 this(value, (byte) 0, 0);
79 }
80
8c8bf09f 81 /**
28b94d61 82 * Simple constructor with value and scale
8c8bf09f 83 *
1f506a43
FC
84 * @param value
85 * @param scale
8c8bf09f
ASL
86 */
87 public TmfTimestamp(long value, byte scale) {
88 this(value, scale, 0);
89 }
90
91 /**
28b94d61 92 * Constructor with value, scale and precision
8c8bf09f 93 *
1f506a43
FC
94 * @param value
95 * @param scale
96 * @param precision
8c8bf09f
ASL
97 */
98 public TmfTimestamp(long value, byte scale, long precision) {
99 fValue = value;
100 fScale = scale;
101 fPrecision = Math.abs(precision);
102 }
103
104 /**
28b94d61 105 * Copy constructor
8c8bf09f 106 *
1f506a43 107 * @param other
8c8bf09f
ASL
108 */
109 public TmfTimestamp(TmfTimestamp other) {
cbd4ad82
FC
110 if (other == null)
111 throw new IllegalArgumentException();
28b94d61
FC
112 fValue = other.fValue;
113 fScale = other.fScale;
114 fPrecision = other.fPrecision;
8c8bf09f
ASL
115 }
116
cbd4ad82 117 // ------------------------------------------------------------------------
8c8bf09f 118 // Accessors
cbd4ad82 119 // ------------------------------------------------------------------------
8c8bf09f
ASL
120
121 /**
28b94d61 122 * @return the timestamp value
8c8bf09f
ASL
123 */
124 public long getValue() {
125 return fValue;
126 }
127
128 /**
28b94d61 129 * @return the timestamp scale
8c8bf09f
ASL
130 */
131 public byte getScale() {
132 return fScale;
133 }
134
135 /**
28b94d61 136 * @return the timestamp value precision
8c8bf09f
ASL
137 */
138 public long getPrecision() {
139 return fPrecision;
140 }
141
cbd4ad82 142 // ------------------------------------------------------------------------
8c8bf09f 143 // Operators
cbd4ad82 144 // ------------------------------------------------------------------------
4ab33d2b 145
8c8bf09f
ASL
146 /**
147 * Return a shifted and scaled timestamp.
148 *
149 * Limitation: The scaling is limited to MAX_SCALING orders of magnitude.
150 * The main reason is that the 64 bits value starts to lose any significance
151 * meaning beyond that scale difference and it's not even worth the trouble
152 * to switch to BigDecimal arithmetics.
153 *
cbd4ad82
FC
154 * @param offset the shift value (in the same scale as newScale)
155 * @param newScale the new timestamp scale
156 * @return the synchronized timestamp in the new scale
157 * @throws ArithmeticException
8c8bf09f 158 */
cbd4ad82 159 public TmfTimestamp synchronize(long offset, byte newScale) throws ArithmeticException {
8c8bf09f 160
023761c4 161 long newValue = fValue;
8c8bf09f
ASL
162 long newPrecision = fPrecision;
163
023761c4
FC
164 // Handle the easy case
165 if (fScale == newScale && offset == 0)
166 return this;
167
8c8bf09f
ASL
168 // Determine the scaling factor
169 if (fScale != newScale) {
170 int scaleDiff = Math.abs(fScale - newScale);
171 // Let's try to be realistic...
023761c4 172 if (scaleDiff >= scalingFactors.length) {
3b38ea61 173 throw new ArithmeticException("Scaling exception"); //$NON-NLS-1$
8c8bf09f 174 }
023761c4
FC
175 // Adjust the timestamp
176 long scalingFactor = scalingFactors[scaleDiff];
8c8bf09f
ASL
177 if (newScale < fScale) {
178 newValue *= scalingFactor;
179 newPrecision *= scalingFactor;
180 } else {
181 newValue /= scalingFactor;
182 newPrecision /= scalingFactor;
183 }
184 }
185
023761c4
FC
186 if (offset < 0) {
187 newValue = (newValue < Long.MIN_VALUE - offset) ? Long.MIN_VALUE : newValue + offset;
188 } else {
189 newValue = (newValue > Long.MAX_VALUE - offset) ? Long.MAX_VALUE : newValue + offset;
190 }
191
192 return new TmfTimestamp(newValue, newScale, newPrecision);
8c8bf09f
ASL
193 }
194
023761c4
FC
195 private static final long scalingFactors[] = new long[] {
196 1L,
197 10L,
198 100L,
199 1000L,
200 10000L,
201 100000L,
202 1000000L,
203 10000000L,
204 100000000L,
205 1000000000L,
206 10000000000L,
207 100000000000L,
208 1000000000000L,
209 10000000000000L,
210 100000000000000L,
211 1000000000000000L,
212 10000000000000000L,
213 100000000000000000L,
214 1000000000000000000L,
215 };
216
217 private static final long scalingLimits[] = new long[] {
218 Long.MAX_VALUE / 1L,
219 Long.MAX_VALUE / 10L,
220 Long.MAX_VALUE / 100L,
221 Long.MAX_VALUE / 1000L,
222 Long.MAX_VALUE / 10000L,
223 Long.MAX_VALUE / 100000L,
224 Long.MAX_VALUE / 1000000L,
225 Long.MAX_VALUE / 10000000L,
226 Long.MAX_VALUE / 100000000L,
227 Long.MAX_VALUE / 1000000000L,
228 Long.MAX_VALUE / 10000000000L,
229 Long.MAX_VALUE / 100000000000L,
230 Long.MAX_VALUE / 1000000000000L,
231 Long.MAX_VALUE / 10000000000000L,
232 Long.MAX_VALUE / 100000000000000L,
233 Long.MAX_VALUE / 1000000000000000L,
234 Long.MAX_VALUE / 10000000000000000L,
235 Long.MAX_VALUE / 100000000000000000L,
236 Long.MAX_VALUE / 1000000000000000000L,
237 };
238
239 public static long getScalingFactor(byte scale)
240 {
241 return scalingFactors[scale];
242 }
243
8c8bf09f
ASL
244 /**
245 * Compute the adjustment, in the reference scale, needed to synchronize
1f506a43 246 * this timestamp with a reference timestamp.
8c8bf09f 247 *
cbd4ad82
FC
248 * @param reference the reference timestamp to synchronize with
249 * @param scale the scale of the adjustment
28b94d61 250 * @return the adjustment term in the reference time scale
cbd4ad82 251 * @throws ArithmeticException
8c8bf09f 252 */
cbd4ad82
FC
253 public long getAdjustment(TmfTimestamp reference, byte scale) throws ArithmeticException {
254 TmfTimestamp ts1 = synchronize(0, scale);
255 TmfTimestamp ts2 = reference.synchronize(0, scale);
256 return ts2.fValue - ts1.fValue;
8c8bf09f
ASL
257 }
258
73005152
BH
259 /**
260 * Compute the delta between two timestamps (adjusted to scale of current timestamp).
261 *
262 * @param reference the reference timestamp to synchronize with
263 * @return the delta timestamp
264 * @throws ArithmeticException
265 */
266 public TmfTimestamp getDelta(TmfTimestamp other) throws ArithmeticException {
267 TmfTimestamp newSecond = other;
268 if ((fScale != other.fScale) || (fPrecision != other.fPrecision)) {
269 newSecond = other.synchronize(0, fScale);
270 }
271 return new TmfTimestamp(fValue - newSecond.fValue,
272 fScale,
273 newSecond.fPrecision > fPrecision ? newSecond.fPrecision : fPrecision);
274 }
275
8c8bf09f
ASL
276 /**
277 * Compare with another timestamp
278 *
cbd4ad82
FC
279 * @param other the other timestamp
280 * @param withinPrecision indicates if precision is to be take into consideration
281 * @return -1: this timestamp is lower (i.e. anterior)
28b94d61 282 * 0: timestamps are equal (within precision if requested)
cbd4ad82 283 * 1: this timestamp is higher (i.e. posterior)
8c8bf09f
ASL
284 */
285 public int compareTo(final TmfTimestamp other, boolean withinPrecision) {
286
023761c4
FC
287 // If values have the same time scale, perform the comparison
288 if (fScale == other.fScale) {
289 if (withinPrecision)
290 return compareWithinPrecision(this.fValue, this.fPrecision, other.fValue, other.fPrecision);
291 else
292 return compareNoPrecision(this.fValue, other.fValue);
293 }
8c8bf09f 294
023761c4
FC
295 // If values have different time scales, adjust to the finest one and
296 // then compare. If the scaling difference is too large, revert to
297 // some heuristics. Hopefully, nobody will try to compare galactic and
298 // quantic clock events...
299 int scaleDiff = Math.abs(fScale - other.fScale);
300 long factor, limit;
301 if (scaleDiff < scalingFactors.length) {
302 factor = scalingFactors[scaleDiff];
303 limit = scalingLimits[scaleDiff];
304 } else {
305 factor = 0;
306 limit = 0; // !!! 0 can always be scaled!!!
307 }
f3a4c7f4 308
023761c4
FC
309 if (fScale < other.fScale) {
310 // this has finer scale, so other should be scaled
311 if (withinPrecision)
312 if (other.fValue > limit || other.fValue < -limit
313 || other.fPrecision > limit
314 || other.fPrecision < -limit)
315 return other.fValue > 0 ? -1 : +1; // other exceeds scaling limit
316 else
317 return compareWithinPrecision(this.fValue, this.fPrecision,
318 other.fValue * factor, other.fPrecision * factor);
319 else if (other.fValue > limit || other.fValue < -limit)
320 return other.fValue > 0 ? -1 : +1; // other exceeds scaling limit
321 else
322 return compareNoPrecision(this.fValue, other.fValue * factor);
323 } else {
324 // other has finer scale, so this should be scaled
325 if (withinPrecision)
326 if (this.fValue > limit || this.fValue < -limit
327 || this.fPrecision > limit || this.fPrecision < -limit)
328 return this.fValue > 0 ? +1 : -1; // we exceed scaling limit
329 else
330 return compareWithinPrecision(this.fValue * factor,
331 this.fPrecision * factor, other.fValue,
332 other.fPrecision);
333 else if (this.fValue > limit || this.fValue < -limit)
334 return this.fValue > 0 ? +1 : -1; // we exceed scaling limit
335 else
336 return compareNoPrecision(this.fValue * factor, other.fValue);
337 }
8c8bf09f
ASL
338 }
339
023761c4
FC
340 private static int compareNoPrecision(long thisValue, long otherValue) {
341 return (thisValue == otherValue) ? 0 : (thisValue < otherValue) ? -1 : 1;
342 }
343
344 private static int compareWithinPrecision(long thisValue, long thisPrecision, long otherValue, long otherPrecision) {
345 if ((thisValue + thisPrecision) < (otherValue - otherPrecision))
346 return -1;
347 if ((thisValue - thisPrecision) > (otherValue + otherPrecision))
348 return 1;
349 return 0;
f3a4c7f4
FC
350 }
351
cbd4ad82
FC
352 // ------------------------------------------------------------------------
353 // Object
354 // ------------------------------------------------------------------------
28b94d61 355
8c8bf09f 356 @Override
cbd4ad82
FC
357 public int hashCode() {
358 int result = 17;
359 result = 37 * result + (int) (fValue ^ (fValue >>> 32));
360 result = 37 * result + fScale;
361 result = 37 * result + (int) (fPrecision ^ (fPrecision >>> 32));
362 return result;
363 }
364
365 @Override
8c8bf09f 366 public boolean equals(Object other) {
cbd4ad82
FC
367 if (!(other instanceof TmfTimestamp))
368 return false;
369 TmfTimestamp o = (TmfTimestamp) other;
370 return compareTo(o, false) == 0;
8c8bf09f
ASL
371 }
372
1f506a43 373 @Override
3b38ea61 374 @SuppressWarnings("nls")
1f506a43 375 public String toString() {
28b94d61 376 return "[TmfTimestamp(" + fValue + "," + fScale + "," + fPrecision + ")]";
1f506a43
FC
377 }
378
ff4ed569
FC
379 @Override
380 public TmfTimestamp clone() {
381 TmfTimestamp clone = null;
382 try {
383 clone = (TmfTimestamp) super.clone();
384 clone.fValue = fValue;
385 clone.fScale = fScale;
386 clone.fPrecision = fPrecision;
387 } catch (CloneNotSupportedException e) {
388 }
389 return clone;
390 }
391
a79913eb
FC
392 @Override
393 public int compareTo(TmfTimestamp o) {
394 return compareTo(o, false);
395 }
396
023761c4 397}
This page took 0.048003 seconds and 5 git commands to generate.