/******************************************************************************* * Copyright (c) 2013, 2014 École Polytechnique de Montréal * * All rights reserved. This program and the accompanying materials are made * available under the terms of the Eclipse Public License v1.0 which * accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Geneviève Bastien - Initial implementation and API *******************************************************************************/ package org.eclipse.tracecompass.internal.tmf.core.synchronization; import java.math.BigDecimal; import java.math.MathContext; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.tracecompass.common.core.NonNullUtils; import org.eclipse.tracecompass.tmf.core.synchronization.ITmfTimestampTransform; import org.eclipse.tracecompass.tmf.core.synchronization.TimestampTransformFactory; import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimestamp; import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestamp; /** * Class implementing a linear timestamp transform, with a slope and/or offset * * f(t) = alpha*t + beta * * @author Geneviève Bastien */ public class TmfTimestampTransformLinear implements ITmfTimestampTransformInvertible { /** * Generated serial UID */ private static final long serialVersionUID = -4756608071358979461L; /** * Respectively the slope and offset and this linear equation. */ private final @NonNull BigDecimal fAlpha; private final @NonNull BigDecimal fBeta; private static final MathContext fMc = MathContext.DECIMAL128; /** * Default constructor */ public TmfTimestampTransformLinear() { fAlpha = BigDecimal.ONE; fBeta = BigDecimal.ZERO; } /** * Constructor with alpha and beta * * @param alpha * The slope of the linear transform * @param beta * The initial offset of the linear transform */ public TmfTimestampTransformLinear(final double alpha, final double beta) { fAlpha = BigDecimal.valueOf(alpha); fBeta = BigDecimal.valueOf(beta); } /** * Constructor with alpha and beta in big decimal * * @param fAlpha2 * The slope of the linear transform * @param fBeta2 * The initial offset of the linear transform */ public TmfTimestampTransformLinear(final BigDecimal fAlpha2, final BigDecimal fBeta2) { if (fAlpha2 != null) { fAlpha = fAlpha2; } else { fAlpha = BigDecimal.ONE; } if (fBeta2 != null) { fBeta = fBeta2; } else { fBeta = BigDecimal.ZERO; } } @Override public ITmfTimestamp transform(ITmfTimestamp timestamp) { BigDecimal newvalue = BigDecimal.valueOf(timestamp.getValue()).multiply(fAlpha, fMc).add(fBeta); return TmfTimestamp.create(newvalue.longValue(), timestamp.getScale()); } @Override public long transform(long timestamp) { BigDecimal t = BigDecimal.valueOf(timestamp).multiply(fAlpha, fMc).add(fBeta); return t.longValue(); } @Override public ITmfTimestampTransform composeWith(ITmfTimestampTransform composeWith) { if (composeWith.equals(TmfTimestampTransform.IDENTITY)) { /* If composing with identity, just return this */ return this; } else if (composeWith instanceof TmfTimestampTransformLinear) { /* If composeWith is a linear transform, add the two together */ TmfTimestampTransformLinear ttl = (TmfTimestampTransformLinear) composeWith; BigDecimal newAlpha = fAlpha.multiply(ttl.fAlpha, fMc); BigDecimal newBeta = fAlpha.multiply(ttl.fBeta, fMc).add(fBeta); /* Don't use the factory to make sure any further composition will * be performed on the same object type */ return new TmfTimestampTransformLinear(newAlpha, newBeta); } else { /* * We do not know what to do with this kind of transform, just * return this */ return this; } } @Override public boolean equals(Object other) { boolean result = false; if (other instanceof TmfTimestampTransformLinear) { TmfTimestampTransformLinear that = (TmfTimestampTransformLinear) other; result = ((that.fAlpha.equals(fAlpha)) && (that.fBeta.equals(fBeta))); } return result; } @Override public int hashCode() { final int prime = 31; int result = 1; result = (prime * result) + (fBeta.multiply(fAlpha).intValue()); return result; } @Override public String toString() { return "TmfTimestampLinear [ slope = " + fAlpha.toString() + //$NON-NLS-1$ ", offset = " + fBeta.toString() + //$NON-NLS-1$ " ]"; //$NON-NLS-1$ } @Override public ITmfTimestampTransform inverse() { return TimestampTransformFactory.createLinear(NonNullUtils.checkNotNull(BigDecimal.ONE.divide(fAlpha, fMc)), NonNullUtils.checkNotNull(BigDecimal.valueOf(-1).multiply(fBeta).divide(fAlpha, fMc))); } /** * @return the slope alpha */ public BigDecimal getAlpha() { return fAlpha; } /** * @return the offset beta */ public BigDecimal getBeta() { return fBeta; } }