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
;
18 * A generic timestamp implementation. The timestamp is represented by the
19 * tuple { value, scale, precision }.
23 * @author Francois Chouinard
25 * @see TmfSimpleTimestamp
27 public class TmfTimestamp
implements ITmfTimestamp
, Cloneable
{
29 // ------------------------------------------------------------------------
31 // ------------------------------------------------------------------------
34 * The beginning of time
36 public static final ITmfTimestamp BIG_BANG
=
37 new TmfTimestamp(Long
.MIN_VALUE
, Integer
.MAX_VALUE
, 0);
42 public static final ITmfTimestamp BIG_CRUNCH
=
43 new TmfTimestamp(Long
.MAX_VALUE
, Integer
.MAX_VALUE
, 0);
48 public static final ITmfTimestamp ZERO
=
49 new TmfTimestamp(0, 0, 0);
51 // ------------------------------------------------------------------------
53 // ------------------------------------------------------------------------
56 * The timestamp raw value (mantissa)
61 * The timestamp scale (magnitude)
66 * The value precision (tolerance)
68 private int fPrecision
;
70 // ------------------------------------------------------------------------
72 // ------------------------------------------------------------------------
77 public TmfTimestamp() {
82 * Simple constructor (scale = precision = 0)
84 * @param value the timestamp value
86 public TmfTimestamp(final long value
) {
91 * Simple constructor (precision = 0)
93 * @param value the timestamp value
94 * @param scale the timestamp scale
96 public TmfTimestamp(final long value
, final int scale
) {
97 this(value
, scale
, 0);
103 * @param value the timestamp value
104 * @param scale the timestamp scale
105 * @param precision the timestamp precision
107 public TmfTimestamp(final long value
, final int scale
, final int precision
) {
110 fPrecision
= Math
.abs(precision
);
116 * @param timestamp the timestamp to copy
118 public TmfTimestamp(final ITmfTimestamp timestamp
) {
119 if (timestamp
== null) {
120 throw new IllegalArgumentException();
122 fValue
= timestamp
.getValue();
123 fScale
= timestamp
.getScale();
124 fPrecision
= timestamp
.getPrecision();
127 // ------------------------------------------------------------------------
129 // ------------------------------------------------------------------------
131 protected void setValue(long value
, int scale
, int precision
) {
134 fPrecision
= precision
;
137 // ------------------------------------------------------------------------
139 // ------------------------------------------------------------------------
142 * @see org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp#getValue()
145 public long getValue() {
150 * @see org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp#getScale()
153 public int getScale() {
158 * @see org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp#getPrecision()
161 public int getPrecision() {
165 private static final long scalingFactors
[] = new long[] {
184 1000000000000000000L,
188 * @see org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp#normalize(long, int)
191 public ITmfTimestamp
normalize(final long offset
, final int scale
) throws ArithmeticException
{
194 int precision
= fPrecision
;
196 // Handle the trivial case
197 if (fScale
== scale
&& offset
== 0) {
198 return new TmfTimestamp(this);
201 // First, scale the timestamp
202 if (fScale
!= scale
) {
203 final int scaleDiff
= Math
.abs(fScale
- scale
);
204 if (scaleDiff
>= scalingFactors
.length
) {
205 throw new ArithmeticException("Scaling exception"); //$NON-NLS-1$
208 final long scalingFactor
= scalingFactors
[scaleDiff
];
209 if (scale
< fScale
) {
210 value
*= scalingFactor
;
211 precision
*= scalingFactor
;
213 value
/= scalingFactor
;
214 precision
/= scalingFactor
;
218 // Then, apply the offset
220 value
= (value
< Long
.MIN_VALUE
- offset
) ? Long
.MIN_VALUE
: value
+ offset
;
222 value
= (value
> Long
.MAX_VALUE
- offset
) ? Long
.MAX_VALUE
: value
+ offset
;
225 return new TmfTimestamp(value
, scale
, precision
);
229 * @see org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp#compareTo(org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp, boolean)
232 public int compareTo(final ITmfTimestamp ts
, final boolean withinPrecision
) {
234 // Check the corner cases (we can't use equals() because it uses compareTo()...)
238 if (this == ts
|| (fValue
== ts
.getValue() && fScale
== ts
.getScale())) {
241 if ((fValue
== BIG_BANG
.getValue() && fScale
== BIG_BANG
.getScale()) || (ts
.getValue() == BIG_CRUNCH
.getValue() && ts
.getScale() == BIG_CRUNCH
.getScale())) {
244 if ((fValue
== BIG_CRUNCH
.getValue() && fScale
== BIG_CRUNCH
.getScale()) || (ts
.getValue() == BIG_BANG
.getValue() && ts
.getScale() == BIG_BANG
.getScale())) {
249 final ITmfTimestamp nts
= ts
.normalize(0, fScale
);
250 final long delta
= fValue
- nts
.getValue();
251 if ((delta
== 0) || (withinPrecision
&& (Math
.abs(delta
) <= (fPrecision
+ nts
.getPrecision())))) {
254 return (delta
> 0) ?
1 : -1;
256 catch (final ArithmeticException e
) {
257 // Scaling error. We can figure it out nonetheless.
259 // First, look at the sign of the mantissa
260 final long value
= ts
.getValue();
261 if (fValue
== 0 && value
== 0) {
264 if (fValue
< 0 && value
>= 0) {
267 if (fValue
>= 0 && value
< 0) {
271 // Otherwise, just compare the scales
272 final int scale
= ts
.getScale();
273 return (fScale
> scale
) ?
(fValue
>= 0) ?
1 : -1 : (fValue
>= 0) ?
-1 : 1;
278 * @see org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp#getDelta(org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp)
281 public ITmfTimestamp
getDelta(final ITmfTimestamp ts
) {
282 final ITmfTimestamp nts
= ts
.normalize(0, fScale
);
283 final long value
= fValue
- nts
.getValue();
284 return new TmfTimestamp(value
, fScale
, fPrecision
+ nts
.getPrecision());
287 // ------------------------------------------------------------------------
289 // ------------------------------------------------------------------------
292 * @see java.lang.Object#clone()
295 public TmfTimestamp
clone() {
296 TmfTimestamp clone
= null;
298 clone
= (TmfTimestamp
) super.clone();
299 clone
.fValue
= fValue
;
300 clone
.fScale
= fScale
;
301 clone
.fPrecision
= fPrecision
;
302 } catch (final CloneNotSupportedException e
) {
307 // ------------------------------------------------------------------------
309 // ------------------------------------------------------------------------
312 * @see org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp#compareTo(org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp)
315 public int compareTo(final ITmfTimestamp ts
) {
316 return compareTo(ts
, false);
319 // ------------------------------------------------------------------------
321 // ------------------------------------------------------------------------
324 * @see java.lang.Object#hashCode()
327 public int hashCode() {
328 final int prime
= 31;
330 result
= prime
* result
+ (int) (fValue ^
(fValue
>>> 32));
331 result
= prime
* result
+ fScale
;
332 result
= prime
* result
+ fPrecision
;
337 * @see java.lang.Object#equals(java.lang.Object)
340 public boolean equals(final Object other
) {
347 if (!(other
instanceof TmfTimestamp
)) {
350 final TmfTimestamp ts
= (TmfTimestamp
) other
;
351 return compareTo(ts
, false) == 0;
355 * @see java.lang.Object#toString()
358 @SuppressWarnings("nls")
359 public String
toString() {
360 return "TmfTimestamp [fValue=" + fValue
+ ", fScale=" + fScale
+ ", fPrecision=" + fPrecision
+ "]";