001package components.naturalnumber;
002
003import components.stack.Stack;
004import components.stack.Stack1L;
005
006/**
007 * {@code NaturalNumber} represented as a {@link Stack<Integer>} with
008 * implementations of primary methods.
009 *
010 * <p>
011 * Execution-time performance of all methods implemented in this class is O(1),
012 * except the constructors from {@code String} (which is O(|{@code s}|)) and
013 * from {@code NaturalNumber} (which is O(log {@code n})).
014 *
015 * @mathdefinitions {@code
016 * HAS_ONLY_DIGITS (
017 *   s: string of integer
018 *  ): boolean satisfies
019 *  if s = empty_string
020 *   then HAS_ONLY_DIGITS (s) = true
021 *   else for all a: string of integer, k: integer where (s = a * <k>)
022 *         (HAS_ONLY_DIGITS (s) = (HAS_ONLY_DIGITS (a)  and  0 <= k < 10))
023 *
024 * IS_WELL_FORMED_RADIX_REPRESENTATION (
025 *   s: string of integer
026 *  ): boolean is
027 *  s = empty_string  or
028 *      there exists k: integer, a: string of integer
029 *       (s = <k> * a  and
030 *        1 <= k < 10  and
031 *        HAS_ONLY_DIGITS (a))
032 *
033 * NUMERICAL_VALUE (
034 *   s: string of integer
035 *  ): integer satisfies
036 *  if s = empty_string
037 *   then NUMERICAL_VALUE (s) = 0
038 *   else for all a: string of integer, k: integer where (s = a * <k>)
039 *         (NUMERICAL_VALUE (s) = NUMERICAL_VALUE (a) * 10 + k)
040 *
041 * REVERSED_STRING_OF_DIGITS (
042 *   n: NATURAL
043 *  ): string of integer satisfies
044 *  if n = 0
045 *  then REVERSED_STRING_OF_DIGITS (n) = empty_string
046 *  else REVERSED_STRING_OF_DIGITS (n) = <n mod 10> * REVERSED_STRING_OF_DIGITS (n / 10)
047 * }
048 * @convention IS_WELL_FORMED_RADIX_REPRESENTATION (rev($this.digits))
049 * @correspondence this = NUMERICAL_VALUE (rev($this.digits))
050 */
051public class NaturalNumber2 extends NaturalNumberSecondary {
052
053    /*
054     * Private members --------------------------------------------------------
055     */
056
057    /**
058     * Representation of {@code this}.
059     */
060    private Stack<Integer> digits;
061
062    /**
063     * Prepends onto the front of a {@code Stack} the digits of a given integer
064     * i, in reverse order, if i is positive; otherwise, does nothing.
065     *
066     * @param digits
067     *            the stack of digits
068     * @param i
069     *            the integer to convert
070     * @updates digits
071     * @requires i >= 0
072     * @ensures digits = REVERSED_STRING_OF_DIGITS(i) * #digits
073     */
074    private static void prependRepFromInt(Stack<Integer> digits, int i) {
075        /**
076         * @decreases i
077         */
078        if (i > 0) {
079            int lastDigit = i % RADIX;
080            prependRepFromInt(digits, i / RADIX);
081            digits.push(lastDigit);
082        }
083    }
084
085    /**
086     * Prepends onto the front of a {@code Stack} the digits in a given
087     * {@code String} s, in reverse order, if s is not "0"; otherwise, does
088     * nothing.
089     *
090     * @param digits
091     *            the stack of digits
092     * @param s
093     *            the {@code String} to convert
094     * @updates digits
095     * @requires there exists n: NATURAL (s = TO_STRING(n))
096     * @ensures <pre>
097     * there exists n: NATURAL
098     *  (s = TO_STRING(n)  and  digits = REVERSED_STRING_OF_DIGITS(n) * #digits
099     * </pre>
100     */
101    private static void prependRepFromString(Stack<Integer> digits, String s) {
102        /**
103         * @decreases |s|
104         */
105        if (!s.equals("0")) {
106            if (s.length() > 1) {
107                prependRepFromString(digits, s.substring(0, s.length() - 1));
108            }
109            digits.push(Character.digit(s.charAt(s.length() - 1), RADIX));
110        }
111    }
112
113    /**
114     * Creator of initial representation.
115     */
116    private void createNewRep() {
117        this.digits = new Stack1L<Integer>();
118    }
119
120    /*
121     * Constructors -----------------------------------------------------------
122     */
123
124    /**
125     * No-argument constructor.
126     */
127    public NaturalNumber2() {
128        this.createNewRep();
129    }
130
131    /**
132     * Constructor from {@code int}.
133     *
134     * @param i
135     *            {@code int} to initialize from
136     */
137    public NaturalNumber2(int i) {
138        assert i >= 0 : "Violation of: i >= 0";
139        this.createNewRep();
140        prependRepFromInt(this.digits, i);
141    }
142
143    /**
144     * Constructor from {@code String}.
145     *
146     * @param s
147     *            {@code String} to initialize from
148     */
149    public NaturalNumber2(String s) {
150        assert s != null : "Violation of: s is not null";
151        assert s.matches("0|[1-9]\\d*")
152                : "Violation of: there exists n: NATURAL (s = TO_STRING(n))";
153        this.createNewRep();
154        prependRepFromString(this.digits, s);
155    }
156
157    /**
158     * Constructor from {@code NaturalNumber}.
159     *
160     * @param n
161     *            {@code NaturalNumber} to initialize from
162     */
163    public NaturalNumber2(NaturalNumber n) {
164        assert n != null : "Violation of: n is not null";
165        this.createNewRep();
166        /*
167         * The following call to the NaturalNumber method toString is not a
168         * violation of the kernel purity rule because the parameter n is viewed
169         * only through its declared type (the interface NaturalNumber) and
170         * therefore can be safely handled from the client's point of view.
171         */
172        String s = n.toString();
173        prependRepFromString(this.digits, s);
174    }
175
176    /*
177     * Standard methods -------------------------------------------------------
178     */
179
180    @Override
181    public final NaturalNumber newInstance() {
182        try {
183            return this.getClass().getConstructor().newInstance();
184        } catch (ReflectiveOperationException e) {
185            throw new AssertionError(
186                    "Cannot construct object of type " + this.getClass());
187        }
188    }
189
190    @Override
191    public final void clear() {
192        this.createNewRep();
193    }
194
195    @Override
196    public final void transferFrom(NaturalNumber source) {
197        assert source != null : "Violation of: source is not null";
198        assert source != this : "Violation of: source is not this";
199        assert source instanceof NaturalNumber2
200                : "Violation of: source is of dynamic type NaturalNumber2";
201        /*
202         * This cast cannot fail since the assert above would have stopped
203         * execution in that case.
204         */
205        NaturalNumber2 localSource = (NaturalNumber2) source;
206        this.digits = localSource.digits;
207        localSource.createNewRep();
208    }
209
210    /*
211     * Kernel methods ---------------------------------------------------------
212     */
213
214    @Override
215    public final void multiplyBy10(int k) {
216        assert 0 <= k : "Violation of: 0 <= k";
217        assert k < RADIX : "Violation of: k < 10";
218        if (this.digits.length() > 0 || k > 0) {
219            this.digits.push(k);
220        }
221    }
222
223    @Override
224    public final int divideBy10() {
225        int k = 0;
226        if (this.digits.length() > 0) {
227            k = this.digits.pop();
228        }
229        return k;
230    }
231
232    @Override
233    public final boolean isZero() {
234        return this.digits.length() == 0;
235    }
236
237}