A few hacks to make the list circular: this lets the CG not signal the JPF that the...
[jpf-core.git] / src / main / gov / nasa / jpf / vm / choice / IntIntervalGenerator.java
1 /*
2  * Copyright (C) 2014, United States Government, as represented by the
3  * Administrator of the National Aeronautics and Space Administration.
4  * All rights reserved.
5  *
6  * The Java Pathfinder core (jpf-core) platform is licensed under the
7  * Apache License, Version 2.0 (the "License"); you may not use this file except
8  * in compliance with the License. You may obtain a copy of the License at
9  * 
10  *        http://www.apache.org/licenses/LICENSE-2.0. 
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and 
16  * limitations under the License.
17  */
18 package gov.nasa.jpf.vm.choice;
19
20 import gov.nasa.jpf.Config;
21 import gov.nasa.jpf.JPFException;
22 import gov.nasa.jpf.vm.ChoiceGenerator;
23 import gov.nasa.jpf.vm.ChoiceGeneratorBase;
24 import gov.nasa.jpf.vm.IntChoiceGenerator;
25
26 import java.util.Arrays;
27 import java.util.Comparator;
28
29 /**
30  * Choice Generator that enumerates an interval of int values. Pretty simplistic
31  * implementation for now, but at least it can count up and down
32  *
33  * randomizing is handled through RandomOrderIntCG
34  */
35 public class IntIntervalGenerator extends ChoiceGeneratorBase<Integer> implements IntChoiceGenerator {
36
37   protected int min, max;
38   protected int next;
39   protected int delta;
40
41   @Override
42   public void reset () {
43     isDone = false;
44
45     if (delta == 0) {
46       throw new JPFException("IntIntervalGenerator delta value is 0");
47     }
48
49     if (min > max) {
50       int t = max;
51       max = min;
52       min = t;
53     }
54
55     if (delta > 0) {
56       next = min - delta;
57     } else {
58       next = max - delta;
59     }
60   }
61
62   /**
63    *  don't use this since it is not safe for cascaded ChoiceGenerators
64    * (we need the 'id' to be as context specific as possible)
65    */
66   @Deprecated public IntIntervalGenerator(int min, int max){
67     this("?", min, max);
68   }
69
70   @Deprecated public IntIntervalGenerator(int min, int max, int delta){
71     this("?", min, max, delta);
72   }
73
74   public IntIntervalGenerator(String id, int min, int max, int delta) {
75     super(id);
76
77     this.min = min;
78     this.max = max;
79     this.delta = delta;
80
81     reset();
82   }
83
84   public IntIntervalGenerator(String id, int min, int max) {
85     this(id, min, max, 1);
86   }
87
88   public IntIntervalGenerator(Config conf, String id) {
89     super(id);
90     min = conf.getInt(id + ".min");
91     max = conf.getInt(id + ".max");
92     delta = conf.getInt(id + ".delta", 1);
93
94     reset();
95   }
96
97   @Override
98   public Integer getChoice (int idx){
99     int nChoices = getTotalNumberOfChoices();
100     if (idx >= 0 && idx < nChoices){
101       return min + idx*delta;
102     } else {
103       throw new IllegalArgumentException("choice index out of range: " + idx);
104     }
105   }
106   
107   @Override
108   public Integer getNextChoice () {
109     return new Integer(next);
110   }
111
112   @Override
113   public boolean hasMoreChoices () {
114     if (isDone) {
115       return false;
116     } else {
117       if (delta > 0) {
118         return (next < max);
119       } else {
120         return (next > min);
121       }
122     }
123   }
124
125   @Override
126   public void advance () {
127     next += delta;
128   }
129   
130   @Override
131   public int getTotalNumberOfChoices () {
132     return Math.abs((max - min) / delta) + 1;
133   }
134
135   @Override
136   public int getProcessedNumberOfChoices () {
137     if (delta > 0) {
138       if (next < min){
139         return 0;
140       } else {
141         return (Math.abs((next - min) / delta) + 1);
142       }
143     } else {
144       if (next > max){
145         return 0;
146       } else {
147         return (Math.abs((max - next) / delta) + 1);
148       }
149     }
150   }
151   
152   public boolean isAscending(){
153     return delta > 0;
154   }
155
156   /**
157    *  note this should only be called before the CG is advanced since it resets
158    *  the enumeration state 
159    */
160   public void reverse(){
161     delta = -delta;
162     reset();
163   }
164   
165   
166   public Integer[] getChoices(){
167     int n = getTotalNumberOfChoices();
168     Integer[] vals = new Integer[n];
169     int v = (delta > 0) ? min : max;
170     
171     for (int i=0; i<n; i++){
172       vals[i] = v;
173       v += delta;
174     }
175     
176     return vals;
177   }
178
179   @Override
180   public boolean supportsReordering(){
181     return true;
182   }
183   
184   @Override
185   public ChoiceGenerator<Integer> reorder (Comparator<Integer> comparator){
186     Integer[] vals = getChoices();
187     Arrays.sort(vals, comparator);
188     
189     return new IntChoiceFromList(id, vals);
190   }
191   
192   @Override
193   public String toString () {
194     StringBuilder sb = new StringBuilder(getClass().getName());
195     sb.append("[id=\"");
196     sb.append(id);
197     sb.append('"');
198
199     sb.append(",isCascaded:");
200     sb.append(isCascaded);
201
202     sb.append(",");
203     sb.append(min);
204     sb.append("..");
205     sb.append(max);
206     sb.append(",delta=");
207     if (delta > 0) {
208       sb.append('+');
209     }
210     sb.append(delta);
211     sb.append(",cur=");
212     sb.append(getNextChoice());
213     sb.append(']');
214     return sb.toString();
215   }
216
217   @Override
218   public Class<Integer> getChoiceType() {
219     return Integer.class;
220   }
221
222   @Override
223   public ChoiceGenerator<Integer> randomize() {
224     return new RandomOrderIntCG(this);
225   }
226 }