SmallInteger.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 Hoot.Runtime.Faces.IntegerValue;
import Hoot.Runtime.Names.Primitive;
import Hoot.Magnitudes.Integer;
import Smalltalk.Magnitudes.Scalar;
import Smalltalk.Magnitudes.Ordinal;
import Smalltalk.Magnitudes.Numeric;

public class SmallInteger extends Integer
{

  public static Metaclass type() { return (Metaclass)Metaclass.$class; }
  @Override public Metaclass $class() { return (Metaclass)Metaclass.$class; }
  public static class Metaclass extends Integer.Metaclass
  {
    static final SmallInteger.Metaclass $class = new SmallInteger.Metaclass();
    public Metaclass() {
      this(SmallInteger.Metaclass.class);
    }

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

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

    protected static SmallInteger Generality = SmallInteger.from(10);

    /**
     * @return 
     */
    public   SmallInteger IntegerFrom(final java.lang.Integer intValue)
    {
      java.lang.String exitID = "SmallIntegerMetatype>>IntegerFrom";
      Frame f0 = new Frame(exitID);
      return f0.evaluate(() -> {
      return (SmallInteger)f0.exit(exitID, SmallInteger.from(intValue));
      });
    }

    /**
     * @return 
     */
    public   java.lang.Integer intFrom(final Integer anInteger)
    {
      java.lang.String exitID = "SmallIntegerMetatype>>intFrom";
      Frame f0 = new Frame(exitID);
      return anInteger.intValue();
    }

    /**
     * @return 
     */
    @Override public   SmallInteger coerce(final Number aNumber)
    {
      java.lang.String exitID = "SmallIntegerMetatype>>coerce";
      Frame f0 = new Frame(exitID);
      return f0.evaluate(() -> {
      return (SmallInteger)f0.exit(exitID, SmallInteger.from(aNumber.primitiveInteger()));
      });
    }

    /**
     * @return 
     */
    @Override protected   void initialize()
    {
      java.lang.String exitID = "SmallIntegerMetatype>>initialize";
      Frame f0 = new Frame(exitID);
      SmallInteger.initializeFlyweights();
    }

    /**
     * @return 
     */
    public   SmallInteger maximum()
    {
      java.lang.String exitID = "SmallIntegerMetatype>>maximum";
      Frame f0 = new Frame(exitID);
      return f0.evaluate(() -> {
      return (SmallInteger)f0.exit(exitID, SmallInteger.from(Primitive.elementaryMaxInteger()));
      });
    }

    /**
     * @return 
     */
    public   SmallInteger minimum()
    {
      java.lang.String exitID = "SmallIntegerMetatype>>minimum";
      Frame f0 = new Frame(exitID);
      return f0.evaluate(() -> {
      return (SmallInteger)f0.exit(exitID, SmallInteger.from(Primitive.elementaryMinInteger()));
      });
    }

    /**
     * @return 
     */
    @Override public   SmallInteger radix()
    {
      java.lang.String exitID = "SmallIntegerMetatype>>radix";
      Frame f0 = new Frame(exitID);
      return f0.evaluate(() -> {
      return (SmallInteger)f0.exit(exitID, Duality);
      });
    }

    /**
     * @return 
     */
    @Override public   SmallInteger precision()
    {
      java.lang.String exitID = "SmallIntegerMetatype>>precision";
      Frame f0 = new Frame(exitID);
      return f0.evaluate(() -> {
      return (SmallInteger)f0.exit(exitID, SmallInteger.from(32));
      });
    }

    /**
     * @return 
     */
    public   SmallInteger generality()
    {
      java.lang.String exitID = "SmallIntegerMetatype>>generality";
      Frame f0 = new Frame(exitID);
      return f0.evaluate(() -> {
      return (SmallInteger)f0.exit(exitID, Generality);
      });
    }
  }


  protected static IntegerValue.Cache FlyweightCache = new IntegerValue.Cache(SmallInteger.valueFactory());
  public static SmallInteger Zero = SmallInteger.from(0);
  public static SmallInteger Unity = SmallInteger.from(1);
  public static SmallInteger Duality = SmallInteger.from(2);
  public static SmallInteger Negativity = (SmallInteger.from(0).minus(SmallInteger.from(1)));
  protected int cachedValue = 0;

  /**
   * @return 
   */
  public static   Closure valueFactory()
  {
    java.lang.String exitID = "SmallInteger>>$valueFactory";
    Frame f0 = new Frame(exitID);
    return (Closure)Closure.with(f2 -> {
      int value = f2.getValue(0).value();
      return new SmallInteger(value);
    }, "value");
  }

  /**
   * @return 
   */
  public static   IntegerValue.Cache flyweights()
  {
    java.lang.String exitID = "SmallInteger>>$flyweights";
    Frame f0 = new Frame(exitID);
    return (IntegerValue.Cache)FlyweightCache;
  }

  /**
   * @return 
   */
  public static   SmallInteger flyweightCount()
  {
    java.lang.String exitID = "SmallInteger>>$flyweightCount";
    Frame f0 = new Frame(exitID);
    return (SmallInteger)SmallInteger.from(FlyweightCache.size());
  }

  /**
   * @return 
   */
  public static   void initializeFlyweights()
  {
    java.lang.String exitID = "SmallInteger>>$initializeFlyweights";
    Frame f0 = new Frame(exitID);
    int index = 0;
    while((index < FlyweightCache.size())) {
      FlyweightCache.cacheCovered(new SmallInteger(index));
      FlyweightCache.cacheCovered(new SmallInteger((0 - index)));
      index += 1;
    };

     Zero = FlyweightCache.getCached(0);

     Unity = FlyweightCache.getCached(1);

     Duality = FlyweightCache.getCached(2);

     Negativity = FlyweightCache.getCached((0 - 1));
  }

  /**
   * 
   */
  protected    SmallInteger()
  {
    super();
    java.lang.String exitID = "SmallInteger>>SmallInteger";
    Frame f0 = new Frame(exitID);
  }

  /**
   * 
   */
  protected    SmallInteger(final int value)
  {
    this();
    java.lang.String exitID = "SmallInteger>>SmallInteger";
    Frame f0 = new Frame(exitID);
     cachedValue = value;
  }

  /**
   * @return 
   */
  public static   SmallInteger from(final int intValue)
  {
    java.lang.String exitID = "SmallInteger>>$from";
    Frame f0 = new Frame(exitID);
    return (SmallInteger)SmallInteger.flyweights().getCached(intValue);
  }

  /**
   * @return 
   */
  public final   SmallInteger plus(final SmallInteger aNumber)
  {
    java.lang.String exitID = "SmallInteger>>plus";
    Frame f0 = new Frame(exitID);
    return (SmallInteger)SmallInteger.from((cachedValue + aNumber.intValue()));
  }

  /**
   * @return 
   */
  public final   SmallInteger minus(final SmallInteger aNumber)
  {
    java.lang.String exitID = "SmallInteger>>minus";
    Frame f0 = new Frame(exitID);
    return (SmallInteger)SmallInteger.from((cachedValue - aNumber.intValue()));
  }

  /**
   * @return 
   */
  public final   SmallInteger times(final SmallInteger aNumber)
  {
    java.lang.String exitID = "SmallInteger>>times";
    Frame f0 = new Frame(exitID);
    return (SmallInteger)SmallInteger.from((cachedValue * aNumber.intValue()));
  }

  /**
   * @return 
   */
  public final   Number divideWith(final SmallInteger aNumber)
  {
    java.lang.String exitID = "SmallInteger>>divideWith";
    Frame f0 = new Frame(exitID);
    aNumber.faultIfZero();
    return (Number)Fraction.type().numerator_denominator(this, aNumber);
  }

  /**
   * @return 
   */
  @Override public   Integer plus(final Numeric aNumber)
  {
    java.lang.String exitID = "SmallInteger>>plus";
    Frame f0 = new Frame(exitID);
    return (Integer)LargeInteger.from(((Number)aNumber).asInteger().asBigInteger().add(this.asBigInteger())).narrowGenerality();
  }

  /**
   * @return 
   */
  @Override public   Integer times(final Numeric aNumber)
  {
    java.lang.String exitID = "SmallInteger>>times";
    Frame f0 = new Frame(exitID);
    return (Integer)LargeInteger.from(((Number)aNumber).asInteger().asBigInteger().multiply(this.asBigInteger())).narrowGenerality();
  }

  /**
   * @return 
   */
  public   Number divideWith(final Number aNumber)
  {
    java.lang.String exitID = "SmallInteger>>divideWith";
    Frame f0 = new Frame(exitID);
    return (Number)(this.divideWith(aNumber.asSmallInteger()));
  }

  /**
   * @return 
   */
  @Override public   SmallInteger truncateWith(final Numeric aNumber)
  {
    java.lang.String exitID = "SmallInteger>>truncateWith";
    Frame f0 = new Frame(exitID);
    return (SmallInteger)(this.truncateWith(((Number)aNumber).asSmallInteger()));
  }

  /**
   * @return 
   */
  @Override public   Number divideWith(final Numeric aNumber)
  {
    java.lang.String exitID = "SmallInteger>>divideWith";
    Frame f0 = new Frame(exitID);
    Number n = ((Number)aNumber);
    n.faultIfZero();
    return (Number)this.divideWith(n);
  }

  /**
   * @return 
   */
  public   SmallInteger truncateWith(final SmallInteger aNumber)
  {
    java.lang.String exitID = "SmallInteger>>truncateWith";
    Frame f0 = new Frame(exitID);
    aNumber.faultIfZero();
    return (SmallInteger)SmallInteger.from((this.primitiveInteger() / aNumber.intValue()));
  }

  /**
   * @return 
   */
  public   SmallInteger remainderFrom(final SmallInteger aNumber)
  {
    java.lang.String exitID = "SmallInteger>>remainderFrom";
    Frame f0 = new Frame(exitID);
    aNumber.faultIfZero();
    return (SmallInteger)SmallInteger.from((this.primitiveInteger() % aNumber.intValue()));
  }

  /**
   * @return 
   */
  public final   Boolean equals(final SmallInteger aNumber)
  {
    java.lang.String exitID = "SmallInteger>>equals";
    Frame f0 = new Frame(exitID);
    return (Boolean)Boolean.from((this.primitiveInteger() == aNumber.intValue()));
  }

  /**
   * @return 
   */
  public final   Boolean lessThan(final SmallInteger aNumber)
  {
    java.lang.String exitID = "SmallInteger>>lessThan";
    Frame f0 = new Frame(exitID);
    return (Boolean)Boolean.from((this.primitiveInteger() < aNumber.intValue()));
  }

  /**
   * @return 
   */
  public final   Boolean moreThan(final SmallInteger aNumber)
  {
    java.lang.String exitID = "SmallInteger>>moreThan";
    Frame f0 = new Frame(exitID);
    return (Boolean)Boolean.from((this.primitiveInteger() > aNumber.intValue()));
  }

  /**
   * @return 
   */
  @Override public   Boolean equals(final Magnitude aNumber)
  {
    java.lang.String exitID = "SmallInteger>>equals";
    Frame f0 = new Frame(exitID);
    return (Boolean)Number.type().accepts(aNumber).and(Predicate.with(f2 -> {
      return (((Number)aNumber).asRational().equals(this));
    }, ""));
  }

  /**
   * @return 
   */
  @Override public   Boolean lessThan(final Scalar aNumber)
  {
    java.lang.String exitID = "SmallInteger>>lessThan";
    Frame f0 = new Frame(exitID);
    return (Boolean)Number.type().accepts(aNumber).and(Predicate.with(f2 -> {
      return (((Number)aNumber).asRational().moreThan(this));
    }, ""));
  }

  /**
   * @return 
   */
  @Override public   Boolean moreThan(final Scalar aNumber)
  {
    java.lang.String exitID = "SmallInteger>>moreThan";
    Frame f0 = new Frame(exitID);
    return (Boolean)Number.type().accepts(aNumber).and(Predicate.with(f2 -> {
      return (((Number)aNumber).asRational().lessThan(this));
    }, ""));
  }

  /**
   * @return 
   */
  public   Boolean lessThan(final Number aNumber)
  {
    java.lang.String exitID = "SmallInteger>>lessThan";
    Frame f0 = new Frame(exitID);
    return (Boolean)Number.type().accepts(aNumber).and(Predicate.with(f2 -> {
      return (((Number)aNumber).asRational().moreThan(this));
    }, ""));
  }

  /**
   * @return 
   */
  public   Boolean moreThan(final Number aNumber)
  {
    java.lang.String exitID = "SmallInteger>>moreThan";
    Frame f0 = new Frame(exitID);
    return (Boolean)Number.type().accepts(aNumber).and(Predicate.with(f2 -> {
      return (((Number)aNumber).asRational().lessThan(this));
    }, ""));
  }

  /**
   * @return 
   */
  @Override public   SmallInteger generality()
  {
    java.lang.String exitID = "SmallInteger>>generality";
    Frame f0 = new Frame(exitID);
    return (SmallInteger)this.$class().generality();
  }

  /**
   * @return 
   */
  public static   SmallInteger from(final Numeric aNumber)
  {
    java.lang.String exitID = "SmallInteger>>$from";
    Frame f0 = new Frame(exitID);
    return (SmallInteger)SmallInteger.from(aNumber.asInteger().intValue());
  }

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

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

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

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

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

  /**
   * @return 
   */
  @Override public   long primitiveLong()
  {
    java.lang.String exitID = "SmallInteger>>primitiveLong";
    Frame f0 = new Frame(exitID);
    return (long)this.elementaryInteger().longValue();
  }

  /**
   * @return 
   */
  @Override public   java.lang.Float primitiveFloat()
  {
    java.lang.String exitID = "SmallInteger>>primitiveFloat";
    Frame f0 = new Frame(exitID);
    return (java.lang.Float)this.elementaryInteger().floatValue();
  }

  /**
   * @return 
   */
  @Override public   java.lang.Double primitiveDouble()
  {
    java.lang.String exitID = "SmallInteger>>primitiveDouble";
    Frame f0 = new Frame(exitID);
    return (java.lang.Double)this.elementaryInteger().doubleValue();
  }

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

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

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

  /**
   * @return 
   */
  public   String asString()
  {
    java.lang.String exitID = "SmallInteger>>asString";
    Frame f0 = new Frame(exitID);
    return (String)this.printString();
  }

  /**
   * @return 
   */
  public   Character codePoint()
  {
    java.lang.String exitID = "SmallInteger>>codePoint";
    Frame f0 = new Frame(exitID);
    return (Character)Character.type().codePoint(this);
  }

  /**
   * @return 
   */
  public   FastInteger asFastInteger()
  {
    java.lang.String exitID = "SmallInteger>>asFastInteger";
    Frame f0 = new Frame(exitID);
    return (FastInteger)FastInteger.fromInteger(this);
  }

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

  /**
   * @return 
   */
  @Override public   SmallInteger deepCopy()
  {
    java.lang.String exitID = "SmallInteger>>deepCopy";
    Frame f0 = new Frame(exitID);
    return (SmallInteger)this.shallowCopy();
  }

  /**
   * @return 
   */
  public   SmallInteger unmodifiableInteger()
  {
    java.lang.String exitID = "SmallInteger>>unmodifiableInteger";
    Frame f0 = new Frame(exitID);
    this.error(String.from("Attempt to change an unmodifiable SmallInteger instance"));
    return (SmallInteger)this;
  }

  /**
   * @return 
   */
  @Override public   SmallInteger bitAnd(final Ordinal anInteger)
  {
    java.lang.String exitID = "SmallInteger>>bitAnd";
    Frame f0 = new Frame(exitID);
    return (SmallInteger)SmallInteger.from((this.intValue() & anInteger.intValue()));
  }

  /**
   * @return 
   */
  @Override public   SmallInteger bitOr(final Ordinal anInteger)
  {
    java.lang.String exitID = "SmallInteger>>bitOr";
    Frame f0 = new Frame(exitID);
    return (SmallInteger)SmallInteger.from((this.intValue() | anInteger.intValue()));
  }

  /**
   * @return 
   */
  @Override public   SmallInteger bitXor(final Ordinal anInteger)
  {
    java.lang.String exitID = "SmallInteger>>bitXor";
    Frame f0 = new Frame(exitID);
    return (SmallInteger)SmallInteger.from(Primitive.xorBits(this.intValue(), anInteger.intValue()));
  }

  /**
   * @return 
   */
  @Override public   Integer bitAt(final Ordinal index)
  {
    java.lang.String exitID = "SmallInteger>>bitAt";
    Frame f0 = new Frame(exitID);
    int x = (((Integer)index).primitiveInteger() - 1);
    if (((x < 0) | (x > 31))) {
      throw new IllegalArgumentException("Bit index out of range, not 1 - 32");
    };

    SmallInteger s = SmallInteger.from((1 << x));
    return (Integer)(Boolean.primitiveValue((this.bitAnd(s).primitiveInteger() == 0)) ? Zero : Unity);
  }

  /**
   * @return 
   */
  @Override public   SmallInteger bitAt_put(final Ordinal index, final Ordinal bitValue)
  {
    java.lang.String exitID = "SmallInteger>>bitAt_put";
    Frame f0 = new Frame(exitID);
    int x = (((Integer)index).intValue() - 1);

    int v = ((Integer)bitValue).intValue();
    if (((x < 0) | (x > 31))) {
      throw new IllegalArgumentException("Bit index out of range, not 1 - 32");
    };

    SmallInteger s = SmallInteger.from((1 << x));
    if ((v == 0)) {
      return SmallInteger.from((this.intValue() & s.bitInvert().intValue()));
    };
    if ((v == 1)) {
      return SmallInteger.from((this.intValue() | s.intValue()));
    };
    throw new IllegalArgumentException("Bit value must be 0 or 1");
  }

  /**
   * @return 
   */
  public   SmallInteger rightShift(final Integer count)
  {
    java.lang.String exitID = "SmallInteger>>rightShift";
    Frame f0 = new Frame(exitID);
    return (SmallInteger)SmallInteger.from((this.intValue() >> count.intValue()));
  }

  /**
   * @return 
   */
  public   SmallInteger leftShift(final Integer count)
  {
    java.lang.String exitID = "SmallInteger>>leftShift";
    Frame f0 = new Frame(exitID);
    return (SmallInteger)SmallInteger.from((this.intValue() << count.intValue()));
  }

  /**
   * @return 
   */
  @Override public   SmallInteger bitShift(final Ordinal count)
  {
    java.lang.String exitID = "SmallInteger>>bitShift";
    Frame f0 = new Frame(exitID);
    if ((((Integer)count).primitiveInteger() < 0)) {
      return this.rightShift(((Integer)count.negated()));
    };
    return (SmallInteger)this.leftShift(((Integer)count));
  }

  /**
   * @return 
   */
  @Override public   Boolean isLiteral()
  {
    java.lang.String exitID = "SmallInteger>>isLiteral";
    Frame f0 = new Frame(exitID);
    return (Boolean)True.literal();
  }

  /**
   * @return 
   */
  @Override public   Boolean isSmallInteger()
  {
    java.lang.String exitID = "SmallInteger>>isSmallInteger";
    Frame f0 = new Frame(exitID);
    return (Boolean)True.literal();
  }

  /**
   * @return 
   */
  @Override public   SmallInteger abs()
  {
    java.lang.String exitID = "SmallInteger>>abs";
    Frame f0 = new Frame(exitID);
    return (SmallInteger)(this.lessThan(Zero)).ifTrue_ifFalse(Closure.with(f2 -> {
      return this.negated();
    }, ""), Closure.with(f2 -> {
      return this;
    }, ""));
  }

  /**
   * @return 
   */
  @Override public   SmallInteger negated()
  {
    java.lang.String exitID = "SmallInteger>>negated";
    Frame f0 = new Frame(exitID);
    return (SmallInteger)SmallInteger.from((Zero.intValue() - this.intValue()));
  }

  /**
   * @return 
   */
  @Override public   SmallInteger timesRepeat(final NiladicValuable aBlock)
  {
    java.lang.String exitID = "SmallInteger>>timesRepeat";
    Frame f0 = new Frame(exitID);
    FastInteger count = Unity.asFastInteger();
    Predicate.with(f2 -> {
      return (count.notMore(this));
    }, "").whileTrue(Closure.with(f2 -> {
      aBlock.value();
    count.add(Unity);
    }, ""));
    return (SmallInteger)this;
  }

  /**
   * @return 
   */
  public   SmallInteger to_by_do(final SmallInteger otherBound, final SmallInteger delta, final MonadicValuable aBlock)
  {
    java.lang.String exitID = "SmallInteger>>to_by_do";
    Frame f0 = new Frame(exitID);
    FastInteger index = this.asFastInteger();
    (delta.moreThan(Zero)).ifTrue_ifFalse(Closure.with(f2 -> {
      return Predicate.with(f3 -> {
      return (index.notMore(otherBound));
    }, "").whileTrue(Closure.with(f3 -> {
      aBlock.value(index);
    index.add(delta);
    }, ""));
    }, ""), Closure.with(f2 -> {
      return Predicate.with(f3 -> {
      return (otherBound.notMore(index));
    }, "").whileTrue(Closure.with(f3 -> {
      aBlock.value(index);
    index.add(delta);
    }, ""));
    }, ""));
    return (SmallInteger)this;
  }

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