1 /*******************************************************************************
2 * Copyright (c) 2009, 2010, 2012 Ericsson
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
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 *******************************************************************************/
15 package org
.eclipse
.linuxtools
.tmf
.core
.event
;
19 * A generic timestamp implementation. The timestamp is represented by the
20 * tuple { value, scale, precision }.
23 * @author Francois Chouinard
25 public class TmfTimestamp
implements ITmfTimestamp
, Cloneable
{
27 // ------------------------------------------------------------------------
29 // ------------------------------------------------------------------------
32 * The beginning of time
34 public static final ITmfTimestamp BIG_BANG
=
35 new TmfTimestamp(Long
.MIN_VALUE
, Integer
.MAX_VALUE
, 0);
40 public static final ITmfTimestamp BIG_CRUNCH
=
41 new TmfTimestamp(Long
.MAX_VALUE
, Integer
.MAX_VALUE
, 0);
46 public static final ITmfTimestamp ZERO
=
47 new TmfTimestamp(0, 0, 0);
49 // ------------------------------------------------------------------------
51 // ------------------------------------------------------------------------
54 * The timestamp raw value (mantissa)
59 * The timestamp scale (magnitude)
64 * The value precision (tolerance)
66 private int fPrecision
;
68 // ------------------------------------------------------------------------
70 // ------------------------------------------------------------------------
75 public TmfTimestamp() {
80 * Simple constructor (scale = precision = 0)
82 * @param value the timestamp value
84 public TmfTimestamp(final long value
) {
89 * Simple constructor (precision = 0)
91 * @param value the timestamp value
92 * @param scale the timestamp scale
94 public TmfTimestamp(final long value
, final int scale
) {
95 this(value
, scale
, 0);
101 * @param value the timestamp value
102 * @param scale the timestamp scale
103 * @param precision the timestamp precision
105 public TmfTimestamp(final long value
, final int scale
, final int precision
) {
108 fPrecision
= Math
.abs(precision
);
114 * @param timestamp the timestamp to copy
116 public TmfTimestamp(final ITmfTimestamp timestamp
) {
117 if (timestamp
== null) {
118 throw new IllegalArgumentException();
120 fValue
= timestamp
.getValue();
121 fScale
= timestamp
.getScale();
122 fPrecision
= timestamp
.getPrecision();
125 // ------------------------------------------------------------------------
127 // ------------------------------------------------------------------------
129 protected void setValue(long value
, int scale
, int precision
) {
132 fPrecision
= precision
;
135 // ------------------------------------------------------------------------
137 // ------------------------------------------------------------------------
140 * @see org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp#getValue()
143 public long getValue() {
148 * @see org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp#getScale()
151 public int getScale() {
156 * @see org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp#getPrecision()
159 public int getPrecision() {
163 private static final long scalingFactors
[] = new long[] {
182 1000000000000000000L,
186 * @see org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp#normalize(long, int)
189 public ITmfTimestamp
normalize(final long offset
, final int scale
) {
192 int precision
= fPrecision
;
194 // Handle the trivial case
195 if (fScale
== scale
&& offset
== 0) {
196 return new TmfTimestamp(this);
199 // In case of big bang and big crunch just return this (no need to normalize)
200 if (this.equals(BIG_BANG
) || this.equals(BIG_CRUNCH
)) {
204 // First, scale the timestamp
205 if (fScale
!= scale
) {
206 final int scaleDiff
= Math
.abs(fScale
- scale
);
207 if (scaleDiff
>= scalingFactors
.length
) {
208 throw new ArithmeticException("Scaling exception"); //$NON-NLS-1$
211 final long scalingFactor
= scalingFactors
[scaleDiff
];
212 if (scale
< fScale
) {
213 value
*= scalingFactor
;
214 precision
*= scalingFactor
;
216 value
/= scalingFactor
;
217 precision
/= scalingFactor
;
221 // Then, apply the offset
223 value
= (value
< Long
.MIN_VALUE
- offset
) ? Long
.MIN_VALUE
: value
+ offset
;
225 value
= (value
> Long
.MAX_VALUE
- offset
) ? Long
.MAX_VALUE
: value
+ offset
;
228 return new TmfTimestamp(value
, scale
, precision
);
232 * @see org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp#compareTo(org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp, boolean)
235 public int compareTo(final ITmfTimestamp ts
, final boolean withinPrecision
) {
237 // Check the corner cases (we can't use equals() because it uses compareTo()...)
241 if (this == ts
|| (fValue
== ts
.getValue() && fScale
== ts
.getScale())) {
244 if ((fValue
== BIG_BANG
.getValue() && fScale
== BIG_BANG
.getScale()) || (ts
.getValue() == BIG_CRUNCH
.getValue() && ts
.getScale() == BIG_CRUNCH
.getScale())) {
247 if ((fValue
== BIG_CRUNCH
.getValue() && fScale
== BIG_CRUNCH
.getScale()) || (ts
.getValue() == BIG_BANG
.getValue() && ts
.getScale() == BIG_BANG
.getScale())) {
252 final ITmfTimestamp nts
= ts
.normalize(0, fScale
);
253 final long delta
= fValue
- nts
.getValue();
254 if ((delta
== 0) || (withinPrecision
&& (Math
.abs(delta
) <= (fPrecision
+ nts
.getPrecision())))) {
257 return (delta
> 0) ?
1 : -1;
259 catch (final ArithmeticException e
) {
260 // Scaling error. We can figure it out nonetheless.
262 // First, look at the sign of the mantissa
263 final long value
= ts
.getValue();
264 if (fValue
== 0 && value
== 0) {
267 if (fValue
< 0 && value
>= 0) {
270 if (fValue
>= 0 && value
< 0) {
274 // Otherwise, just compare the scales
275 final int scale
= ts
.getScale();
276 return (fScale
> scale
) ?
(fValue
>= 0) ?
1 : -1 : (fValue
>= 0) ?
-1 : 1;
281 * @see org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp#getDelta(org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp)
284 public ITmfTimestamp
getDelta(final ITmfTimestamp ts
) {
285 final ITmfTimestamp nts
= ts
.normalize(0, fScale
);
286 final long value
= fValue
- nts
.getValue();
287 return new TmfTimestamp(value
, fScale
, fPrecision
+ nts
.getPrecision());
290 // ------------------------------------------------------------------------
292 // ------------------------------------------------------------------------
295 * @see java.lang.Object#clone()
298 public TmfTimestamp
clone() {
299 TmfTimestamp clone
= null;
301 clone
= (TmfTimestamp
) super.clone();
302 clone
.fValue
= fValue
;
303 clone
.fScale
= fScale
;
304 clone
.fPrecision
= fPrecision
;
305 } catch (final CloneNotSupportedException e
) {
310 // ------------------------------------------------------------------------
312 // ------------------------------------------------------------------------
315 * @see org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp#compareTo(org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp)
318 public int compareTo(final ITmfTimestamp ts
) {
319 return compareTo(ts
, false);
322 // ------------------------------------------------------------------------
324 // ------------------------------------------------------------------------
327 * @see java.lang.Object#hashCode()
330 public int hashCode() {
331 final int prime
= 31;
333 result
= prime
* result
+ (int) (fValue ^
(fValue
>>> 32));
334 result
= prime
* result
+ fScale
;
335 result
= prime
* result
+ fPrecision
;
340 * @see java.lang.Object#equals(java.lang.Object)
343 public boolean equals(final Object other
) {
350 if (!(other
instanceof TmfTimestamp
)) {
353 final TmfTimestamp ts
= (TmfTimestamp
) other
;
354 return compareTo(ts
, false) == 0;
358 * @see java.lang.Object#toString()
361 @SuppressWarnings("nls")
362 public String
toString() {
363 return "TmfTimestamp [fValue=" + fValue
+ ", fScale=" + fScale
+ ", fPrecision=" + fPrecision
+ "]";