001/** 002 * AbstractModuloIntegerPrimitive.java 003 * 004 * Copyright (c) 2004-2012, Nicole C. Tedesco. All rights reserved. 005 * 006 * Licensed under the Apache License, Version 2.0 (the "License"); 007 * you may not use this file except in compliance with the License. 008 * You may obtain a copy of the License at: 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 019package net.sf.jaccumulator.integers; 020 021import java.math.BigDecimal; 022import java.math.BigInteger; 023 024import net.sf.jaccumulator.Domain; 025import net.sf.jaccumulator.StructureStrategy; 026import net.sf.jaccumulator.primitives.Primitive; 027import net.sf.jaccumulator.scalars.Scalar; 028 029/** 030 * Common behavior for all {@link IntegerPrimitive integer} primitives that 031 * obey modular arithmetic 032 * 033 * @param <PRIMITIVE> 034 * this primitive type (used to facilitate operation chaining on write 035 * operations) 036 * @since JAccumulator 4.0 037 * @author Nicole Tedesco (<a 038 * href="mailto:Nicole@NicoleTedesco.com">Nicole@NicoleTedesco.com</a>) 039 */ 040public abstract class AbstractModuloIntegerPrimitive<PRIMITIVE extends Primitive<PRIMITIVE>> 041 extends 042 AbstractIntegerPrimitive<PRIMITIVE> 043{ 044 private static final long serialVersionUID = 5553304082651635872L; 045 046 private final boolean _isEmpty; 047 private final boolean _isOrdered; 048 private final BigInteger _theBIModularLimit; 049 private final int _theMaximumValue; 050 private final int _theModularLimit; 051 private final StructureStrategy _theStrategy; 052 053 public AbstractModuloIntegerPrimitive() 054 { 055 this(0); 056 } 057 058 public <E extends Enum<E>> AbstractModuloIntegerPrimitive( final Class<E> anEnumerationClass ) 059 { 060 this( anEnumerationClass.getEnumConstants() ); 061 } 062 063 public AbstractModuloIntegerPrimitive( final Enum<?> anEnumeration ) 064 { 065 this( anEnumeration.getDeclaringClass().getEnumConstants() ); 066 } 067 068 public AbstractModuloIntegerPrimitive( final Enum<?>[] values ) 069 { 070 this( values.length ); 071 } 072 073 public AbstractModuloIntegerPrimitive( final int aLimit ) 074 { 075 super( Domain.MODULO ); 076 if ( aLimit < 0 ) { 077 throw new IllegalArgumentException( "The modular limit cannot be less than zero" ); 078 } 079 this._theModularLimit = aLimit; 080 this._theBIModularLimit = BigInteger.valueOf(aLimit); 081 switch( aLimit ) { 082 case 0: 083 this._theStrategy = StructureStrategy.EMPTY; 084 break; 085 default: 086 this._theStrategy = StructureStrategy.TUPLE; 087 break; 088 } 089 this._isEmpty = aLimit < 1; 090 this._isOrdered = aLimit == 1; 091 this._theMaximumValue = aLimit - 1; 092 } 093 094 protected final int modulo( final int aValue ) { 095 final int aModularLimit = this.getModularLimit(); 096 final int anIndex = aValue % aModularLimit; 097 if (anIndex < 0) { 098 return aModularLimit + anIndex; 099 } 100 return anIndex; 101 } 102 103 @Override 104 @SuppressWarnings( "unchecked" ) 105 public final PRIMITIVE absoluteValue() 106 throws UnsupportedOperationException, 107 ArithmeticException, 108 IllegalArgumentException 109 { 110 return (PRIMITIVE)this; 111 } 112 113 @Override 114 public final PRIMITIVE and( final int aValue ) 115 throws UnsupportedOperationException, 116 IllegalArgumentException, 117 ArithmeticException 118 { 119 final int result = this.intValue() & aValue; 120 return this.setScalar(result); 121 } 122 123 @Override 124 public final PRIMITIVE decrement() 125 throws UnsupportedOperationException, 126 IllegalArgumentException, 127 ArithmeticException 128 { 129 final int result = this.intValue() - 1; 130 return this.setScalar(result); 131 } 132 133 @Override 134 public final PRIMITIVE difference( final int aValue ) 135 throws UnsupportedOperationException, 136 IllegalArgumentException, 137 ArithmeticException 138 { 139 final int result = this.intValue() - aValue; 140 return this.setScalar(result); 141 } 142 143 public final int getMaximumValue() { 144 return this._theMaximumValue; 145 } 146 147 public final int getModularLimit() { 148 return this._theModularLimit; 149 } 150 151 @Override 152 public StructureStrategy getStructureStrategy() { 153 return this._theStrategy; 154 } 155 156 @Override 157 public final PRIMITIVE increment() 158 throws UnsupportedOperationException, 159 ArithmeticException, 160 IllegalArgumentException 161 { 162 final int result = this.intValue() + 1; 163 return this.setScalar(result); 164 } 165 166 @Override 167 @SuppressWarnings( "unchecked" ) 168 public final <S extends Scalar<?>> S induceScalarMaximum( final S aTarget ) { 169 return (S)aTarget.setScalar( this.getMaximumValue() ); 170 } 171 172 @Override 173 @SuppressWarnings( "unchecked" ) 174 public final <S extends Scalar<?>> S induceScalarMinimum( final S aTarget ) { 175 return (S)aTarget.setZero(); 176 } 177 178 @Override 179 public final int intPostDecrement() 180 throws UnsupportedOperationException, 181 ArithmeticException, 182 IllegalArgumentException 183 { 184 final int myValue = this.intValue(); 185 this.decrement(); 186 return myValue; 187 } 188 189 @Override 190 public final int intPostIncrement() 191 throws UnsupportedOperationException, 192 ArithmeticException, 193 IllegalArgumentException 194 { 195 final int myValue = this.intValue(); 196 this.increment(); 197 return myValue; 198 } 199 200 @Override 201 public final PRIMITIVE inverse() 202 throws UnsupportedOperationException, 203 ArithmeticException, 204 IllegalArgumentException 205 { 206 final int aModularLimit = this.getModularLimit(); 207 final int result = intModularInverse( this.intValue(), aModularLimit ); 208 return this.setScalar(result); 209 } 210 211 @Override 212 public final boolean isEmpty() { 213 return this._isEmpty; 214 } 215 216 @Override 217 public final boolean isModulo() { 218 return true; 219 } 220 221 @Override 222 public final boolean isOrdered() { 223 return this._isOrdered; 224 } 225 226 @Override 227 public final PRIMITIVE mod( final int aValue ) 228 throws UnsupportedOperationException, 229 IllegalArgumentException, 230 ArithmeticException 231 { 232 final int result = this.intValue() % aValue; 233 return this.setScalar(result); 234 } 235 236 @Override 237 public final PRIMITIVE not() 238 throws UnsupportedOperationException, 239 IllegalArgumentException, 240 ArithmeticException 241 { 242 final int result = this.intValue() ^ -1; 243 return this.setScalar(result); 244 } 245 246 @Override 247 public final PRIMITIVE or( final int aValue ) 248 throws UnsupportedOperationException, 249 IllegalArgumentException, 250 ArithmeticException 251 { 252 final int result = this.intValue() - aValue; 253 return this.setScalar(result); 254 } 255 256 @Override 257 public final PRIMITIVE product( final int aValue ) 258 throws UnsupportedOperationException, 259 IllegalArgumentException, 260 ArithmeticException 261 { 262 final int result = this.intValue() * aValue; 263 return this.setScalar(result); 264 } 265 266 @Override 267 public final PRIMITIVE quotient( final int aValue ) 268 throws UnsupportedOperationException, 269 IllegalArgumentException, 270 ArithmeticException 271 { 272 final int result = 273 intModularQuotient( 274 this.intValue(), 275 aValue, 276 this.getModularLimit()); 277 return this.setScalar(result); 278 } 279 280 @Override 281 public final PRIMITIVE setMaximum() 282 throws UnsupportedOperationException, 283 ArithmeticException, 284 IllegalArgumentException 285 { 286 return this.setScalar( this.getMaximumValue() ); 287 } 288 289 @Override 290 public final PRIMITIVE setMinimum() 291 throws UnsupportedOperationException, 292 ArithmeticException, 293 IllegalArgumentException 294 { 295 return this.setZero(); 296 } 297 298 @Override 299 public final PRIMITIVE setReal( final BigDecimal aValue ) 300 throws UnsupportedOperationException, 301 IllegalArgumentException, 302 ArithmeticException, 303 NullPointerException 304 { 305 return this.setReal(aValue.toBigInteger()); 306 } 307 308 @Override 309 public final PRIMITIVE setReal( final BigInteger aValue ) 310 throws UnsupportedOperationException, 311 IllegalArgumentException, 312 ArithmeticException, 313 NullPointerException 314 { 315 return this.setScalar(aValue.mod(this._theBIModularLimit).intValue()); 316 } 317 318 @Override 319 public final PRIMITIVE setScalar( final double aValue ) 320 throws UnsupportedOperationException, 321 IllegalArgumentException, 322 ArithmeticException 323 { 324 return this.setReal( new BigDecimal( String.valueOf(aValue)) ); 325 } 326 327 @Override 328 public final PRIMITIVE setScalar( final float aValue ) 329 throws UnsupportedOperationException, 330 IllegalArgumentException, 331 ArithmeticException 332 { 333 return this.setReal( new BigDecimal( String.valueOf(aValue)) ); 334 } 335 336 @Override 337 public final PRIMITIVE setScalar( final long aValue ) 338 throws UnsupportedOperationException, 339 IllegalArgumentException, 340 ArithmeticException 341 { 342 final long aResult = aValue % this.getModularLimit(); 343 return this.setScalar((int)aResult); 344 } 345 346 @Override 347 public PRIMITIVE shiftLeft( final int count ) 348 throws UnsupportedOperationException, 349 IllegalArgumentException, 350 ArithmeticException 351 { 352 int myValue = this.intValue(); 353 myValue <<= count; 354 return this.setScalar( myValue ); 355 } 356 357 @Override 358 public PRIMITIVE shiftRight( final int count ) 359 throws UnsupportedOperationException, 360 IllegalArgumentException, 361 ArithmeticException 362 { 363 int myValue = this.intValue(); 364 myValue >>= count; 365 return this.setScalar( myValue ); 366 } 367 368 @Override 369 public PRIMITIVE shiftRightExtendZero( final int count ) 370 throws UnsupportedOperationException, 371 IllegalArgumentException, 372 ArithmeticException 373 { 374 int myValue = this.intValue(); 375 myValue >>>= count; 376 return this.setScalar( myValue ); 377 } 378 379 @Override 380 public final PRIMITIVE sum( final int aValue ) 381 throws UnsupportedOperationException, 382 IllegalArgumentException, 383 ArithmeticException 384 { 385 final int result = this.intValue() + aValue; 386 return this.setScalar(result); 387 } 388 389 @Override 390 public final PRIMITIVE xor( final int aValue ) 391 throws UnsupportedOperationException, 392 IllegalArgumentException, 393 ArithmeticException 394 { 395 final int result = this.intValue() ^ aValue; 396 return this.setScalar(result); 397 } 398}