Looking for Specman methods to get first/next/last enumerated value - specman

Are there built-in methods in Specman that give me the value of the first, last, and next value of an enumerated variable?
For example:
type color_e: [blue, green, red, yellow, orange];`
var color: color_e;
color = <want to assign first value of color_e>; //blue
…
color = <next value>; //which is green

you can use the all_values() method, which returns a list of all value of the enumerated type. You can then play with the list as you want.
example:
type color : [RED, BLUE, GREEN];
extend color : [BLACK, CYAN];
extend sys {
run() is also {
var x : color;
foreach in all_values(color) {
x = it;
print x;
};
};
};
Running the test ...
x = RED
x = BLUE
x = GREEN
x = BLACK
x = CYAN

I got the following reflection solution, but woner if there is an easier way.
<'
----------------------------------------------------------------------
-- Define an enumerated type and populate
----------------------------------------------------------------------
type color_e : [blue, green, red, yellow, orange];
----------------------------------------------------------------------
-- Extend sys
----------------------------------------------------------------------
extend sys {
----------------------------------------------------------------------
-- Use the reflection facility to get the number of labels in an
-- enumerated type
----------------------------------------------------------------------
get_num_labels(enum_item: string) : int is {
var size : int; -- number of labels defined in the enumerated type
-- Find the type if defined
for each (t) in rf_manager.get_user_types() {
if t is a rf_enum and t.get_name() == enum_item {
-- return the size of the list
result = t.as_a(rf_enum).get_items().size();
}; // if t is a rf_en...
}; // for each (t) in...
}; // get_num_labels( ...
----------------------------------------------------------------------
-- Use the reflection facility to return the value of the
-- label defined in an enumerated type at a particular index
----------------------------------------------------------------------
get_enum_label_value(enum_item: string, idx: int) : int is {
var size : int; -- number of labels defined in the enumerated type
-- Find the type if defined
for each (t) in rf_manager.get_user_types() {
if t is a rf_enum and t.get_name() == enum_item {
-- get the size of the list
size = get_num_labels(enum_item);
-- return the value of the item in the list at the specified index if legal
if (idx < size) {
result = t.as_a(rf_enum).get_items()[idx].get_value();
} else {
dut_errorf("Index requested is greater than the number of labels in the enumerated type %s\n",enum_item);
};
}; // if t is a rf_en...
}; // for each (t) in...
}; // get_enum_label_value( ...
----------------------------------------------------------------------
-- Extend the run phase
----------------------------------------------------------------------
run() is also {
var color : color_e;
var size : int;
size = get_num_labels("color_e");
messagef (NONE, "Enumerated type color_e has %d labels, and they are...\n", size);
for i from 0 to (size-1) {
color = get_enum_label_value("color_e",i).as_a(color_e);
messagef (NONE, "%s\n", color);
}; -- for
}; // run is also
}; // extend sys
'>

Another possible solution (in addition to all_values()) is with reflection. Given a rf_enum, we can call its get_items() method to get a list of all enum items.
However, there are some differences between the refleciton soluition and all_values(), which are important to know.
One difference is that if some enum items are given explicit numeric values, not necessarily in increasing order, then all_values() will return the values in increasing order, but rf_enum.get_items() will return the items in the order of declaration.
For example, if we have:
type foo: [A=5, B, C=1, D];
then all_values(foo) will return C, D, A, B (in this order - according to the respective numeric values 1, 2, 5, 6), but rf_manager.get_type_by_name("foo").as_a(rf_enum).get_items() will return A, B, C, D.
If you want to get the reflection result sorted by the numeric values, you can do, for example, rf_manager.get_type_by_name("foo").as_a(rf_enum).get_items().sort(it.get_value()).
Another difference is that when we have several enumerated types based on each other, with different generative sub-ranges, then all_values() for a specific type will return only values that belong to that types's generative range, but rf_enum.get_items() will return all items.
For example:
type t1: [A, B, C, D];
type t2: t1[A..B];
type t3: t2;
extend t2: [E];
With this example, rf_enum.get_items() will return A, B, C, D, E for any of t1, t2, or t3. But all_values() will give different results, according to the generative range of each type. all_values(t1) will return A, B, C, D; all_values(t2) will return A, B, E; and all_values(t3) will return A, B.

Related

Swift Index and it's implementation

I'm new to programming. I was trying to understand how indices work in swift. This is the following code from swift documents.
converted into function.
func ind(){
var c = [10, 20, 30, 40, 50] //index = [0:5]
var i = c.startIndex //i = [0]
while i != c.endIndex { // i!= [5] , while i not equal to [5]
c[i] /= 5
i = c.index(after: i)
}
print(c) // [2,4,6,8,10]
}
the code line i = c.index(after: i) doesn't seems to make sense to me. "after" means the character of string after the string.index, but because we initialized the 'i' to be zero(0) the output should stay [4 and onwards]. secondly, if i replace the i let's say with integer 2. the loop keeps repeating itself. why? Thank you in advance for your time
after means the next element on your list in this context.
An index is more general and is not limited to String.
In addition, an index can have different types depending on the structure that you are manipulating.
For instance:
var c1 = [10, 20, 30, 40, 50] //
var i1 = c1.startIndex
// Print: Int
print(type(of: i1))
var c2 = "Hello" //
var i2 = c2.startIndex
// Print: Index
print(type(of: i2))
You can even create your own index for a specific type, as long as you provide a way to compute the next index.
Thus, in your code for this particular example, the index is of type Int.
If you change the value of i to be the constant 2, you can never equal the value of the end index (which is 5 here).
Then, your loop will never end.

How to map inputs to outputs with same output and uniform distribution guarantees?

I have a set of inputs (in my case Strings) of variable size N, that I need to map to a set of outputs (in my case indexes of an array) of fixed size M. So, I basically need a function like:
fn map(input: String) -> usize;
I need to guarantee 2 things:
For any input X I must always return the same output Y. For example: every time I pass the string "hello" to my function the returned value must always be the same, for example 1.
The distribution of the values returned must be uniform, that is, for an infinite number of inputs, the average of the same returned values must be the same. For example, if I have M = 4 different values to return, and I have N = 100 different inputs, the number of inputs mapped to each output must be ideally equal to 25.
I came up with the following piece of code:
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
fn main() {
let bucket = Bucket::new(5);
let inputs = ["hello", "world", "house", "hi"];
for input in &inputs {
let output = bucket.get(input);
assert_eq!(output, bucket.get(input));
println!("{} -> {}", input, output);
}
}
pub struct Bucket {
values: Vec<usize>,
}
impl Bucket {
pub fn new(size: usize) -> Self {
let values = (0..size).collect();
Bucket { values }
}
pub fn get<T: Hash>(&self, id: &T) -> usize {
let mut hasher = DefaultHasher::new();
Hash::hash(id, &mut hasher);
let index = (hasher.finish() % self.values.len() as u64) as usize;
self.values[index]
}
}
Link to Playground
I think that the above code guarantees the 1st point (always same output for same input), but not necessarily the 2nd (uniformity of the distribution).
Is there a fast implementation of such a function so that both points are guaranteed?
I think you are correct that the 1st point is ok with your implementation.
Regarding the 2nd point: It depends on what DefaultHasher does. In practice it may be good enough, but there is another technique that will lead to your requirement fulfilled:
Have a counter m, initially 0.
Have a HashMap mapping String to usize.
Whenever you want to get the result, look up the given string in the HashMap:
If the string is already present, return the associated value.
If the string is not already present:
Add a new entry to the HashMap that maps the given string to the current value of m.
Increment m by 1.
If m==M, reset m to 0.

Write the method that takes four integer arguments and returns true if and only if at least three of the four values are the same

Write the method public static boolean atLeastThreeMatch(int a,
int b, int c, int d) that takes four integer arguments and returns true if and only if at least three of the four values are the same. For example, if the values passed in are 5, 3, 5, 5, it would return
true. If the values passed in are 7, 3, 7, 9, it would return false.
To complete the task I wrote every possible condition that would satisfy the desired output. I didn't like doing it that way and I feel there is an easier way to acquire the desired output. Any thoughts?
cehck below code snippet in which Set is preserving all input values. Set contains only distinct values so if set contains less/equal to 2 values that means atleast three values are equal.
public boolean atLeastThreeMatch(int a, int b, int c, int d) {
List<Integer> values = Arrays.asList(a, b, c, d);
Set<Integer> counter = new HashSet<Integer>();
counter.addAll(values);
if(counter.size() <=2){
return true;
} else {
return false;
}
}
Try to create a counter that counts the equalities between numbers. For example:
int counter=0;
if(num1 == num2)
counter++;
At last:
return counter==3;

How to check if two sets are identical in Swift?

I am using Swift and have two sets, say:
var setA: set<Int>
var setB: set<Int>
How to compare these two sets to see if they are identical (having the same elements regardless of the order)?
Set conforms to Equatable, so you can just do this:
if setA == setB {
...
}
"a set A is a subset of a set B, or equivalently B is a superset of A, if A is "contained" inside B, that is, all elements of A are also elements of B. A and B may coincide."
There fore you could check if A is a subset of B and vise versa.
let abcSet: Set = ["Chips", "Sandwiches", "Salad"]
var foodSet = Set(["Salad", "Chips", "Sandwiches"])
abcSet.isSubsetOf(foodSet); // true
foodSet.isSubsetOf(abcSet); // true

How do you assign a slice of numbers to an array in swift

x is an object that holds an array called point.
x implements the subscript operator so you can do things, like x[i] to get the array's ith element (of type T, which is usually an Int or Double).
This is what I want to do:
x[0...2] = [0...2]
But I get an error that says ClosedInterval<T> is not convertible to Int/Double.
Edit1:
Here is my object x:
let x = Point<Double>(dimensions:3)
For kicks and giggles: define x as [1.0,2.0,0.0]
I can get the first n elements via x[0...2].
What I want to know is how to update x[0...2] to hold [0.0, 0.0.0.0] in one fell swoop. Intuitively, I would want to do x[0...2] = [0...2]. This does not work as can be seen in the answers. I want to update x without iteration (on my end) and by hiding the fact that x is not an array (even though it is not).
[0...2] is an array with one element which, at best, will be a Range<Int> from 0 through 2. You can't assign that to a slice containing, say, Ints.
x[0...2] on the other hand is (probably) a slice, and Sliceable only defines a get subscript, not a setter. So even if the types were more compatible - that is, if you tried x[0...2] = 0...2, which at least is attempting to replace a range within x with the values of a similarly-sized collection - it still wouldn't work.
edit: as #rintaro points out, Array does support a setter subscript for ranges – so if x were a range you could do x[0...2] = Slice(0...2) – but it has to be a slice you assign, so I'd still go with replaceRange.
If what you mean is you want to replace entries 0 through 2 with some values, what you want is replaceRange, as long as your collection conforms to RangeReplaceableCollection (which, for example, Array does):
var x = [0,1,2,3,4,5]
var y = [200,300,400]
x.replaceRange(2..<5, with: y)
// x is now [0,1,200,300,400,5]
Note, the replaced range and y don't have to be the same size, the collection will expand/contract as necessary.
Also, y doesn't have to an array, it can be any kind of collection (has to be a collection though, not a sequence). So the above code could have been written as:
var x = [0,1,2,3,4,5]
var y = lazy(2...4).map { $0 * 100 }
x.replaceRange(2..<5, with: y)
edit: so, per your edit, to in-place zero out an array of any size in one go, you can do:
var x = [1.0,2.0,0.0]
// range to replace is the whole array's range,
// Repeat just generates any given value n times
x.replaceRange(indices(x), with: Repeat(count: x.count, repeatedValue: 0.0))
Adjust the range (and count of replacing entries) accordingly if you want to just zero out a subrange.
Given your example Point class, here is how you could implement this behavior assuming it's backed by an array under the hood:
struct Point<T: FloatLiteralConvertible> {
private var _vals: [T]
init(dimensions: Int) {
_vals = Array(count: dimensions, repeatedValue: 0.0)
}
mutating func replaceRange
<C : CollectionType where C.Generator.Element == T>
(subRange: Range<Array<T>.Index>, with newElements: C) {
// just forwarding on the request - you could perhaps
// do some additional validation first to ensure dimensions
// aren't being altered...
_vals.replaceRange(subRange, with: newElements)
}
}
var x = Point<Double>(dimensions:3)
x.replaceRange(0...2, with: [1.1,2.2,3.3])
You need to implement subscript(InvervalType) to handle the case of multiple assignments like this. That isn't done for you automatically.