/******************************************************************************* * Copyright (c) 2010, 2014 Willink Transformations and others. * 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: * E.D.Willink - Initial API and implementation *******************************************************************************/ package org.eclipse.ocl.pivot.internal.values; import java.math.BigDecimal; import java.math.BigInteger; import java.math.RoundingMode; import org.eclipse.emf.ecore.EClass; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.ocl.pivot.StandardLibrary; import org.eclipse.ocl.pivot.Type; import org.eclipse.ocl.pivot.ids.IdResolver; import org.eclipse.ocl.pivot.ids.TypeId; import org.eclipse.ocl.pivot.messages.PivotMessages; import org.eclipse.ocl.pivot.utilities.ValueUtil; import org.eclipse.ocl.pivot.values.ComparableValue; import org.eclipse.ocl.pivot.values.IntegerValue; import org.eclipse.ocl.pivot.values.InvalidValueException; import org.eclipse.ocl.pivot.values.NumberValue; import org.eclipse.ocl.pivot.values.RealValue; import org.eclipse.ocl.pivot.values.UnlimitedNaturalValue; import org.eclipse.ocl.pivot.values.ValuesPackage; /** * @generated NOT */ public class RealValueImpl extends NumberValueImpl implements RealValue { private static final long serialVersionUID = -6016171050097266652L; /** * <!-- begin-user-doc --> * <!-- end-user-doc --> * @generated */ @Override protected EClass eStaticClass() { return ValuesPackage.Literals.REAL_VALUE; } private static final int MINIMUM_SCALE = Double.SIZE/2; // Gives nearly twice the precision of Double protected static @NonNull RealValue divideBigDecimal(@NonNull BigDecimal left, @NonNull BigDecimal right) { try { if (right.signum() == 0) { throw new InvalidValueException("divide by zero"); } int scale = Math.max(left.scale() - right.scale(), MINIMUM_SCALE); @SuppressWarnings("null") @NonNull BigDecimal result = left.divide(right, scale, RoundingMode.HALF_EVEN); return ValueUtil.realValueOf(result); } catch (ArithmeticException e) { throw new InvalidValueException(e, "divideBigDecimal"); } } /** * A simple public static method that may be used to force class initialization. */ public static void initStatics() {} private final @NonNull BigDecimal value; private Object integerValue = null; // Lazily computed exact IntegerValue or Exception @SuppressWarnings("null") public RealValueImpl(double value) { this(BigDecimal.valueOf(value)); } public RealValueImpl(@NonNull BigDecimal value) { this.value = value; assert value != null; } @Override public @NonNull RealValue abs() { @SuppressWarnings("null") @NonNull BigDecimal result = value.abs(); return ValueUtil.realValueOf(result); } @Override public @NonNull RealValue addInteger(@NonNull IntegerValue rightValue) { try { @SuppressWarnings("null") @NonNull BigDecimal result = value.add(rightValue.bigDecimalValue()); return ValueUtil.realValueOf(result); } catch (InvalidValueException e) { throw new InvalidValueException(PivotMessages.InvalidReal, e, null, rightValue); } } @Override public @NonNull RealValue addReal(@NonNull RealValue rightValue) { try { @SuppressWarnings("null") @NonNull BigDecimal result = value.add(rightValue.bigDecimalValue()); return ValueUtil.realValueOf(result); } catch (InvalidValueException e) { throw new InvalidValueException(PivotMessages.InvalidReal, e, null, rightValue); } } @Override public @NonNull Double asDouble() { return value.doubleValue(); } @Override public Object asEcoreObject(@NonNull IdResolver idResolver, @Nullable Class<?> instanceClass) { if (instanceClass == BigDecimal.class) { return value; } else { Object ecoreValue = super.asEcoreObject(idResolver, instanceClass); return ecoreValue != null ? ecoreValue : doubleValue(); } } @Override public @NonNull Number asNumber() { return value; } @Override public @NonNull Object asObject() { return value; } @Override public @NonNull RealValue asRealValue() { return this; } @Override public @NonNull Object asUnboxedObject(@NonNull IdResolver idResolver) { return value; } @Override public @NonNull BigDecimal bigDecimalValue() { return value; } @Override public @NonNull BigInteger bigIntegerValue() { Object intValue = getIntegerValue(); if (intValue instanceof Exception) { throw new InvalidValueException((Exception) intValue, "bigIntegerValue"); } else { return ((IntegerValue) intValue).bigIntegerValue(); } } @Override public @NonNull RealValue commutatedAdd(@NonNull RealValue left) { return left.addReal(this); } @Override public int commutatedCompareTo(@NonNull ComparableValue<?> left) { if (left instanceof NumberValue) { return ((NumberValue)left).commutatedCompareToReal(this); } else { return ValueUtil.throwUnsupportedCompareTo(left, this); } } @Override public int commutatedCompareToInteger(@NonNull IntegerValue left) { return value.compareTo(left.bigDecimalValue()); } @Override public int commutatedCompareToReal(@NonNull RealValue left) { return value.compareTo(left.bigDecimalValue()); } @Override public @NonNull RealValue commutatedDivide(@NonNull RealValue left) { return left.divideReal(this); } @Override public @NonNull RealValue commutatedMultiply(@NonNull RealValue left) { return left.multiplyReal(this); } @Override public @NonNull RealValue commutatedSubtract(@NonNull RealValue left) { return left.subtractReal(this); } @Override public int compareTo(@Nullable NumberValue right) { if (right != null) { return -right.commutatedCompareToReal(this); } else { return ValueUtil.throwUnsupportedCompareTo(this, right); } } @Override public @NonNull RealValue divideInteger(@NonNull IntegerValue right) { return divideBigDecimal(value, right.bigDecimalValue()); } @Override public @NonNull RealValue divideReal(@NonNull RealValue right) { return divideBigDecimal(value, right.bigDecimalValue()); } @Override public double doubleValue() { return value.doubleValue(); } @Override public boolean equals(Object obj) { try { if (obj instanceof RealValue) { BigDecimal bigDecimalValue = ((RealValue)obj).bigDecimalValue(); return value.compareTo(bigDecimalValue) == 0; } if (obj instanceof IntegerValue) { BigDecimal bigDecimalValue = ((IntegerValue)obj).bigDecimalValue(); return value.compareTo(bigDecimalValue) == 0; } } catch (InvalidValueException e) { } return this == obj; } @Override public float floatValue() { return value.floatValue(); } @Override public @NonNull IntegerValue floor() { @SuppressWarnings("null") @NonNull BigInteger result = value.setScale(0, RoundingMode.FLOOR).toBigInteger(); return ValueUtil.integerValueOf(result); } protected Object getIntegerValue() { if (integerValue == null) { try { @SuppressWarnings("null") @NonNull BigInteger intValue = value.toBigIntegerExact(); integerValue = ValueUtil.integerValueOf(intValue); } catch (ArithmeticException e) { integerValue = e; } } return integerValue; } public @NonNull Type getType(@NonNull StandardLibrary standardLibrary) { return standardLibrary.getRealType(); } @Override public @NonNull TypeId getTypeId() { return TypeId.REAL; } @Override public int hashCode() { Object intValue = getIntegerValue(); if (intValue instanceof IntegerValue) { return intValue.hashCode(); } else { return value.hashCode(); } } @Override public int intValue() { return value.intValue(); } @Override public @Nullable IntegerValue isIntegerValue() { return null; } @Override public @Nullable UnlimitedNaturalValue isUnlimitedNaturalValue() { return null; } @Override public long longValue() { return value.longValue(); } @Override public @NonNull RealValue max(@NonNull RealValue rightValue) { return rightValue.maxReal(this); } @Override public @NonNull RealValue maxInteger(@NonNull IntegerValue rightValue) { try { @SuppressWarnings("null") @NonNull BigDecimal result = value.max(rightValue.bigDecimalValue()); return ValueUtil.realValueOf(result); } catch (InvalidValueException e) { throw new InvalidValueException(PivotMessages.InvalidReal, e, null, rightValue); } } @Override public @NonNull RealValue maxReal(@NonNull RealValue rightValue) { try { @SuppressWarnings("null") @NonNull BigDecimal result = value.max(rightValue.bigDecimalValue()); return ValueUtil.realValueOf(result); } catch (InvalidValueException e) { throw new InvalidValueException(PivotMessages.InvalidReal, e, null, rightValue); } } @Override public @NonNull RealValue min(@NonNull RealValue rightValue) { return rightValue.minReal(this); } @Override public @NonNull RealValue minInteger(@NonNull IntegerValue rightValue) { try { @SuppressWarnings("null") @NonNull BigDecimal result = value.min(rightValue.bigDecimalValue()); return ValueUtil.realValueOf(result); } catch (InvalidValueException e) { throw new InvalidValueException(PivotMessages.InvalidReal, e, null, rightValue); } } @Override public @NonNull RealValue minReal(@NonNull RealValue rightValue) { try { @SuppressWarnings("null") @NonNull BigDecimal result = value.min(rightValue.bigDecimalValue()); return ValueUtil.realValueOf(result); } catch (InvalidValueException e) { throw new InvalidValueException(PivotMessages.InvalidReal, e, null, rightValue); } } @Override public @NonNull RealValue multiplyInteger(@NonNull IntegerValue rightValue) { try { @SuppressWarnings("null") @NonNull BigDecimal result = value.multiply(rightValue.bigDecimalValue()); return ValueUtil.realValueOf(result); } catch (InvalidValueException e) { throw new InvalidValueException(PivotMessages.InvalidReal, e, null, rightValue); } } @Override public @NonNull RealValue multiplyReal(@NonNull RealValue rightValue) { try { @SuppressWarnings("null") @NonNull BigDecimal result = value.multiply(rightValue.bigDecimalValue()); return ValueUtil.realValueOf(result); } catch (InvalidValueException e) { throw new InvalidValueException(PivotMessages.InvalidReal, e, null, rightValue); } } @Override public @NonNull RealValue negate() { @SuppressWarnings("null") @NonNull BigDecimal result = value.negate(); return ValueUtil.realValueOf(result); } @Override public @NonNull IntegerValue round() { BigDecimal rounded; if (value.signum() >= 0) { rounded = value.setScale(0, RoundingMode.HALF_UP); // functions as HALF_AWAY } else { rounded = value.negate().setScale(0, RoundingMode.HALF_DOWN).negate(); } @SuppressWarnings("null") @NonNull BigInteger result = rounded.toBigInteger(); return ValueUtil.integerValueOf(result); } @Override public int signum() { return value.signum(); } @Override public @NonNull RealValue subtractInteger(@NonNull IntegerValue rightValue) { try { @SuppressWarnings("null") @NonNull BigDecimal result = value.subtract(rightValue.bigDecimalValue()); return ValueUtil.realValueOf(result); } catch (InvalidValueException e) { throw new InvalidValueException(PivotMessages.InvalidReal, e, null, rightValue); } } @Override public @NonNull RealValue subtractReal(@NonNull RealValue rightValue) { try { @SuppressWarnings("null") @NonNull BigDecimal result = value.subtract(rightValue.bigDecimalValue()); return ValueUtil.realValueOf(result); } catch (InvalidValueException e) { throw new InvalidValueException(PivotMessages.InvalidReal, e, null, rightValue); } } @Override public String toString() { return value.toString(); } }