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}