001package components.naturalnumber;
002
003import java.math.BigInteger;
004
005/**
006 * {@code NaturalNumber} represented as a {@link java.math.BigInteger
007 * java.math.BigInteger} with implementations of primary methods.
008 *
009 * @convention $this.rep >= 0
010 * @correspondence this = $this.rep
011 */
012public class NaturalNumber1L extends NaturalNumberSecondary {
013
014    /*
015     * Private members --------------------------------------------------------
016     */
017
018    /**
019     * Representation of {@code this}.
020     */
021    private BigInteger rep;
022
023    /**
024     * Creator of initial representation.
025     */
026    private void createNewRep() {
027        this.rep = BigInteger.valueOf(0);
028    }
029
030    /*
031     * Constructors -----------------------------------------------------------
032     */
033
034    /**
035     * No-argument constructor.
036     */
037    public NaturalNumber1L() {
038        this.createNewRep();
039    }
040
041    /**
042     * Constructor from {@code int}.
043     *
044     * @param i
045     *            {@code int} to initialize from
046     */
047    public NaturalNumber1L(int i) {
048        assert i >= 0 : "Violation of: i >= 0";
049        this.rep = BigInteger.valueOf(i);
050    }
051
052    /**
053     * Constructor from {@code String}.
054     *
055     * @param s
056     *            {@code String} to initialize from
057     */
058    public NaturalNumber1L(String s) {
059        assert s != null : "Violation of: s is not null";
060        assert s.matches("0|[1-9]\\d*")
061                : "Violation of: there exists n: NATURAL (s = TO_STRING(n))";
062        this.rep = new BigInteger(s);
063    }
064
065    /**
066     * Constructor from {@code NaturalNumber}.
067     *
068     * @param n
069     *            {@code NaturalNumber} to initialize from
070     */
071    public NaturalNumber1L(NaturalNumber n) {
072        assert n != null : "Violation of: n is not null";
073        /*
074         * The call to the NaturalNumber method toString in the statement below
075         * is not a violation of the kernel purity rule because the parameter n
076         * is viewed only through its declared type (the interface
077         * NaturalNumber) and therefore can be safely handled from the client's
078         * point of view.
079         */
080        this.rep = new BigInteger(n.toString());
081    }
082
083    /*
084     * Standard methods -------------------------------------------------------
085     */
086
087    @Override
088    public final NaturalNumber newInstance() {
089        try {
090            return this.getClass().getConstructor().newInstance();
091        } catch (ReflectiveOperationException e) {
092            throw new AssertionError(
093                    "Cannot construct object of type " + this.getClass());
094        }
095    }
096
097    @Override
098    public final void clear() {
099        this.createNewRep();
100    }
101
102    @Override
103    public final void transferFrom(NaturalNumber source) {
104        assert source != null : "Violation of: source is not null";
105        assert source != this : "Violation of: source is not this";
106        assert source instanceof NaturalNumber1L
107                : "Violation of: source is of dynamic type NaturalNumber1L";
108        /*
109         * This cast cannot fail since the assert above would have stopped
110         * execution in that case.
111         */
112        NaturalNumber1L localSource = (NaturalNumber1L) source;
113        this.rep = localSource.rep;
114        localSource.createNewRep();
115    }
116
117    /*
118     * Kernel methods ---------------------------------------------------------
119     */
120
121    @Override
122    public final void multiplyBy10(int k) {
123        assert 0 <= k : "Violation of: 0 <= k";
124        assert k < RADIX : "Violation of: k < 10";
125        BigInteger bigK = BigInteger.valueOf(k);
126        this.rep = this.rep.multiply(BigInteger.TEN);
127        this.rep = this.rep.add(bigK);
128    }
129
130    @Override
131    public final int divideBy10() {
132        BigInteger[] results = this.rep.divideAndRemainder(BigInteger.TEN);
133        this.rep = results[0];
134        return results[1].intValue();
135    }
136
137    @Override
138    public final boolean isZero() {
139        return this.rep.compareTo(BigInteger.ZERO) == 0;
140    }
141
142}