Passing a value by ref to an IENumerator function? - c#

To clarify I'm doing this in Unity3D, which may or may not be important?
I'm trying to figure out if I can pass a value by ref to an IEnumerator function that does not yield. If I try to do it with one that yields, VS2010 complains ("Iterators cannot have ref or out parameters"), but, if I wrap the call up with a similar IEnumerator function that calls the yielding function, but does not yield itself, the error goes away and things appear to work. I'm trying to find out if I'm in unexpected behavior land or if this is normal behavior.
Here's an example of what I'm doing:
IEnumerator Wrapper(ref int value)
{
int tmp = ++value; // This is the ONLY place I want the value
return Foo(tmp); // of the ref parameter to change!
} // I do _NOT_ want the value of the ref
// parameter to change in Foo()!
IENumerator Foo(int value)
{
// blah blah
someFunc(value);
someSlowFunc();
yield return null;
yield return null;
}

Looks good. The top function just returns an IEnumerator - but is otherwise a normal function. The bottom function is an IEnumerator [transformed into a funky class by the compiler] and as such cannot have a ref value.
The top function could have been written as such:
void Wrapper(ref int value, out IEnumerator coroutine)
{
int tmp = ++value;
coroutine = Foo(tmp);
}
This is a little more messy - but it shows how this is a normal function that deals with two pieces of data. A int passed by referance, and a IEnumerator [just a class] that it returns [in this example by using out].
Supplemental: This is how stuff works behind the scenes:
static void Main(string[] args)
{
//Lets get the 'IEnumerable Class' that RandomNum gets compiled down into.
var IEnumeratorClass = RandomNum(10, 10);
//All an IEnumerable is is a class with 'GetEnumerator'... so lets get it!
var IEnumerableClass = IEnumeratorClass.GetEnumerator();
//It can be used like so:
while (IEnumerableClass.MoveNext())
{
Console.WriteLine(IEnumerableClass.Current);
}
Console.WriteLine(new String('-', 10));
//Of course, that's a lot of code for a simple job.
//Luckily - there's some nice built in functionality to make use of this.
//This is the same as above, but much shorter
foreach (var random in RandomNum(10, 10)) Console.WriteLine(random);
Console.WriteLine(new String('-', 10));
//These simple concepts are behind Unity3D coroutines, and Linq [which uses chaining extensively]
Enumerable.Range(0, 100).Where(x => x % 2 == 0).Take(5).ToList().ForEach(Console.WriteLine);
Console.ReadLine();
}
static Random rnd = new Random();
static IEnumerable<int> RandomNum(int max, int count)
{
for (int i = 0; i < count; i++) yield return rnd.Next(i);
}
//This is an example of what the compiler generates for RandomNum, see how boring it is?
public class RandomNumIEnumerableCompiled : IEnumerable<int>
{
int max, count;
Random _rnd;
public RandomNumIEnumerableCompiled(int max, int count)
{
this.max = max;
this.count = count;
_rnd = rnd;
}
IEnumerator IEnumerable.GetEnumerator()
{
return new RandomNumIEnumeratorCompiled(max, count, rnd);
}
IEnumerator<int> IEnumerable<int>.GetEnumerator()
{
return new RandomNumIEnumeratorCompiled(max, count, rnd);
}
}
public class RandomNumIEnumeratorCompiled : IEnumerator<int>
{
int max, count;
Random _rnd;
int current;
int currentCount = 0;
public RandomNumIEnumeratorCompiled(int max, int count, Random rnd)
{
this.max = max;
this.count = count;
_rnd = rnd;
}
int IEnumerator<int>.Current { get { return current; } }
object IEnumerator.Current { get { return current; } }
public bool MoveNext()
{
if (currentCount < count)
{
currentCount++;
current = rnd.Next(max);
return true;
}
return false;
}
public void Reset() { currentCount = 0; }
public void Dispose() { }
}

Related

How to make loot table not repeat items in Unity?

I am looking to randomly generate 3 items using a loot table. The loot table currently works as expected, it will randomly generate an item based on the item's rarity. However, I don't want there to be duplicates of the same item. How can I set this up? This script is currently attached to 3 separate GameObject item pedestals.
using System.Collections.Generic;
using UnityEngine;
public class ShopItemSpawner : MonoBehaviour
{
[System.Serializable]
public class DropItem
{
public string name;
public GameObject item;
public int dropRarity;
}
public List<DropItem> ShopItemPool = new List<DropItem>();
private void Start()
{
int itemWeight = 0;
for (int i = 0; i < ShopItemPool.Count; i++)
{
itemWeight += ShopItemPool[i].dropRarity;
}
int randomValue = Random.Range(0, itemWeight);
for (int j = 0; j < ShopItemPool.Count; j++)
{
if (randomValue <= ShopItemPool[j].dropRarity)
{
Instantiate(ShopItemPool[j].item, transform.position, Quaternion.identity);
return;
}
randomValue -= ShopItemPool[j].dropRarity;
}
}
}
You could clone the ShopItemPool list and with each item rolled you remove that item from the list. You then need to go all over again by recalculating the total weight.
I find it useful to have a general purpose class for randomizing items with weights, it allows you do this this:
var randomizer = new WeightRandomizer<DropItem>();
foreach (var shopItem in ShopItemPool) {
randomizer.Add(shopItem, shopItem.dropRarity);
}
randomizer.Roll(); // Get a random element based on weight.
randomizer.Take(); // Get a random element based on weight and remove it from the randomizer.
General Purpose Weight Randomizer:
public class WeightRandomizer<T> {
[Serializable]
public class WeightedElement<T> {
public T value;
public int weight;
public WeightedElement (T value, int weight) {
this.value = value;
this.weight = weight;
}
}
private readonly List<WeightedElement<T>> elements = new();
public void Add (T value, int weight) => elements.Add(new WeightedElement<T>(value, weight));
public void AddRange (IEnumerable<WeightedElement<T>> weightedElements) => elements.AddRange(weightedElements);
public int TotalWeight() => elements.Sum(x => x.weight);
public T Roll() => Pick(false);
public T Take() => Pick(true);
private T Pick (bool remove) {
if (elements.Count == 0) {
Debug.LogWarning($"{nameof(WeightRandomizer<T>)} is missing elements.");
return default(T);
}
var roll = Random.Range(0, TotalWeight());
var selectedIndex = elements.Count - 1;
var selected = elements[selectedIndex].value;
for (var i = 0; i < elements.Count; i++) {
var element = elements[i];
// Found an element with a low enough value.
if (roll < element.weight) {
selected = element.value;
selectedIndex = i;
break;
}
// Keep searching for an element with a lower value.
roll -= element.weight;
}
// Sometimes we want to take and remove the element from the pool.
if (remove) elements.RemoveAt(selectedIndex);
return selected;
}
}

Radix sort in singly-linked list C#

I'm trying to do a Radix sort in a Linked list class. I found radix sort algorithm for array and am trying to change it to work with my linked list. However, I'm a bit struggling. The code I'm trying to change is taken from http://www.w3resource.com/csharp-exercises/searching-and-sorting-algorithm/searching-and-sorting-algorithm-exercise-10.php I tested the code with an array and it worked. Does anybody have any ideas how to make radix sort work in a linked list?
//abstract class
abstract class DataList
{
protected int length;
public int Length { get { return length; } }
public abstract double Head();
public abstract double Next();
public abstract void Swap(int a, int b);
public void Print(int n)
{
Console.Write("{0} ", Head());
for (int i = 1; i < n; i++)
Console.Write("{0} ", Next());
Console.WriteLine();
}
}
//linked list class
class LinkedList : DataList
{
class MyLinkedListNode
{
public MyLinkedListNode nextNode { get; set; }
public int data { get; set; }
public MyLinkedListNode(int data)
{
this.data = data;
}
public MyLinkedListNode()
{
this.data = 0;
}
}
MyLinkedListNode headNode;
MyLinkedListNode prevNode;
MyLinkedListNode currentNode;
public LinkedList(int n, int min, int max)
{
length = n;
Random rand = new Random();
headNode = new MyLinkedListNode(rand.Next(min, max));
currentNode = headNode;
for (int i = 1; i < length; i++)
{
prevNode = currentNode;
currentNode.nextNode = new MyLinkedListNode(rand.Next(min, max));
currentNode = currentNode.nextNode;
}
currentNode.nextNode = null;
}
public LinkedList()
{
headNode = new MyLinkedListNode();
currentNode = headNode;
}
public override double Head()
{
currentNode = headNode;
prevNode = null;
return currentNode.data;
}
public override double Next()
{
prevNode = currentNode;
currentNode = currentNode.nextNode;
return currentNode.data;
}
public override void Swap(int a, int b)
{
prevNode.data = a;
currentNode.data = b;
}
//my radix sort
public void radixSort()
{
int j = 0;
LinkedList tmp = new LinkedList();
for (int shift = 31; shift > -1; --shift)
{
//I try to go trough old list
MyLinkedListNode current = headNode;
while (current != null)
{
bool move = (current.data << shift) >= 0;
//I found this expression somewhere and I'm trying to use it to form a new Linked list (tmp)
if (shift == 0 ? !move : move)
;
else
{
if (tmp.headNode == null)
tmp.headNode = currentNode;
else
{
tmp.currentNode.nextNode = current;
//infinite loop happens on the commented line
//tmp.currentNode = tmp.currentNode.nextNode;
j++;
}
current = current.nextNode;
}
}
}
}
Following the C# radix sort example, you need an array of ten lists. Move nodes from the original list into the ten lists, appending a node with least signfificant digit == '0' into array_of_lists[0], '1' into array_of_list[1], and so on. After the original list is emptied, then concatenate the array of lists back into the original list and repeat for the next to least significant digit. Repeat the process until all the digits are handled.
You could use a larger base, such as base 16, where you would use an array of 16 lists. You can then select each "digit" using a shift and an and .

Cannot mimic performance of ConcurrentStack when using same code implementation

I am learning about writing concurrent data structures and looking at the ConcurrentStack implementation as a learning exercise. As a starting point I have created a copy of the ConcurrentStack implementation by using IlSpy to decompile it into C#. I have limited myself to investigating and using just the Push and TryPop methods for the time being.
But my implementation is significantly slower than using the original.
My testing uses 4 threads (on a single socket, 4 core CPU) with thread affinity for each thread against a different core. Each thread performs 1,000,000 loops and each loop does three pushes and three pops. Running the testing many times the average time to complete all the threads is...
ConcurrentStack => 445ms
Clone of Push/TryPop => 670ms
So even though the code, as far as I can tell, is identical between the two the clone is about 50% slower. I run the testing 500 times in a run and take the average over all the runs. So I do not believe the issue is the initial JIT'ing of the code.
Any ideas why a copy of the methods would be so much slower?
C# Implementation
(For the sake of completeness I have provided the C# console app code that can be used to replicate the result. For anyone interesting in seeing if they get the same result as me.)
class Program
{
static void Main(string[] args)
{
int processors = Environment.ProcessorCount;
Console.WriteLine("Processors: {0}", processors);
List<Type> runnersT = new List<Type>() { typeof(ThreadRunnerConcurrent),
typeof(ThreadRunnerCASStack)};
int cycles = 500;
foreach (Type runnerT in runnersT)
{
long total = 0;
for (int i = 0; i < cycles; i++)
{
// Create a thread runner per processor
List<ThreadRunner> runners = new List<ThreadRunner>();
for (int j = 0; j < processors; j++)
{
ThreadRunner runner = Activator.CreateInstance(runnerT) as ThreadRunner;
runner.Processor = j;
runners.Add(runner);
}
// Start each runner going
Stopwatch sw = new Stopwatch();
sw.Start();
runners.ForEach((r) => r.Start());
// Wait for all the runners to exit
runners.ForEach((r) => r.Join());
runners.ForEach((r) => r.Check());
sw.Stop();
total += sw.ElapsedMilliseconds;
}
Console.WriteLine("{0} Average: {1}ms", runnerT.Name, (total / cycles));
}
Console.WriteLine("Finished");
Console.ReadLine();
}
}
abstract class ThreadRunner
{
private int _processor;
private Thread _thread;
public ThreadRunner()
{
}
public int Processor
{
get { return _processor; }
set { _processor = value; }
}
public void Start()
{
_thread = new Thread(new ParameterizedThreadStart(Run));
_thread.Start();
}
public void Join()
{
_thread.Join();
}
public abstract void Check();
protected abstract void Run(int cycles);
private void Run(object param)
{
SetAffinity();
Run(1000000);
}
private void SetAffinity()
{
#pragma warning disable 618
int osThreadId = AppDomain.GetCurrentThreadId();
#pragma warning restore 618
// Set the thread's processor affinity
ProcessThread thread = Process.GetCurrentProcess().Threads.Cast<ProcessThread>().Where(t => t.Id == osThreadId).Single();
thread.ProcessorAffinity = new IntPtr(1L << Processor);
}
}
class ThreadRunnerConcurrent : ThreadRunner
{
private static ConcurrentStack<int> _stack = new ConcurrentStack<int>();
protected override void Run(int cycles)
{
int ret;
for (int i = 0; i < cycles; i++)
{
_stack.Push(i);
_stack.Push(i);
while (!_stack.TryPop(out ret)) ;
_stack.Push(i);
while (!_stack.TryPop(out ret)) ;
while (!_stack.TryPop(out ret)) ;
}
}
public override void Check()
{
if (_stack.Count > 0)
Console.WriteLine("ThreadRunnerConcurrent has entries!");
}
}
class ThreadRunnerCASStack : ThreadRunner
{
private static CASStack<int> _stack = new CASStack<int>();
protected override void Run(int cycles)
{
int ret;
for (int i = 0; i < cycles; i++)
{
_stack.Push(i);
_stack.Push(i);
while (!_stack.TryPop(out ret)) ;
_stack.Push(i);
while (!_stack.TryPop(out ret)) ;
while (!_stack.TryPop(out ret)) ;
}
}
public override void Check()
{
if (_stack.Count > 0)
Console.WriteLine("ThreadRunnerCASStack has entries!");
}
}
class CASStack<T>
{
private class Node
{
internal readonly T m_value;
internal CASStack<T>.Node m_next;
internal Node(T value)
{
this.m_value = value;
this.m_next = null;
}
}
private volatile CASStack<T>.Node m_head;
public void Push(T item)
{
CASStack<T>.Node node = new CASStack<T>.Node(item);
node.m_next = this.m_head;
if (Interlocked.CompareExchange<CASStack<T>.Node>(ref this.m_head, node, node.m_next) == node.m_next)
return;
PushCore(node, node);
}
private void PushCore(Node head, Node tail)
{
SpinWait spinWait = default(SpinWait);
do
{
spinWait.SpinOnce();
tail.m_next = this.m_head;
}
while (Interlocked.CompareExchange<CASStack<T>.Node>(ref this.m_head, head, tail.m_next) != tail.m_next);
}
public bool TryPop(out T result)
{
CASStack<T>.Node head = this.m_head;
if (head == null)
{
result = default(T);
return false;
}
if (Interlocked.CompareExchange<CASStack<T>.Node>(ref this.m_head, head.m_next, head) == head)
{
result = head.m_value;
return true;
}
return TryPopCore(out result);
}
private bool TryPopCore(out T result)
{
CASStack<T>.Node node;
if (TryPopCore(1, out node) == 1)
{
result = node.m_value;
return true;
}
result = default(T);
return false;
}
private int TryPopCore(int count, out CASStack<T>.Node poppedHead)
{
SpinWait spinWait = default(SpinWait);
int num = 1;
Random random = new Random(Environment.TickCount & 2147483647);
CASStack<T>.Node head;
int num2;
while (true)
{
head = this.m_head;
if (head == null)
break;
CASStack<T>.Node node = head;
num2 = 1;
while (num2 < count && node.m_next != null)
{
node = node.m_next;
num2++;
}
if (Interlocked.CompareExchange<CASStack<T>.Node>(ref this.m_head, node.m_next, head) == head)
goto Block_5;
for (int i = 0; i < num; i++)
spinWait.SpinOnce();
num = (spinWait.NextSpinWillYield ? random.Next(1, 8) : (num * 2));
}
poppedHead = null;
return 0;
Block_5:
poppedHead = head;
return num2;
}
}
#endregion
ConcurrentStack<T> has one advantage that your CASStack<T> doesn't have, even though the code for both is identical.
ConcurrentStack<T> has an ngen'd native image installed on your computer that was compiled when you installed your .Net framework install. Your CASStack<T> is being compiled via JIT, and because JIT has to be fast, it does not perform as many optimizations as the AOT compiler in ngen.
I tested your code on my computer. Without ngen'ing your image, I got these results:
Processors: 4
ThreadRunnerConcurrent Average: 764ms
ThreadRunnerCASStack Average: 948ms
Finished
After ngening:
Processors: 4
ThreadRunnerConcurrent Average: 778ms
ThreadRunnerCASStack Average: 742ms
Finished

Assigning specific type object into an generic array

I have a generic type called Vector<T>, I created it as so, cause the T might be float or Complex :
public class Vector<T>
{
#region Properties
public ulong Length
{
get
{
return _length;
}
}
public VectorType VectorType
{
get
{
return _vectorType;
}
}
#endregion
#region Indexers
public T this[ulong index]
{
get
{
return _data[index];
}
set
{
_data[index] = value;
}
}
#endregion
#region Constructors
public Vector(VectorType vectorType, T[] data)
{
if (!((data is float[]) || (data is Complex[])))
{
throw new InvalidDataException("Data must be array of float or array of Complex");
}
_data = new T[_length = (ulong)data.Length];
for (ulong i = 0; i < _length; i++)
{
_data[i] = data[i];
}
_vectorType = vectorType;
}
public Vector(VectorType vectorType, Vector<T> vector)
{
_data = new T[_length = vector.Length];
for (ulong i = 0; i < _length; i++)
{
_data[i] = vector[i];
}
_vectorType = vectorType;
}
#endregion
#region Methods
//Unity Matrix, this vector has 1/N everywhere
public static Vector<float> e(VectorType vectorType, ulong length)
{
var data = new float[length];
for (ulong i = 0; i < length; i++)
{
data[i] = (float)1 / length;
}
var vectorE = new Vector<float>(vectorType, data);
return vectorE;
}
public float Sum()
{
float sum = 0;
if (_data is float[])
{
sum = (_data as float[]).Sum();
}
else
{
if (_data is Complex[])
{
for (ulong i = 0; i < _length; i++)
{
sum += (float)
Math.Sqrt(Math.Pow((_data[i] as Complex?).Value.Real, 2) +
Math.Pow((_data[i] as Complex?).Value.Imaginary, 2));
}
}
}
return sum;
}
public bool CheckIfSochasitc()
{
return Math.Abs(Sum() - 1) < float.Epsilon;
}
public void Normalize()
{
var sum = Sum();
if (_data is float[])
{
for (ulong i = 0; i < _length; i++)
{
float x = ((float) _data[i])/sum;
_data[i] = (T)x;
}
}
}
#endregion
#region Operators
//I omitted the code inhere to avoid overload
#endregion
#region Fields
private ulong _length;
private readonly VectorType _vectorType;
private T[] _data;
#endregion
}
public enum VectorType
{
Row,Column
}
My problem is that I have a generic array (if I can call it so) :
private T[] _data;
And I have the Normalize() method:
public void Normalize()
{
var sum = Sum();
if (_data is float[])
{
for (ulong i = 0; i < _length; i++)
{
//Here is the problem
_data[i] = ((_data[i] as float?) / sum);
}
}
}
This doesn't work saying can't cast float to T tried to search but couldn't find helpful aide, any clarification I'd be thankful.
Update :
The Sum() method always returns a float
It's not clear why you're converting to float? at all (or why you're using ulong as the index variable type...) but you just need to cast the result back to T - otherwise you can't assign it back into an array of type T[]. Additionally, you need to cast to object (in order to convert back to T:
float x = ((float) (object) data[i]) / sum;
data[i] = (T) (object) x;
You can use float? for the first line, with as, to avoid boxing - but then you need to get the non-nullable value:
float x = (data[i] as float?).Value / sum;
Both are pretty ugly :(
As noted in comments though, this sort of thing is usually an indication of the design not really being properly generic at all. We don't know what type Sum() returns, but you should consider just how "general" your type is to start with.
May be you can try this
if (typeof(_data) == float[])
{
for (ulong i = 0; i < _length; i++)
{
_data[i] = ((_data[i] as float?) / sum);
}
}

C#: How to translate the Yield Keyword

What would the MSDN sample look like without the yield keyword? You may use any example if you perfer. I would just like to understand what is going on under the hood.
Is the yield operator eagerly or lazily evaluated?
Sample:
using System;
using System.Collections;
public class List
{
public static IEnumerable Power(int number, int exponent)
{
int counter = 0;
int result = 1;
while (counter++ < exponent)
{
result = result * number;
yield return result;
}
}
static void Main()
{
// Display powers of 2 up to the exponent 8:
foreach (int i in Power(2, 8))
{
Console.Write("{0} ", i);
}
}
}
MSDN - Yield Keyword
If the yield operator is eagerly evaluated here is my guess:
public static IEnumerable Power(int number, int exponent)
{
int counter = 0;
int result = 1;
List<int> powers;
while (counter++ < exponent)
{
result = result * number;
powers.add(result);
}
return powers;
}
I have no clue what it might look like if the yield operator is lazily evaluated.
Update: Reflector gives this:
public class List
{
// Methods
public List();
private static void Main();
public static IEnumerable Power(int number, int exponent);
// Nested Types
[CompilerGenerated]
private sealed class <Power>d__0 : IEnumerable<object>, IEnumerable, IEnumerator<object>, IEnumerator, IDisposable
{
// Fields
private int <>1__state;
private object <>2__current;
public int <>3__exponent;
public int <>3__number;
private int <>l__initialThreadId;
public int <counter>5__1;
public int <result>5__2;
public int exponent;
public int number;
// Methods
[DebuggerHidden]
public <Power>d__0(int <>1__state);
private bool MoveNext();
[DebuggerHidden]
IEnumerator<object> IEnumerable<object>.GetEnumerator();
[DebuggerHidden]
IEnumerator IEnumerable.GetEnumerator();
[DebuggerHidden]
void IEnumerator.Reset();
void IDisposable.Dispose();
// Properties
object IEnumerator<object>.Current { [DebuggerHidden] get; }
object IEnumerator.Current { [DebuggerHidden] get; }
}
}
IEnumerator<object> IEnumerable<object>.GetEnumerator()
{
List.<Power>d__0 d__;
if ((Thread.CurrentThread.ManagedThreadId == this.<>l__initialThreadId) && (this.<>1__state == -2))
{
this.<>1__state = 0;
d__ = this;
}
else
{
d__ = new List.<Power>d__0(0);
}
d__.number = this.<>3__number;
d__.exponent = this.<>3__exponent;
return d__;
}
private bool MoveNext()
{
switch (this.<>1__state)
{
case 0:
this.<>1__state = -1;
this.<counter>5__1 = 0;
this.<result>5__2 = 1;
while (this.<counter>5__1++ < this.exponent)
{
this.<result>5__2 *= this.number;
this.<>2__current = this.<result>5__2;
this.<>1__state = 1;
return true;
Label_0065:
this.<>1__state = -1;
}
break;
case 1:
goto Label_0065;
}
return false;
}
First off, yield is not an operator. yield return and yield break are statements.
There are plenty of articles available on how the compiler implements iterator blocks. Start by reading the C# specification section on iterator blocks; it gives some suggestions for how an implementer of C# might want to go about it.
Next read Raymond Chen's series "The implementation of iterators in C# and its consequences"
http://www.bing.com/search?q=raymond+chen+the+implementation+of+iterators
Next, read Jon Skeet's book chapter on the subject:
http://csharpindepth.com/Articles/Chapter6/IteratorBlockImplementation.aspx
If after all that you are still interested then read my series on the design factors that went into this feature:
http://blogs.msdn.com/b/ericlippert/archive/tags/iterators/
Back in the good old days, before we had the yield operator, we used to write classes which implemented IEnumerator.
class PowerEnumerator : IEnumerator<int>
{
private int _number;
private int _exponent;
private int _current = 1;
public PowerEnumerator(int number, int exponent)
{
_number = number;
_exponent = exponent;
}
public bool MoveNext()
{
_current *= number;
return _exponent-- > 0;
}
public int Current
{
get
{
if (_exponent < 0) throw new InvalidOperationException();
return _current;
}
}
}
Or something like that. It wasn't fun, let me tell you.
Let .NET Reflector decompile it. It's a generic solution (a state machine actually), but quite complex, > 20 lines of codes if I remember correctly.
Lazy. That's the point why yield can be quite efficient.
It would be a custom implementation of IEnumerable<T>, not leaning on an existing implementation such as List<T>
Lazily.
More info available here.

Categories

Resources