Fixed.java

/**
* Copyright 2010,2021 Nikolas S Boyd.
Permission is granted to copy this work provided this copyright statement is retained in all copies.

*/
package Hoot.Magnitudes;

import Hoot.Runtime.Functions.*;
import Hoot.Runtime.Faces.*;
import Hoot.Runtime.Values.*;
import Hoot.Runtime.Blocks.*;
import Smalltalk.Core.*;
import Smalltalk.Blocks.*;
import Smalltalk.Magnitudes.*;
import Hoot.Behaviors.*;
import Hoot.Behaviors.Nil;
import Hoot.Behaviors.Object;
import Hoot.Behaviors.True;
import Hoot.Behaviors.False;
import Hoot.Behaviors.Boolean;
import Hoot.Collections.*;
import Hoot.Collections.String;
import java.math.BigDecimal;
import Smalltalk.Magnitudes.*;
import Smalltalk.Streams.StreamedSink;
import Hoot.Runtime.Names.Primitive;

public class Fixed extends Rational implements Fractional, ScaledDecimal
{

  public static Metaclass type() { return (Metaclass)Metaclass.$class; }
  @Override public Metaclass $class() { return (Metaclass)Metaclass.$class; }
  public static class Metaclass extends Rational.Metaclass implements Fractional.Metatype, ScaledDecimal.Metatype
  {
    static final Fixed.Metaclass $class = new Fixed.Metaclass();
    public Metaclass() {
      this(Fixed.Metaclass.class);
    }

    public Metaclass(java.lang.Class aClass) {
      super(aClass);
    }

    @Override public java.lang.Class outerClass() { return Fixed.class; }


    /**
     * @return 
     */
    public   Character exponentCharacter()
    {
      java.lang.String exitID = "FixedMetatype>>exponentCharacter";
      Frame f0 = new Frame(exitID);
      return f0.evaluate(() -> {
      return (Character)f0.exit(exitID, ((Character)Character.from('s')));
      });
    }

    /**
     * @return 
     */
    public   Fixed numerator_denominator(final Number upper, final Number lower)
    {
      java.lang.String exitID = "FixedMetatype>>numerator_denominator";
      Frame f0 = new Frame(exitID);
      return f0.evaluate(() -> {
      return (Fixed)f0.exit(exitID, Fraction.type().numerator_denominator(upper.asInteger(), lower.asInteger()).scaledZero());
      });
    }

    /**
     * @return 
     */
    public   Fixed numerator_denominator(final Ordinal upper, final Ordinal lower)
    {
      java.lang.String exitID = "FixedMetatype>>numerator_denominator";
      Frame f0 = new Frame(exitID);
      return f0.evaluate(() -> {
      return (Fixed)f0.exit(exitID, Fraction.type().numerator_denominator(upper, lower).scaledZero());
      });
    }

    /**
     * @return 
     */
    public   Fixed numerator_denominator_scale(final Number upper, final Number lower, final Number scale)
    {
      java.lang.String exitID = "FixedMetatype>>numerator_denominator_scale";
      Frame f0 = new Frame(exitID);
      return f0.evaluate(() -> {
      return (Fixed)f0.exit(exitID, Fraction.type().numerator_denominator(upper.asInteger(), lower.asInteger()).scaledAt(scale.asInteger()));
      });
    }
  }


  protected static SmallInteger Generality = SmallInteger.from(50);
  protected Integer scale = SmallInteger.from(0);
  protected Integer numerator = SmallInteger.from(0);
  protected Integer denominator = SmallInteger.from(1);

  /**
   * 
   */
  public    Fixed()
  {
    this(SmallInteger.from(0), SmallInteger.from(1));
    java.lang.String exitID = "Fixed>>Fixed";
    Frame f0 = new Frame(exitID);
  }

  /**
   * 
   */
  public    Fixed(final Integer upper, final Integer lower)
  {
    java.lang.String exitID = "Fixed>>Fixed";
    Frame f0 = new Frame(exitID);
     numerator = upper;

     denominator = lower;
  }

  /**
   * 
   */
  public    Fixed(final Integer upper, final Integer lower, final Integer s)
  {
    this(upper, lower);
    java.lang.String exitID = "Fixed>>Fixed";
    Frame f0 = new Frame(exitID);
     scale = s;
  }

  /**
   * @return 
   */
  public static   Fixed from(final java.lang.String value)
  {
    java.lang.String exitID = "Fixed>>$from";
    Frame f0 = new Frame(exitID);
    Long [] parts = Primitive.parseDecimal(value);
    return (Fixed)new Fixed(LongInteger.from(parts[0]), LongInteger.from(parts[1]), LongInteger.from(parts[2]));
  }

  /**
   * @return 
   */
  public   Integer scale()
  {
    java.lang.String exitID = "Fixed>>scale";
    Frame f0 = new Frame(exitID);
    return (Integer)scale;
  }

  /**
   * @return 
   */
  @Override public   Integer numerator()
  {
    java.lang.String exitID = "Fixed>>numerator";
    Frame f0 = new Frame(exitID);
    return (Integer)numerator;
  }

  /**
   * @return 
   */
  @Override public   Integer denominator()
  {
    java.lang.String exitID = "Fixed>>denominator";
    Frame f0 = new Frame(exitID);
    return (Integer)denominator;
  }

  /**
   * @return 
   */
  public   Fixed scaledAt(final Integer otherScale)
  {
    java.lang.String exitID = "Fixed>>scaledAt";
    Frame f0 = new Frame(exitID);
    return (Fixed)new Fixed(numerator, denominator, otherScale);
  }

  /**
   * @return 
   */
  @Override public   byte primitiveByte()
  {
    java.lang.String exitID = "Fixed>>primitiveByte";
    Frame f0 = new Frame(exitID);
    return (byte)((byte)this.primitiveLong());
  }

  /**
   * @return 
   */
  @Override public   short primitiveShort()
  {
    java.lang.String exitID = "Fixed>>primitiveShort";
    Frame f0 = new Frame(exitID);
    return (short)((short)this.primitiveLong());
  }

  /**
   * @return 
   */
  @Override public   char primitiveCharacter()
  {
    java.lang.String exitID = "Fixed>>primitiveCharacter";
    Frame f0 = new Frame(exitID);
    return (char)((char)this.primitiveLong());
  }

  /**
   * @return 
   */
  @Override public   int primitiveInteger()
  {
    java.lang.String exitID = "Fixed>>primitiveInteger";
    Frame f0 = new Frame(exitID);
    return (int)((int)this.primitiveLong());
  }

  /**
   * @return 
   */
  @Override public   long primitiveLong()
  {
    java.lang.String exitID = "Fixed>>primitiveLong";
    Frame f0 = new Frame(exitID);
    return (long)(Boolean.primitiveValue(this.lessThan(SmallInteger.Zero)) ? ((long)java.lang.Math.ceil(this.primitiveDouble())) : ((long)java.lang.Math.floor(this.primitiveDouble())));
  }

  /**
   * @return 
   */
  @Override public   java.lang.Float primitiveFloat()
  {
    java.lang.String exitID = "Fixed>>primitiveFloat";
    Frame f0 = new Frame(exitID);
    return (java.lang.Float)(numerator.primitiveFloat() / denominator.primitiveFloat());
  }

  /**
   * @return 
   */
  @Override public   java.lang.Double primitiveDouble()
  {
    java.lang.String exitID = "Fixed>>primitiveDouble";
    Frame f0 = new Frame(exitID);
    return (java.lang.Double)(numerator.primitiveDouble() / denominator.primitiveDouble());
  }

  /**
   * @return 
   */
  @Override public   java.lang.Number elementaryNumber()
  {
    java.lang.String exitID = "Fixed>>elementaryNumber";
    Frame f0 = new Frame(exitID);
    return (java.lang.Number)this.primitiveDouble();
  }

  /**
   * @return 
   */
  @Override public   Fraction asFraction()
  {
    java.lang.String exitID = "Fixed>>asFraction";
    Frame f0 = new Frame(exitID);
    return (Fraction)new Fraction(numerator.asSmallInteger(), denominator.asSmallInteger());
  }

  /**
   * @return 
   */
  public   BigDecimal asDecimal(final Integer scale)
  {
    java.lang.String exitID = "Fixed>>asDecimal";
    Frame f0 = new Frame(exitID);
    return (BigDecimal)Primitive.decimalFrom(numerator.primitiveLong(), denominator.primitiveLong(), scale.intValue());
  }

  /**
   * @return 
   */
  @Override public   BigDecimal asDecimal()
  {
    java.lang.String exitID = "Fixed>>asDecimal";
    Frame f0 = new Frame(exitID);
    int n = numerator.printString().length();

    int d = denominator.printString().length();
    return (BigDecimal)this.asDecimal(scale);
  }

  /**
   * @return 
   */
  @Override public   Integer generality()
  {
    java.lang.String exitID = "Fixed>>generality";
    Frame f0 = new Frame(exitID);
    return (Integer)Generality;
  }

  /**
   * @return 
   */
  @Override public   SmallInteger ceiling()
  {
    java.lang.String exitID = "Fixed>>ceiling";
    Frame f0 = new Frame(exitID);
    return (SmallInteger)SmallInteger.from(((int)java.lang.Math.ceil(this.primitiveDouble())));
  }

  /**
   * @return 
   */
  @Override public   SmallInteger floor()
  {
    java.lang.String exitID = "Fixed>>floor";
    Frame f0 = new Frame(exitID);
    return (SmallInteger)SmallInteger.from(((int)java.lang.Math.floor(this.primitiveDouble())));
  }

  /**
   * @return 
   */
  public   Fixed plus(final Fixed aFixed)
  {
    java.lang.String exitID = "Fixed>>plus";
    Frame f0 = new Frame(exitID);
    return f0.evaluate(() -> {
    (denominator.equals(aFixed.denominator())).ifTrue(Closure.with(f2 -> {
      return (Fixed)f0.exit(exitID, this.$class().numerator_denominator_scale((numerator.plus(aFixed.numerator())), denominator, ((Number)scale.max(aFixed.scale()))));
    }, ""));
    return (Fixed)f0.exit(exitID, this.$class().numerator_denominator_scale(this.crossSum(aFixed), this.underProduct(aFixed), ((Number)scale.max(aFixed.scale()))));
    });
  }

  /**
   * @return 
   */
  public   Fixed times(final Fixed aFixed)
  {
    java.lang.String exitID = "Fixed>>times";
    Frame f0 = new Frame(exitID);
    return (Fixed)this.$class().numerator_denominator_scale(this.overProduct(aFixed), this.underProduct(aFixed), ((Number)scale.max(aFixed.scale())));
  }

  /**
   * @return 
   */
  public   Fixed divideWith(final Fixed aFixed)
  {
    java.lang.String exitID = "Fixed>>divideWith";
    Frame f0 = new Frame(exitID);
    return (Fixed)this.$class().numerator_denominator_scale(this.crossProduct(aFixed), aFixed.crossProduct(this), ((Number)scale.max(aFixed.scale())));
  }

  /**
   * @return 
   */
  public   Fixed plus(final Number aNumber)
  {
    java.lang.String exitID = "Fixed>>plus";
    Frame f0 = new Frame(exitID);
    return f0.evaluate(() -> {
    (this.generality().lessThan(aNumber.generality())).ifTrue(Closure.with(f2 -> {
      return (Fixed)f0.exit(exitID, (aNumber.asScaledDecimal(scale).plus(this)));
    }, ""));
    return (Fixed)f0.exit(exitID, (this.plus(aNumber.asScaledDecimal(scale))));
    });
  }

  /**
   * @return 
   */
  public   Fixed times(final Number aNumber)
  {
    java.lang.String exitID = "Fixed>>times";
    Frame f0 = new Frame(exitID);
    return f0.evaluate(() -> {
    (this.generality().lessThan(aNumber.generality())).ifTrue(Closure.with(f2 -> {
      return (Fixed)f0.exit(exitID, (aNumber.times(this)));
    }, ""));
    return (Fixed)f0.exit(exitID, (this.times(aNumber.asScaledDecimal(scale))));
    });
  }

  /**
   * @return 
   */
  public   Fixed divideWith(final Number aNumber)
  {
    java.lang.String exitID = "Fixed>>divideWith";
    Frame f0 = new Frame(exitID);
    return f0.evaluate(() -> {
    (this.generality().lessThan(aNumber.generality())).ifTrue(Closure.with(f2 -> {
      return (Fixed)f0.exit(exitID, (this.coerceTo(aNumber.$class()).divideWith(aNumber)));
    }, ""));
    return (Fixed)f0.exit(exitID, (this.divideWith(aNumber.asScaledDecimal(scale))));
    });
  }

  /**
   * @return 
   */
  @Override public   Fixed printOn(final StreamedSink aStream)
  {
    java.lang.String exitID = "Fixed>>printOn";
    Frame f0 = new Frame(exitID);
    aStream.nextPutAll(this.printString());
    return (Fixed)this;
  }

  /**
   * @return 
   */
  @Override public   String printString()
  {
    java.lang.String exitID = "Fixed>>printString";
    Frame f0 = new Frame(exitID);
    return (String)String.from(this.toString());
  }

  /**
   * @return 
   */
  @Override public   java.lang.String toString()
  {
    java.lang.String exitID = "Fixed>>toString";
    Frame f0 = new Frame(exitID);
    return (java.lang.String)this.asDecimal().toString();
  }
}