f23b91879048cb748ed2e01f72f74f703d414df4
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.core / src / org / eclipse / linuxtools / tmf / core / event / TmfTimestamp.java
1 /*******************************************************************************
2 * Copyright (c) 2009, 2010, 2012 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 * Thomas Gatterweh - Updated scaling / synchronization
12 * Francois Chouinard - Refactoring to align with TMF Event Model 1.0
13 * Francois Chouinard - Implement augmented interface
14 *******************************************************************************/
15
16 package org.eclipse.linuxtools.tmf.core.event;
17
18 /**
19 * A generic timestamp implementation. The timestamp is represented by the
20 * tuple { value, scale, precision }. By default, timestamps are in the
21 * nanosecond scale.
22 *
23 * @version 1.1
24 * @author Francois Chouinard
25 */
26 public class TmfTimestamp implements ITmfTimestamp, Cloneable {
27
28 // ------------------------------------------------------------------------
29 // Constants
30 // ------------------------------------------------------------------------
31
32 /**
33 * The beginning of time
34 */
35 public static final ITmfTimestamp BIG_BANG =
36 new TmfTimestamp(Long.MIN_VALUE, Integer.MAX_VALUE, 0);
37
38 /**
39 * The end of time
40 */
41 public static final ITmfTimestamp BIG_CRUNCH =
42 new TmfTimestamp(Long.MAX_VALUE, Integer.MAX_VALUE, 0);
43
44 /**
45 * A more practical definition of "beginning of time"
46 * @since 2.0
47 */
48 public static final ITmfTimestamp PROJECT_IS_FUNDED = BIG_BANG;
49
50 /**
51 * A more practical definition of "end of time"
52 * @since 2.0
53 */
54 public static final ITmfTimestamp PROJECT_IS_CANCELLED = BIG_CRUNCH;
55
56 /**
57 * Zero
58 */
59 public static final ITmfTimestamp ZERO =
60 new TmfTimestamp(0, 0, 0);
61
62 // ------------------------------------------------------------------------
63 // Attributes
64 // ------------------------------------------------------------------------
65
66 /**
67 * The timestamp raw value (mantissa) in nanoseconds
68 */
69 private long fValue;
70
71 /**
72 * The timestamp scale (magnitude)
73 */
74 private int fScale;
75
76 /**
77 * The value precision (tolerance)
78 */
79 private int fPrecision;
80
81 // ------------------------------------------------------------------------
82 // Constructors
83 // ------------------------------------------------------------------------
84
85 /**
86 * Default constructor
87 */
88 public TmfTimestamp() {
89 this(0, ITmfTimestamp.SECOND_SCALE, 0);
90 }
91
92 /**
93 * Simple constructor (scale = precision = 0)
94 *
95 * @param value the timestamp value
96 */
97 public TmfTimestamp(final long value) {
98 this(value, ITmfTimestamp.SECOND_SCALE, 0);
99 }
100
101 /**
102 * Simple constructor (precision = 0)
103 *
104 * @param value the timestamp value
105 * @param scale the timestamp scale
106 */
107 public TmfTimestamp(final long value, final int scale) {
108 this(value, scale, 0);
109 }
110
111 /**
112 * Full constructor
113 *
114 * @param value the timestamp value
115 * @param scale the timestamp scale
116 * @param precision the timestamp precision
117 */
118 public TmfTimestamp(final long value, final int scale, final int precision) {
119 fValue = value;
120 fScale = scale;
121 fPrecision = Math.abs(precision);
122 }
123
124 /**
125 * Copy constructor
126 *
127 * @param timestamp the timestamp to copy
128 */
129 public TmfTimestamp(final ITmfTimestamp timestamp) {
130 if (timestamp == null) {
131 throw new IllegalArgumentException();
132 }
133 fValue = timestamp.getValue();
134 fScale = timestamp.getScale();
135 fPrecision = timestamp.getPrecision();
136 }
137
138 // ------------------------------------------------------------------------
139 // Setters
140 // ------------------------------------------------------------------------
141
142 protected void setValue(long value, int scale, int precision) {
143 fValue = value;
144 fScale = scale;
145 fPrecision = precision;
146 }
147
148 // ------------------------------------------------------------------------
149 // ITmfTimestamp
150 // ------------------------------------------------------------------------
151
152 /* (non-Javadoc)
153 * @see org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp#getValue()
154 */
155 @Override
156 public long getValue() {
157 return fValue;
158 }
159
160 /* (non-Javadoc)
161 * @see org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp#getScale()
162 */
163 @Override
164 public int getScale() {
165 return fScale;
166 }
167
168 /* (non-Javadoc)
169 * @see org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp#getPrecision()
170 */
171 @Override
172 public int getPrecision() {
173 return fPrecision;
174 }
175
176 private static final long scalingFactors[] = new long[] {
177 1L,
178 10L,
179 100L,
180 1000L,
181 10000L,
182 100000L,
183 1000000L,
184 10000000L,
185 100000000L,
186 1000000000L,
187 10000000000L,
188 100000000000L,
189 1000000000000L,
190 10000000000000L,
191 100000000000000L,
192 1000000000000000L,
193 10000000000000000L,
194 100000000000000000L,
195 1000000000000000000L,
196 };
197
198 /* (non-Javadoc)
199 * @see org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp#normalize(long, int)
200 */
201 @Override
202 public ITmfTimestamp normalize(final long offset, final int scale) {
203
204 long value = fValue;
205 int precision = fPrecision;
206
207 // Handle the trivial case
208 if (fScale == scale && offset == 0) {
209 return new TmfTimestamp(this);
210 }
211
212 // In case of big bang and big crunch just return this (no need to normalize)
213 if (this.equals(BIG_BANG) || this.equals(BIG_CRUNCH)) {
214 return this;
215 }
216
217 // First, scale the timestamp
218 if (fScale != scale) {
219 final int scaleDiff = Math.abs(fScale - scale);
220 if (scaleDiff >= scalingFactors.length) {
221 throw new ArithmeticException("Scaling exception"); //$NON-NLS-1$
222 }
223
224 final long scalingFactor = scalingFactors[scaleDiff];
225 if (scale < fScale) {
226 value *= scalingFactor;
227 precision *= scalingFactor;
228 } else {
229 value /= scalingFactor;
230 precision /= scalingFactor;
231 }
232 }
233
234 // Then, apply the offset
235 if (offset < 0) {
236 value = (value < Long.MIN_VALUE - offset) ? Long.MIN_VALUE : value + offset;
237 } else {
238 value = (value > Long.MAX_VALUE - offset) ? Long.MAX_VALUE : value + offset;
239 }
240
241 return new TmfTimestamp(value, scale, precision);
242 }
243
244 /* (non-Javadoc)
245 * @see org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp#compareTo(org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp, boolean)
246 */
247 @Override
248 public int compareTo(final ITmfTimestamp ts, final boolean withinPrecision) {
249
250 // Check the corner cases (we can't use equals() because it uses compareTo()...)
251 if (ts == null) {
252 return 1;
253 }
254 if (this == ts || (fValue == ts.getValue() && fScale == ts.getScale())) {
255 return 0;
256 }
257 if ((fValue == BIG_BANG.getValue() && fScale == BIG_BANG.getScale()) || (ts.getValue() == BIG_CRUNCH.getValue() && ts.getScale() == BIG_CRUNCH.getScale())) {
258 return -1;
259 }
260 if ((fValue == BIG_CRUNCH.getValue() && fScale == BIG_CRUNCH.getScale()) || (ts.getValue() == BIG_BANG.getValue() && ts.getScale() == BIG_BANG.getScale())) {
261 return 1;
262 }
263
264 try {
265 final ITmfTimestamp nts = ts.normalize(0, fScale);
266 final long delta = fValue - nts.getValue();
267 if ((delta == 0) || (withinPrecision && (Math.abs(delta) <= (fPrecision + nts.getPrecision())))) {
268 return 0;
269 }
270 return (delta > 0) ? 1 : -1;
271 }
272 catch (final ArithmeticException e) {
273 // Scaling error. We can figure it out nonetheless.
274
275 // First, look at the sign of the mantissa
276 final long value = ts.getValue();
277 if (fValue == 0 && value == 0) {
278 return 0;
279 }
280 if (fValue < 0 && value >= 0) {
281 return -1;
282 }
283 if (fValue >= 0 && value < 0) {
284 return 1;
285 }
286
287 // Otherwise, just compare the scales
288 final int scale = ts.getScale();
289 return (fScale > scale) ? (fValue >= 0) ? 1 : -1 : (fValue >= 0) ? -1 : 1;
290 }
291 }
292
293 /* (non-Javadoc)
294 * @see org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp#getDelta(org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp)
295 */
296 @Override
297 public ITmfTimestamp getDelta(final ITmfTimestamp ts) {
298 final ITmfTimestamp nts = ts.normalize(0, fScale);
299 final long value = fValue - nts.getValue();
300 return new TmfTimestamp(value, fScale, fPrecision + nts.getPrecision());
301 }
302
303 // ------------------------------------------------------------------------
304 // Cloneable
305 // ------------------------------------------------------------------------
306
307 /* (non-Javadoc)
308 * @see java.lang.Object#clone()
309 */
310 @Override
311 public TmfTimestamp clone() {
312 TmfTimestamp clone = null;
313 try {
314 clone = (TmfTimestamp) super.clone();
315 clone.fValue = fValue;
316 clone.fScale = fScale;
317 clone.fPrecision = fPrecision;
318 } catch (final CloneNotSupportedException e) {
319 }
320 return clone;
321 }
322
323 // ------------------------------------------------------------------------
324 // Comparable
325 // ------------------------------------------------------------------------
326
327 /* (non-Javadoc)
328 * @see org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp#compareTo(org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp)
329 */
330 @Override
331 public int compareTo(final ITmfTimestamp ts) {
332 return compareTo(ts, false);
333 }
334
335 // ------------------------------------------------------------------------
336 // Object
337 // ------------------------------------------------------------------------
338
339 /* (non-Javadoc)
340 * @see java.lang.Object#hashCode()
341 */
342 @Override
343 public int hashCode() {
344 final int prime = 31;
345 int result = 1;
346 result = prime * result + (int) (fValue ^ (fValue >>> 32));
347 result = prime * result + fScale;
348 result = prime * result + fPrecision;
349 return result;
350 }
351
352 /* (non-Javadoc)
353 * @see java.lang.Object#equals(java.lang.Object)
354 */
355 @Override
356 public boolean equals(final Object other) {
357 if (this == other) {
358 return true;
359 }
360 if (other == null) {
361 return false;
362 }
363 if (!(other instanceof TmfTimestamp)) {
364 return false;
365 }
366 final TmfTimestamp ts = (TmfTimestamp) other;
367 return compareTo(ts, false) == 0;
368 }
369
370 /* (non-Javadoc)
371 * @see java.lang.Object#toString()
372 */
373 @Override
374 public String toString() {
375 return toString(TmfTimestampFormat.getDefaulTimeFormat());
376 }
377
378 /* (non-Javadoc)
379 * @see org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp#toString(org.eclipse.linuxtools.tmf.core.event.TmfTimestampFormat)
380 */
381 /**
382 * @since 2.0
383 */
384 @Override
385 public String toString(final TmfTimestampFormat format) {
386 try {
387 ITmfTimestamp ts = normalize(0, ITmfTimestamp.NANOSECOND_SCALE);
388 return format.format(ts.getValue());
389 }
390 catch (ArithmeticException e) {
391 return format.format(0);
392 }
393 }
394
395 }
This page took 0.040038 seconds and 5 git commands to generate.