(no commit message)
[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 (fchouinard@gmail.com) - 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,
29 * there is a possibility to "adjust" the timestamp both by changing its
30 * scale (traces of different scale) and by adding an offset to its value
31 * (clock drift between traces).
32 * <p>
33 * Note that the adjusted timestamp value could be negative e.g. for events
34 * that occurred before t0 of the reference clock.
35 *
36 */
37 public class TmfTimestamp {
38
39 // ========================================================================
40 // Attributes
41 // ========================================================================
42
43 private final long fValue; // The timestamp value
44 private final byte fScale; // The time scale
45 private 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 with default error value
68 *
69 * @param value - the original time value
70 * @param scale - the time scale
71 */
72 public TmfTimestamp(long value, byte scale) {
73 this(value, scale, 0);
74 }
75
76 /**
77 * Constructor with measurement error.
78 *
79 * @param value - the time value
80 * @param scale - the time scale
81 * @param precision - the value precision (tolerance)
82 */
83 public TmfTimestamp(long value, byte scale, long precision) {
84 fValue = value;
85 fScale = scale;
86 fPrecision = Math.abs(precision);
87 }
88
89 /**
90 * Copy constructor.
91 *
92 * @param other - the timestamp to clone
93 */
94 public TmfTimestamp(TmfTimestamp other) {
95 this(other.fValue, other.fScale, other.fPrecision);
96 }
97
98 // ========================================================================
99 // Accessors
100 // ========================================================================
101
102 /**
103 * @return The timestamp value
104 */
105 public long getValue() {
106 return fValue;
107 }
108
109 /**
110 * @return The timestamp scale
111 */
112 public byte getScale() {
113 return fScale;
114 }
115
116 /**
117 * @return The timestamp value precision
118 */
119 public long getPrecision() {
120 return fPrecision;
121 }
122
123 // ========================================================================
124 // Operators
125 // ========================================================================
126
127 @Override
128 public String toString() {
129 return "[TmfTimestamp:" + fValue + "," + fScale + "," + fPrecision + "]";
130 }
131
132 /**
133 * Return a shifted and scaled timestamp.
134 *
135 * Limitation: The scaling is limited to MAX_SCALING orders of magnitude.
136 * The main reason is that the 64 bits value starts to lose any significance
137 * meaning beyond that scale difference and it's not even worth the trouble
138 * to switch to BigDecimal arithmetics.
139 *
140 * @param offset - the shift value (in the same scale as newScale)
141 * @param newScale - the new scale
142 * @return The synchronized timestamp
143 */
144
145 /*
146 * A java <code>long</code> has a maximum of 19 significant digits.
147 * (-9,223,372,036,854,775,808 .. +9,223,372,036,854,775,807)
148 *
149 * It is therefore useless to try to synchronize 2 timestamps whose
150 * difference in scale exceeds that value.
151 */
152 private static int MAX_SCALING = 19;
153 public TmfTimestamp synchronize(long offset, byte newScale) throws ArithmeticException {
154 long newValue = fValue;
155 long newPrecision = fPrecision;
156
157 // Determine the scaling factor
158 if (fScale != newScale) {
159 int scaleDiff = Math.abs(fScale - newScale);
160 // Let's try to be realistic...
161 if (scaleDiff > MAX_SCALING) {
162 throw new ArithmeticException("Scaling exception");
163 }
164 long scalingFactor = 1;
165 for (int i = 0; i < Math.abs(fScale - newScale); i++) {
166 scalingFactor *= 10;
167 }
168 if (newScale < fScale) {
169 newValue *= scalingFactor;
170 newPrecision *= scalingFactor;
171 } else {
172 newValue /= scalingFactor;
173 newPrecision /= scalingFactor;
174 }
175 }
176
177 return new TmfTimestamp(newValue + offset, newScale, newPrecision);
178 }
179
180 /**
181 * Compute the adjustment, in the reference scale, needed to synchronize
182 * this timestamp with a reference timestamp.
183 *
184 * @param reference - the reference timestamp to synchronize with
185 * @return The adjustment term in the reference time scale
186 * @throws TmfNumericalException
187 */
188 public long getAdjustment(TmfTimestamp reference) throws ArithmeticException {
189 TmfTimestamp ts = synchronize(0, reference.fScale);
190 return reference.fValue - ts.fValue;
191 }
192
193 /**
194 * Compare with another timestamp
195 *
196 * @param other - the otehr timestamp
197 * @param withinPrecision - indicates if precision is to be take into consideration
198 * @return <li> -1: this timestamp is lower
199 * <li> 0: timestamps are equal (within precision if requested)
200 * <li> 1: this timestamp is higher
201 * @throws TmfNumericalException
202 */
203 public int compareTo(final TmfTimestamp other, boolean withinPrecision) {
204
205 // If values have the same time scale, perform the comparison
206 if (fScale == other.fScale) {
207 if (withinPrecision) {
208 if ((fValue + fPrecision) < (other.fValue - other.fPrecision))
209 return -1;
210 if ((fValue - fPrecision) > (other.fValue + other.fPrecision))
211 return 1;
212 return 0;
213 }
214 return (fValue == other.fValue) ? 0 :
215 (fValue < other.fValue) ? -1 : 1;
216 }
217
218 // If values have different time scales, adjust to the finest one and
219 // then compare. If the scaling difference is too large, revert to
220 // some heuristics. Hopefully, nobody will try to compare galactic and
221 // atomic clock events...
222 byte newScale = (fScale < other.fScale) ? fScale : other.fScale;
223 try {
224 TmfTimestamp ts1 = this.synchronize(0, newScale);
225 TmfTimestamp ts2 = other.synchronize(0, newScale);
226 return ts1.compareTo(ts2, withinPrecision);
227 } catch (ArithmeticException e) {
228 if ((fValue == 0) || (other.fValue == 0)) {
229 return (fValue == other.fValue) ? 0 : (fValue < other.fValue) ? -1 : 1;
230 }
231 if ((fValue > 0) && (other.fValue > 0)) {
232 return (fScale < other.fScale) ? -1 : 1;
233 }
234 if ((fValue < 0) && (other.fValue < 0)) {
235 return (fScale > other.fScale) ? -1 : 1;
236 }
237 return (fValue < 0) ? -1 : 1;
238 }
239 }
240
241 /* (non-Javadoc)
242 * @see java.lang.Object#equals(java.lang.Object)
243 */
244 @Override
245 public boolean equals(Object other) {
246 if (other instanceof TmfTimestamp)
247 return compareTo((TmfTimestamp) other, false) == 0;
248 return super.equals(other);
249 }
250
251 }
This page took 0.035895 seconds and 6 git commands to generate.