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 // First, scale the timestamp
200 if (fScale
!= scale
) {
201 final int scaleDiff
= Math
.abs(fScale
- scale
);
202 if (scaleDiff
>= scalingFactors
.length
) {
203 throw new ArithmeticException("Scaling exception"); //$NON-NLS-1$
206 final long scalingFactor
= scalingFactors
[scaleDiff
];
207 if (scale
< fScale
) {
208 value
*= scalingFactor
;
209 precision
*= scalingFactor
;
211 value
/= scalingFactor
;
212 precision
/= scalingFactor
;
216 // Then, apply the offset
218 value
= (value
< Long
.MIN_VALUE
- offset
) ? Long
.MIN_VALUE
: value
+ offset
;
220 value
= (value
> Long
.MAX_VALUE
- offset
) ? Long
.MAX_VALUE
: value
+ offset
;
223 return new TmfTimestamp(value
, scale
, precision
);
227 * @see org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp#compareTo(org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp, boolean)
230 public int compareTo(final ITmfTimestamp ts
, final boolean withinPrecision
) {
232 // Check the corner cases (we can't use equals() because it uses compareTo()...)
236 if (this == ts
|| (fValue
== ts
.getValue() && fScale
== ts
.getScale())) {
239 if ((fValue
== BIG_BANG
.getValue() && fScale
== BIG_BANG
.getScale()) || (ts
.getValue() == BIG_CRUNCH
.getValue() && ts
.getScale() == BIG_CRUNCH
.getScale())) {
242 if ((fValue
== BIG_CRUNCH
.getValue() && fScale
== BIG_CRUNCH
.getScale()) || (ts
.getValue() == BIG_BANG
.getValue() && ts
.getScale() == BIG_BANG
.getScale())) {
247 final ITmfTimestamp nts
= ts
.normalize(0, fScale
);
248 final long delta
= fValue
- nts
.getValue();
249 if ((delta
== 0) || (withinPrecision
&& (Math
.abs(delta
) <= (fPrecision
+ nts
.getPrecision())))) {
252 return (delta
> 0) ?
1 : -1;
254 catch (final ArithmeticException e
) {
255 // Scaling error. We can figure it out nonetheless.
257 // First, look at the sign of the mantissa
258 final long value
= ts
.getValue();
259 if (fValue
== 0 && value
== 0) {
262 if (fValue
< 0 && value
>= 0) {
265 if (fValue
>= 0 && value
< 0) {
269 // Otherwise, just compare the scales
270 final int scale
= ts
.getScale();
271 return (fScale
> scale
) ?
(fValue
>= 0) ?
1 : -1 : (fValue
>= 0) ?
-1 : 1;
276 * @see org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp#getDelta(org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp)
279 public ITmfTimestamp
getDelta(final ITmfTimestamp ts
) {
280 final ITmfTimestamp nts
= ts
.normalize(0, fScale
);
281 final long value
= fValue
- nts
.getValue();
282 return new TmfTimestamp(value
, fScale
, fPrecision
+ nts
.getPrecision());
285 // ------------------------------------------------------------------------
287 // ------------------------------------------------------------------------
290 * @see java.lang.Object#clone()
293 public TmfTimestamp
clone() {
294 TmfTimestamp clone
= null;
296 clone
= (TmfTimestamp
) super.clone();
297 clone
.fValue
= fValue
;
298 clone
.fScale
= fScale
;
299 clone
.fPrecision
= fPrecision
;
300 } catch (final CloneNotSupportedException e
) {
305 // ------------------------------------------------------------------------
307 // ------------------------------------------------------------------------
310 * @see org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp#compareTo(org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp)
313 public int compareTo(final ITmfTimestamp ts
) {
314 return compareTo(ts
, false);
317 // ------------------------------------------------------------------------
319 // ------------------------------------------------------------------------
322 * @see java.lang.Object#hashCode()
325 public int hashCode() {
326 final int prime
= 31;
328 result
= prime
* result
+ (int) (fValue ^
(fValue
>>> 32));
329 result
= prime
* result
+ fScale
;
330 result
= prime
* result
+ fPrecision
;
335 * @see java.lang.Object#equals(java.lang.Object)
338 public boolean equals(final Object other
) {
345 if (!(other
instanceof TmfTimestamp
)) {
348 final TmfTimestamp ts
= (TmfTimestamp
) other
;
349 return compareTo(ts
, false) == 0;
353 * @see java.lang.Object#toString()
356 @SuppressWarnings("nls")
357 public String
toString() {
358 return "TmfTimestamp [fValue=" + fValue
+ ", fScale=" + fScale
+ ", fPrecision=" + fPrecision
+ "]";