package data;

import java.io.Serializable;

/**
  * An objectified value.
  *
  * <p>Values are objects that understand the four basic operations <code>add</code>, <code>subtract</code>,
  * <code>multiply</code> and <code>divide</code>. Additionally, they have an operation for multiplication with
  * 'scalars', i.e. simple type numeric values. Values are commutative monoids with respect to addition and
  * multiplication.</p>
  *
  * <p>An ordering relation is defined on the values, but it is up to the concrete type of value, whether this
  * ordering is a half ordering relation.</p>
  *
  * @author Steffen Zschaler
  * @version 2.0 19/08/1999
  * @since v2.0
  */
public interface Value extends Cloneable,
                               Comparable,
                               Serializable {

  /**
    * Add the given value to this one, changing this value.
    *
    * @override Always
    *
    * @param v the value to be added.
    */
  public void addAccumulating (Value v);

  /**
    * Subtract the given value from this one, changing this value.
    *
    * @override Always
    *
    * @param v the value to be subtracted.
    */
  public void subtractAccumulating (Value v);

  /**
    * Multiply the given value by this one, changing this value.
    *
    * @override Always
    *
    * @param v the value to be multplied by.
    */
  public void multiplyAccumulating (Value v);

  /**
    * Multiply this value by the given 'scalar', changing this value.
    *
    * @override Always
    *
    * @param dl the value by which to multiply.
    */
  public void multiplyAccumulating (double dl);

  /**
    * Multiply this value by the given 'scalar', changing this value.
    *
    * @override Always
    *
    * @param fl the value by which to multiply.
    */
  public void multiplyAccumulating (float fl);

  /**
    * Multiply this value by the given 'scalar', changing this value.
    *
    * @override Always
    *
    * @param l the value by which to multiply.
    */
  public void multiplyAccumulating (long l);

  /**
    * Multiply this value by the given 'scalar', changing this value.
    *
    * @override Always
    *
    * @param n the value by which to multiply.
    */
  public void multiplyAccumulating (int n);

  /**
    * Divide this value by the given one, changing this value.
    *
    * @override Always
    *
    * @param v the value by which to divide.
    */
  public void divideAccumulating (Value v);

  /**
    * Add the given value to this one, and return the result.
    *
    * @override Always
    *
    * @param v the value to be added.
    */
  public Value add (Value v);

  /**
    * Subtract the given value from this one, and return the result.
    *
    * @override Always
    *
    * @param v the value to be subtracted.
    */
  public Value subtract (Value v);

  /**
    * Multiply this value by the given one, and return the result.
    *
    * @override Always
    *
    * @param v the value by which to multiply.
    */
  public Value multiply (Value v);

  /**
    * Multiply this value by the given 'scalar', and return the result.
    *
    * @override Always
    *
    * @param dl the 'scalar' by which to multiply.
    */
  public Value multiply (double dl);

  /**
    * Multiply this value by the given 'scalar', and return the result.
    *
    * @override Always
    *
    * @param fl the 'scalar' by which to multiply.
    */
  public Value multiply (float fl);

  /**
    * Multiply this value by the given 'scalar', and return the result.
    *
    * @override Always
    *
    * @param l the 'scalar' by which to multiply.
    */
  public Value multiply (long l);

  /**
    * Multiply this value by the given 'scalar', and return the result.
    *
    * @override Always
    *
    * @param n the 'scalar' by which to multiply.
    */
  public Value multiply (int n);

  /**
    * Divide this value by the given one, and return the result.
    *
    * @override Always
    *
    * @param v the value by which to divide.
    */
  public Value divide (Value v);

  /**
    * Check whether this is the zero element with respect to addition.
    *
    * @override Always
    *
    * @return true if this is the zero element with respect to addition, i.e. if for any value <code>v</code>:
    * <code>(v.getClass() == this.getClass()) -> ((v.add (this).equals (v)) && (this.add (v).equals (v)))</code>.
    */
  public boolean isAddZero();

  /**
    * Check whether this is the zero element with respect to multiplication.
    *
    * @override Always
    *
    * @return true if this is the zero element with respect to multiplication, i.e. if for any value <code>v</code>:
    * <code>(v.getClass() == this.getClass()) -> ((v.multiply (this).equals (this)) && (this.multiply (v).equals (this)))</code>.
    */
  public boolean isMulZero();

  /**
    * Check whether this is the one element with respect to multiplication.
    *
    * @override Always
    *
    * @return true if this is the one element with respect to multiplication, i.e. if for any value <code>v</code>:
    * <code>(v.getClass() == this.getClass()) -> ((v.multiply (this).equals (v)) && (this.multiply (v).equals (v)))</code>.
    */
  public boolean isMulOne();

  /**
    * Clone this value.
    *
    * @override Always
    */
  public Object clone();
}