Complete Managed Media Aggregation Part III : Quantum Computing in C# Today?
Whats a new Bitable? Enumerable's, Enumerator's, and now Iterator's? Oh my!
Previous Article in this Series
Introduction
I wanted to keep this article short and simple yet highlight all of things which everyone told us we wouldn't be able to do in C# but keep it short and still by the end of this article show them will be you will be able to do that and truly so much more.
The problem with understanding as I see it is that it stems from the precedent that prior knowledge stands alone in a sense like prior history it tends to repeat itself, however we as humans try to learn from our mistakes and correct them as we go. Without getting too much into evolution and and all that great stuff I just wanted to say fundamentally C# allows access to transistors which are the basis for all of the related functionality we achieve.
You can control everything about them including their state and you usually operate on them in 32 or 64 bit values at a time (even if you are only using 1 or 2 or 3 or 8 or 19 of ye given bits).
You can possibly also think about them like this if you wanted...
/// <summary>
/// v
/// </summary>
public enum QState
{
Uncertain, //Not
Certain, //Measured
Transient, //Not quite Low, but not quite High
On, //High
Off //Low
}
This is always how I like to think of things because until quantum computers are in mainstream use this will be the acceptable real of thinking; this will should suffice as an acceptable way to represent them at the current time... on or off, even though transient state is also a possibility...
None the less...
Welcome to the future!
We will cover the solutions so some of the most sought after problems in a new and puzzling (for some) way which has always been right in front of our eyes but lacked the required vision to see it clearly for some reason. I will attempt to shed light on these aspects and make you all aware of this functionality!
We will solve basic copy cat style problems for people moving from C++ to C# to allow the Iterator concept to be utilized in C#
We will also then break down the Generic Math issue in a completely new integrated way which does not involve any Dictionary or delegate creation!
We will build a Complimentor a Storage Allocator and all of the associated classes such as Bit
, MultiBit
, Bitable
GarbadgeCollector
, ICoreObject
, GlobalObject32
, GlobablObject64
and much more!
Last but not least we will allow for INLINE Common Intermediate Language Support
right in any place anywhere in C# and best of all we will do this by the end of the article and everything will be working as intended with everything in total weighing in under 80k!
In part two of this article we talked about making things
easier, Welcome to part III.
Engineering is as Engineering Does, this is typical when you see jQuery this everywhere, async this and Begin that. What it means is (in short) is that most developers are monkey see, monkey do!
They see example x they follow example x as closely as possible and choose not to deviate and thus as a result we are left with the same technology 20 years ago that we have today.
Thank the stars there are people who are innovating and genuine attempts are being made to do things easier and don’t just use jQuery (which I hate) and because it’s cool or the fad. They don’t use @this or # that. They have their own way of thinking and it may not be in line with how everyone else thinks... yet but sometimes it catches on and blows up and we start the cycle all over again.
One example of which I can immediately come up with is the guys over @ the Reactive Extensions Project!
I would have rather seen a polished version of this integrated into the Framework then the async keyword but I guess the UI folks have won again!
After all it’s them who have to sort through the tons of records in our databases, and all the other fun things no one will ever see or know or care about until something goes wrong, at which point the helpless guy who wrote the software gets a mouthful and hopefully can restrain from going *ape $h17 * and shooting up his local library....
It is like people only care about what they see on computers... Well not me and not a lot of you...
Nonetheless I digress, It is however a fact that some of the most mundane work topics stem from not being able to use the LINQ classes provided for a number of reasons.
- State - You don’t have any state with LINQ, things happen in a linear fashion and usually once the enumeration is started you have the whole kitten caboodle to deal with.
- Allocation - Therefore you cannot really use a LINQ set
efficiently without Projecting it! This means you have to call
ToArray
in most cases since iterating a set 1 by 1 when there are 10 of thousands if not more is probably not the best way.
You also can’t set the current member!
Enter Iterators..
Iterators are IEnumerable
and IEnumerator
, they control their
own state and give rise to some interesting concepts such as EnumerableSegment
which allows for offset operations on any IEnumerable
. For example say you
wanted to do "for(i= 2; i < 10 - 2; ++i) action()
" With an enumerable you
can just Skip and Take but what if you wanted a way to control where the
Skipping started when someone used Skip? What if you had 10 different
enumerables and you wanted to make them look like a single enumerable to the
observer? then this is where that class can help.
It supports C++ style patterns such as setting the Current item
(with associated events
) and other events for PreIncrement
, PostIncrement
,
SiblingIncrement
, etc..
#region Iterators
public class Iterator<T> :
EnumerableSegment<T>, //Rather then EnumerableSegment<T> Have no base class maybe and copy the logic and have Array access so iterators can set members? Maybe use caching style?
Iterator
{
#region Properties
public DateTime Started { get; internal protected set; }
public DateTime Ended { get; internal protected set; }
public Iterator Parent { get; protected set; }
public IEnumerable<T> Enumerable { get; protected set; }
public IEnumerator<T> Enumerator { get; protected set; }
#endregion
#region Overrides
public override T Current
{
get
{
Exception ex = null;
try
{
try { OnCurrentRead(); }
catch (Exception _) { ex = _; }
return base.Current;
}
finally { if (ex != null) throw ex; }
}
internal protected set
{
try { base.t = value; }
finally { CurrentAssigned(this); }
}
}
public override bool MoveNext()
{
bool error = false;
try
{
if (Index == -1) OnBegin();
try { OnPreIncrement(); }
catch { error = true; }
finally { error = error || !base.MoveNext(); }
IEnumerator<T> enumerator = Enumerator;
error = !enumerator.MoveNext();
if (!error) Current = (T)enumerator.Current;
return !error;
}
finally { OnPostIncrement(); if (error || Index > VirtualCount) OnEnd(); }
}
#endregion
#region Constructor
public Iterator() : base() { AssignEvents(this); }
public Iterator(IEnumerable<T> enumerable) : base(enumerable) { AssignEvents(this); Enumerable = enumerable; Enumerator = Enumerable.GetEnumerator(); }
public Iterator(IEnumerable<T> enumerable, int index, int count) : base(enumerable, index, count) { AssignEvents(this); Enumerable = enumerable; Enumerator = Enumerable.GetEnumerator(); }
static void AssignEvents(Iterator<T> iterator)
{
iterator.PostDecrement += IteratorPostDecrement;
iterator.PostIncrement += IteratorPostIncrement;
iterator.PreIncrement += IteratorPreIncrement;
iterator.PreDecrement += IteratorPreDecrement;
iterator.CurrentAssigned += IteratorCurrentAssigned;
iterator.CurrentRead += IteratorCurrentRead;
iterator.Begin += IteratorBegin;
iterator.End += IteratorEnd;
}
static void IteratorEnd(Iterator sender)
{
(sender as Iterator<T>).Ended = DateTime.UtcNow;
}
static void IteratorBegin(Iterator sender)
{
(sender as Iterator<T>).Started = DateTime.UtcNow;
}
static void IteratorPostIncrement(Iterator sender)
{
//Reserved
}
static void IteratorCurrentRead(Iterator sender)
{
//Reserved
}
static void IteratorCurrentAssigned(Iterator sender)
{
//Reserved
}
static void IteratorPreIncrement(Iterator sender)
{
//Reserved
}
static void IteratorPreDecrement(Iterator sender)
{
//Reserved
}
static void IteratorPostDecrement(Iterator sender)
{
//Reserved
}
static void IteratorPostIncrment(Iterator sender)
{
//Reserved
}
#endregion
#region Iterator
public static Iterator operator +(Iterator<T> it, Iterator<T> that)
{
return (it as IEnumerable<T>).Concat(that) as Iterator;
}
public static Iterator operator -(Iterator<T> it, Iterator<T> that)
{
return (it as IEnumerable<T>).Skip(that.Count) as Iterator;
}
int Iterator.VirtualCount
{
get { return base.VirtualCount; }
}
int Iterator.VirtualIndex
{
get { return base.VirtualIndex; }
}
/// <summary>
/// Set to -1 to restart the Iteration from the VirtualIndex
/// </summary>
int Iterator.CurrentIndex
{
get
{
return base.Index;
}
set
{
if (value < 0) base.Reset();
base.Index = value;
}
}
public void SetCurrent(T current) { base.Current = current; }
public T GetCurrent(T current) { return base.Current; }
#endregion
#region Events
internal void OnBegin()
{
Begin(this);
}
internal void OnEnd()
{
End(this);
}
internal void OnPreIncrement()
{
PreIncrement(this);
}
internal protected void OnPostIncrement()
{
PostIncrement(this);
}
internal void OnPreDecrement()
{
PreDecrement(this);
}
internal protected void OnPostDecrement()
{
PostDecrement(this);
}
internal protected void OnSiblingIncrement()
{
SiblingIncrement(this);
}
internal protected void OnSiblingDecrement()
{
SiblingDecrement(this);
}
internal protected void OnCurrentRead()
{
CurrentRead(this);
}
internal protected void OnCurrentAssigned()
{
CurrentAssigned(this);
}
public event IterationHanlder PreIncrement;
public event IterationHanlder PreDecrement;
public event IterationHanlder PostIncrement;
public event IterationHanlder PostDecrement;
public event IterationHanlder SiblingIncrement;
public event IterationHanlder SiblingDecrement;
public event IterationHanlder CurrentRead;
public event IterationHanlder CurrentAssigned;
public event IterationHanlder Begin;
public event IterationHanlder End;
#endregion
#region IEnumerator
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return this;
}
object System.Collections.IEnumerator.Current
{
get { return (this as Iterator<T>).Current; }
}
bool System.Collections.IEnumerator.MoveNext()
{
return (this as Iterator<T>).MoveNext();
}
void System.Collections.IEnumerator.Reset()
{
(this as Iterator<T>).Reset();
}
#endregion
#region Statics
public static void ForAll()
{
}
public static bool Any()
{
return false;
}
#endregion
}
public delegate void IterationHanlder(Iterator sender);
public interface Iterator : System.Collections.IEnumerable, System.Collections.IEnumerator, IDisposable
{
event IterationHanlder Begin;
event IterationHanlder End;
int VirtualCount { get; }
int VirtualIndex { get; }
int CurrentIndex { get; set; }
event IterationHanlder PreIncrement;
event IterationHanlder PreDecrement;
event IterationHanlder PostIncrement;
event IterationHanlder PostDecrement;
event IterationHanlder SiblingIncrement;
event IterationHanlder SiblingDecrement;
event IterationHanlder CurrentRead;
event IterationHanlder CurrentAssigned;
}
#endregion
In short, it’s main purpose was to do away with petty memory allocations
which caused paging when performed frequently. This can also be solved using a "ScratchTable
' pattern where you only take note of the index in where things are being changed but the above was more natural to implement for the example without giving too much away " />
Say you wanted to insert a byte into a stream, well you might say "can't you just write the byte to the stream then?" Well what if you wanted the stream to remain untouched? This way a Save method would be able to take all changes and integrate them into a Stream when you decided and without paging or allocating anything more then what was required and only one time?
This is where the EnumerableByteStream
helps... it saves those
allocations for any IEnumerable<byte>
you want to put into a stream and then
when you enumerate the stream you only enumerate the stream up to the position
it was written in, reading past that point you are actually just enumerating
the yielded Enumerable bytes which have been queued in memory with the embedded use of
the IEnumerator
interface...
#region EnumerableByteStream
public class EnumerableByteStream : EnumerableSegment<byte>, IEnumerable<byte>, IEnumerator<byte>, IList<byte>
{
protected int m_Current;
internal protected System.IO.Stream m_Stream;
internal protected bool m_Disposed;
internal EnumerableByteStream m_Self;
bool Initialized { get { return CurrentInt != -1; } }
public int CurrentInt { get { return Current; } }
public EnumerableByteStream(byte Byte) : this(Byte.Yield()) { }
public EnumerableByteStream(IEnumerable<byte> bytes, int? index = null, int? count = null)
: base(bytes, index ?? 0, (int)(count.HasValue ? count - index : -1)) { }
public EnumerableByteStream(System.IO.Stream stream, int? index = null, int? count = null)
: this(null as IEnumerable<byte>, index ?? (int)stream.Position, count ?? (int)stream.Length)
{
m_Stream = stream;
m_Current = Current;
}
//public override int Remaining
//{
// get
// {
// return (int)(m_Stream .Length + base.Remaining);
// }
//}
public IEnumerable<byte> ToArray(int offset, int count, byte[] buffer)
{
if (offset < 0) throw new ArgumentOutOfRangeException("offset must refer to a location within the buffer.");
else if (count + offset > Length) throw new ArgumentOutOfRangeException("count must refer to a location within the buffer with respect to offset.");
if (count == 0) return Enumerable.Empty<byte>();
buffer = buffer ?? new byte[count];
int len = count;
while ((len -= m_Stream.Read(buffer, offset, count)) > 0
&&
Remaining > 0)
{
//
}
return buffer;
}
public IEnumerator<byte> GetEnumerator()
{
if (CurrentInt == -1) MoveNext();
while (!m_Disposed && MoveNext()) yield return Current = (byte)m_Current;
}
public override bool MoveNext()
{
if (base.MoveNext()) return CoreGetEnumerator() != -1;
return false;
}
int CoreGetEnumerator(long direction = 1)
{
if (!m_Disposed && m_Stream.Position < Count) return Current = (byte)(m_Current = m_Stream.ReadByte());
else unchecked { return Current = (byte)(m_Current = -1); }
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return GetEnumerator(); }
internal protected long CoreIndexOf(IEnumerable<byte> items, int start = -1, int count = -1)
{
if (m_Stream == null || m_Disposed || items == null || items == Enumerable.Empty<byte>() || count == 0) return -1;
if (count == -1) count = items.Count();
if (!Initialized && !MoveNext()) return -1;
if (start != -1 && start + count > Count) return -1;
else if (start != -1 && start != Position) if (m_Stream.CanSeek) m_Stream.Seek(start, System.IO.SeekOrigin.Begin);
else return -1;//throw new InvalidOperationException("The underlying stream must be able to seek if the start index is specified and not equal to -1");
using (IEnumerator<byte> itemPointer = items.Skip(start).Take(count).GetEnumerator())
{
if (!itemPointer.MoveNext()) return -1;
//We start at
long position = Position;
if (start == -1 && m_Stream.CanSeek && m_Stream.Position != 0 && itemPointer.Current != Current)
{
Reset();
}
else start = (int)m_Stream.Position;
//While there is an itemPointer
while (itemPointer != null)
{
int j = count;
while (itemPointer.Current == Current && (--j > 0))
{
if (!itemPointer.MoveNext()) break;
}
//The match is complete
if (j == 0)
{
//If CanSeek and moved the position and we will go back to where we were
//if (m_Stream.CanSeek && position != Position) m_Stream.Seek(position, System.IO.SeekOrigin.Begin); //Curent and Begin need to be aware...
return m_Stream.Position - 1; //-1 Because a byte was read to obtain Current
}
if (!MoveNext()) break;
}
if (start == -1 && m_Stream.CanSeek && position != Position) m_Stream.Seek(position, System.IO.SeekOrigin.Begin);
return -1;
}
}
internal protected int CoreIndexOf(byte item, int start, int count) { return (int)CoreIndexOf(item.Yield(), start, count); }
public virtual int IndexOf(byte item)
{
return CoreIndexOf(item, -1, 1);
}
public virtual void Insert(int index, byte item)
{
//System.IO.MemoryStream newMemory = new System.IO.MemoryStream(Count + 1);
//System.IO.Stream oldMemory;
//using (EnumerableByteStream preSegment = new EnumerableByteStream(m_Stream, 0, index - 1))
//{
// using (EnumerableByteStream postSegment = new EnumerableByteStream(m_Stream, index - 1, Count - index + 1))
// {
// foreach (byte b in preSegment) newMemory.WriteByte(b);
// newMemory.WriteByte(item);
// foreach (byte b in postSegment) newMemory.WriteByte(b);
// }
//}
//oldMemory = m_Stream;
//m_Stream = newMemory;
//oldMemory.Dispose();
//Linked stream around origional bytes up to index
//additional byte
//Rest of old stream
//long preInsert = m_Stream.Position;
EnumerableByteStream newPointer = new EnumerableByteStream((new EnumerableByteStream(m_Stream, 0, index - 1) as IEnumerable<byte>).
Concat(item.Yield()).
Concat(new EnumerableByteStream(m_Stream, index - 1, Count - index + 1) as IEnumerable<byte>));
//m_Stream = LinkedStream.LinkAll(new EnumerableByteStream(m_Stream, 0, index - 1), new EnumerableByteStream(item), new EnumerableByteStream(m_Stream, index - 1, Count - index + 1));
m_Self = newPointer;
//m_Stream.Position = preInsert;
}
public virtual void RemoveAt(int index)
{
//Linked stream around index
m_Stream = LinkedStream.LinkAll(new EnumerableByteStream(m_Stream, 0, index), new EnumerableByteStream(m_Stream, ++index, Count - index));
}
/// <summary>
/// Sets or Retrieves a byte from the underlying stream
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
public virtual byte this[int index]
{
get
{
if (index < 1) index = 0;
if (index != m_Stream.Position)
{
if (m_Stream.CanSeek) m_Stream.Seek(index, System.IO.SeekOrigin.Begin);
else throw new InvalidOperationException("You can only move the index if the underlying stream CanSeek");
}
return (byte)m_Stream.ReadByte();
}
set
{
if (m_Stream.CanWrite && m_Stream.CanSeek) m_Stream.Seek(index, System.IO.SeekOrigin.Begin);
else throw new InvalidOperationException("You can logically set a byte in the stream the index if the underlying stream supports CanWrite and CanSeek");
m_Stream.Write(value.Yield().ToArray(), 0, 1);
}
}
public virtual void Add(byte item)
{
if (m_Stream.CanWrite) m_Stream.Write(item.Yield().ToArray(), 0, 1);
else throw new InvalidOperationException("You can logically set a byte in the stream the index if the underlying stream supports CanWrite");
}
/// <summary>
/// Erases all bytes in perspective of the EnumerableByteStream
/// </summary>
/// <remarks>
/// Creates a new <see cref="System.IO.MemoryStream"/> in the place of the m_Stream.
/// </remarks>
public virtual void Clear()
{
m_Stream = new System.IO.MemoryStream();
return;
}
public virtual bool Contains(byte item)
{
//See CachingEnumerableByteStream on why not < -1
return CoreIndexOf(item, 0, 1) != -1;
}
/// <summary>
/// Advanced the underlying System.IO.Stream by reading into the given array
/// </summary>
/// <param name="array">The array to read into</param>
/// <param name="arrayIndex">The index into the given array to stary copying at</param>
public virtual void CopyTo(byte[] array, int arrayIndex)
{
CoreCopyTo(array, arrayIndex);
}
public virtual void CopyTo(System.IO.Stream stream, int? bufferSize = null)
{
m_Stream.CopyTo(stream, (int)(stream.Length - stream.Position));
}
public virtual void CoreCopyTo(byte[] array, int arrayIndex, int length = -1)
{
if (length <= 0) return;
if (length == -1) length = array.Length - arrayIndex;
else if (length > m_Stream.Length) throw new ArgumentOutOfRangeException("Can't copy more bytes then are availble from the stream");
m_Stream.Read(array, arrayIndex, length);
}
public long Position { get { return Index; } }
public virtual long Length
{
get { return Count; }
}
public virtual bool IsReadOnly
{
get { return m_Stream.CanWrite; }
}
public virtual bool Remove(byte item)
{
//Create N new EnumerableByteStreams with the items index noted in each iteration.
//For each occurance of item in the underlying stream place an index
//For each index create a new EnumerableByteStream with the index = i and the count = 1
//m_Stream = new LinkedStream(parts)
//return true if any of this happened
return false;
}
public static implicit operator System.IO.Stream(EnumerableByteStream eByteStream) { return eByteStream.m_Stream; }
object System.Collections.IEnumerator.Current
{
get { return GetEnumerator().Current; }
}
public override void Reset()
{
m_Current = -1;
if (m_Stream.CanSeek) m_Stream.Seek(VirtualIndex, System.IO.SeekOrigin.Begin);
base.Reset();
}
public long Seek(long offset, System.IO.SeekOrigin origin) { if (m_Stream.CanSeek) return m_Stream.Seek(offset, origin); return m_Stream.Position; }
}
#endregion
It’s kind of confusing in the end and thus why I implemented the
Iterator
pattern... but in the end I am not too sure they are any more useful
than anything else which was already provided in the language, and on top of
that it kind of resembles Java which I hate with a passion.
On a side note the ArraySegmentList
is especially useful for dealing with
large sets of data and also when used with SocketAsyncEventArg
’s as the
BufferList
property.
Please make sure you build the ArraySegmentList
before assigning it to
the SocketAsyncEventArg
’s instance because once assigned the
SocketAsyncEventArg
’s instance will prevent further modification by exposing
the SocketAsyncEventArg
’s BufferList
as IList
which internally has been
implemented as a ReadOnlyCollection
to prevent modification.
There will be complete MediaSocketPool
implementation released in the coming weeks along with a more mature version of this library @ Managed Media Aggregation
Now ...
This hopefully makes things easier but what if we tackled real problems like the Generic Math problem?
That thing has been beat to death 1000 times over but I think I might have something new and interesting but before we get to that...
Since learned have we a reliable method of achieving Microsecond precision what would be next?
#region Cross Platform μTimer /// <summary> /// A Cross platform implementation which can delay time on the microsecond(μs) scale. /// It operates at a frequencies which are faster then most Platform Invoke results can provide due to the use of Kernel Calls under the hood. /// Requires Libc.so@usleep on Mono and QueryPerformanceCounter on Windows for uSleep static /// </summary> /// <notes>A Tcp Socket will be created on port 7777 by default to help keep track of time. No connections will be recieved from this socket.</notes> public sealed class μTimer : IDisposable { #region Not Applicable for the MicroFramework #if(!MF) #region Uncesessary Interop (Left for Comparison) #if MONO using System.Runtime.<wbr />InteropServices; [System.Runtime.<wbr />InteropServices.DllImport("<wbr />libc.so")] //.a , Not Portable static extern int usleep (uint amount); ///<notes>The type useconds_t is an unsigned integer type capable of holding integers in the range [0,1000000]. Programs will be more portable if they never mention this type explicitly. </notes> void uSleep(int waitTime) { usleep(waitTime); } #else [System.Runtime.<wbr />InteropServices.DllImport("<wbr />Kernel32.dll")] static extern bool QueryPerformanceCounter(out long lpPerformanceCount); [System.Runtime.<wbr />InteropServices.DllImport("<wbr />Kernel32.dll")] static extern bool QueryPerformanceFrequency(out long lpFrequency); /// <summary> /// Performs a sleep using a plaform dependent but proven method /// </summary> /// <param name="amount">The amount of time to sleep in microseconds(μs)</param> public static void uSleep(TimeSpan amount) { μTimer.uSleep(((int)(amount.<wbr />TotalMilliseconds * 1000))); } /// <summary> /// Performs uSleep by convention of waiting on performance couters /// </summary> /// <param name="waitTime">The amount of time to wait</param> public static void uSleep(int waitTime) { long time1 = 0, time2 = 0, freq = 0; QueryPerformanceCounter(out time1); QueryPerformanceFrequency(out freq); do { QueryPerformanceCounter(out time2); } while ((time2 - time1) < waitTime); } #endif #endregion #endif #endregion #region Statics //Who but me const ushort Port = 7777; /// <summary> /// TicksPerMillisecond = 10,000 /// </summary> public const long TicksPerMicrosecond = TicksPerNanoSecond / 10; // = 10 /// <summary> /// 1 tick * 1E+2 = 100 nanoseconds (ns) /// 1 tick * 1E-1 = 0.1 microseconds (μs) /// 1 tick * 1E-4 = 0.0001 milliseconds (ms) /// 1 tick * 1E-7 = 0.0000001 seconds (sec) /// </summary> public const long TicksPerNanoSecond = TimeSpan.TicksPerMillisecond / 100; // = 100 /// <summary> /// A divider used to scale time for waiting /// </summary> public const long Divider = TimeSpan.TicksPerSecond / TimeSpan.TicksPerMillisecond; // == (TimeSpan.TicksPerMillisecond / TicksPerMicrosecond) = 1000 static bool m_Disposed; /// <summary> /// The socket we use to keep track of time /// </summary> static Socket m_Socket = new Socket(AddressFamily.<wbr />InterNetwork, SocketType.Stream, ProtocolType.Tcp); /// <summary> /// The memory we give to the socket for events which should not occur /// </summary> static SocketAsyncEventArgs m_SocketMemory = new SocketAsyncEventArgs(); public static DateTime LocalTime { get { return new DateTime(Environment.TickCount * TimeSpan.TicksPerMillisecond); } } public static DateTime UniversalTime { get { return LocalTime.ToUniversalTime(); } } /// <summary> /// Samples the system time and then Causes the system to count ticks for as short of a time as possible and then return the summation of the previsouly sampled time and the calculated time. /// </summary> public static DateTime RealTimeLocal { get { DateTime now = LocalTime; Media.Common.μTimer.μSleep(<wbr />TimeSpan.FromTicks((TimeSpan.<wbr />TicksPerMillisecond / Media.Common.μTimer.<wbr />TicksPerMicrosecond / Media.Common.μTimer.Divider)))<wbr />; DateTime then = DateTime.Now; return now + (then - now); } } /// <summary> /// Converts the localtime to utc /// </summary> public static DateTime RealTimeUniversal { get { return RealTimeLocal.ToUniversalTime(<wbr />); } } /// <summary> /// Handles the creation of resources used to provide the μSleep method. /// </summary> static μTimer() { try { //Listen on the Loopback adapter on the specified port m_Socket.Bind(new System.Net.IPEndPoint(System.<wbr />Net.IPAddress.Loopback, Port)); //Only for 1 client m_Socket.Listen(1); //Assign an event now because in Begin process we will not call it if the even will not raise m_SocketMemory.Completed += BeginProcess; #if(!MF) //If the SocketAsyncEventArgs will not raise it's own event we will call it now if (!m_Socket.AcceptAsync(m_<wbr />SocketMemory)) { BeginProcess(typeof(μTimer), m_SocketMemory); } #else new Thread(()=> BeginProcess(this, null)).Start(); #endif } catch { throw; } } /// <summary> /// Handles processing on the master time socket. /// This should never occcur. /// </summary> /// <param name="sender">The sender of the event</param> /// <param name="e">The SocketAsyncEventArgs from the event</param> /// <remarks> /// No one should connect... Ever.. (This is not a signaling implementation) /// </remarks> #if(!MF) static void BeginProcess(object sender, SocketAsyncEventArgs e) { #else static void BeginProcess(object sender, object args e) { while(!m_Disposed) { try { Socket dontCare = m_Socket.Accept(); dontCare.Dispose(); throw new System.<wbr />InvalidProgramException("A Connection to the system was made by a unauthorized means."); } catch { throw; } } #endif if (!m_Disposed && e.LastOperation == SocketAsyncOperation.Connect) { try { throw new System.<wbr />InvalidProgramException("A Connection to the system was made by a unauthorized means."); } finally { if (e.AcceptSocket != null) e.AcceptSocket.Dispose(); } } } /// <summary> /// Performs a sleep using a method engineered by Julius Friedman <a href="mailto:juliusfriedman@gmail.com" ">juliusfriedman@gmail.com</a>) /// </summary> /// <param name="amount">The amount of time to Sleep</param> public static void μSleep(TimeSpan amount) { //Sample the system clock DateTime now = μTimer.UniversalTime, then = μTimer.UniversalTime; TimeSpan waited = now - then; //If cpu time is not fast enough to accomadate then you are in bigger trouble then you know if (waited > amount) return; else System.Threading.Thread.Sleep(<wbr />amount - waited); //A normal sleep with an amount less that 1 but greater than 0 Millisecond will not switch waited = now - then;//Waste cycles and calculate time waited in ticks again if (waited > amount) return; else unchecked { //Scale time, basis of theory is we shouldn't be able to read from a socket in Accept mode //and it should take more time than a 1000th of the time we need if (m_Socket.WaitRead(((int)((<wbr />amount.Ticks - waited.Ticks / TicksPerMicrosecond) / Divider)))) { //We didn't sleep //Sample the system clock then = μTimer.UniversalTime; //Calculate waited //Subtract time already waited from amount amount -= waited; //Waited set to now - then to determine wait waited = now - then; //return or utilize rest of slice sleeping if (waited > amount) return; else System.Threading.Thread.Sleep(<wbr />amount - waited); } } } /// <summary> /// Performs a sleep using a method engineered by Julius Friedman (<a href="mailto:juliusfriedman@gmail.com">juliusfriedman@gmail.com</a>) /// </summary> /// <param name="amount">The amount of time to Sleep in microseconds(μs) </param> public static void μSleep(int amount) { μTimer.μSleep(TimeSpan.<wbr />FromMilliseconds(amount * TimeSpan.TicksPerMillisecond))<wbr />; } #endregion void IDisposable.Dispose() { m_Disposed = true; if (m_Socket != null) { m_Socket.Dispose(); m_Socket = null; } } } #endregion
Well since you can now make a real time clock using C# alone
and my MicroTimer
the next steps for that would be to create a SocketPrecisionWaitHandle
. (Again not everything for free)
It would derive from WaitHandle
and expose Microsecond
precision overloads.
It would have the added benefit that Wait and Set operations
were actually happening on System Interrupts and allow you to signal other
threads with the same scheduling precision as the μTimer
class.
It will use the MultiCastLoopBack
adapter by default for the
best performance.
There could be a Tcp and Udp version although I suspect RAW
Sockets would provide the best performance and allow for the most flexibility
when sending data through the WaitHandles
with the new
SocketPrecision.PostMessage
API’s which allow you to send your messages to all
SocketWaitHandles
or just a single known SocketWaitHandle
.
It is essentially a SocketServer
which only sends data on the
local host.
When you create a SocketPrecisionWaitHandle
you connect to the
SocketPrecisionHost
and then all WaitOne
commands will be performed on the
Socket.
Default signaling commands will just send an empty packet of 0
bytes however in advanced cases you can send data up to a certain length long
depending on the SocketPrecisionHost
’s allowances.
In short this gives you the developer the ability to schedule interprocess communication safely , efficiently and without the need for special kernel mode drivers.
If you need encryption from other prying eyes then you can use
TCP and a SSL Stream or another form when you derive the SocketPrecisionHost
into a SecureSocketPrecisionHost
and Client combination.
I would recommend only using empty transfers and single bytes
as Operation Codes since null 0 - 255 (256 total) values should be sufficient
to support most scenarios.
ets see how to layout a Flagged byte using all 256 possible states! (null included)
/// <summary>
/// Used as a basis to represent state rather than a traditional state machine in a MediaChannelBinding.
/// </summary>
/// <remarks>
/// Structure is Binary 8 Bit
[Flags]
/// +-------- BeforeReservedDisconnect, ReservedDisconnect, BeforeDisconnectedDisconnected, ReservedAfterDisconnected or Invalid if 255
/// | +------- BeforeProcessData and ProcessingData or (BeforeDisconnect if 127) 01111111
/// | | +------ Data Transfer (Send or Receive) or (ReservedAfterReceiveData if 64)
/// | | | +----- QueueData, AfterQueueData or (ReservedBeforeReceiveData if 31)
/// | | | | +---- ReservedCompleted, Connected, AfterConnected or (About to BeforeQueueData if 15)
/// | | | | | +--- Reserved, BeforeConnected, ReservedConnected, ReservedPending
/// | | | | | | +-- Buffers and workers being created or created 2/3
/// | | | | | | | +- Created but not started 0/1
/// 0 1 2 3 4 5 6 7
/// +-------------+
/// | D T Q R S I |
/// +-------------+
/// </remarks>
/// <ToDo>
/// Trying to emulate the wire in some ways.
/// Please remember in certain sitations that Sending and receiving is not necessarily connected.
/// Eventually the SocketPrecisionWaitHandle can send these OpCodes on the handle..
/// </ToDo>
public enum MediaChannelBindingState : byte
{
Unitialized = 0, //Created
BeforeInitialized = 1, //Initialize called
Initialized = 2,
AfterInitialized = 3, //Connected to a remote host
Reserved = 4, //Connected but something else
BeforeConnected = 5,
ReservedConnected = 6, //Connected and something else
ReservedPending = 7,
ReservedCompleted = 8,
Connected = 9,
AfterConnected = 10,
//11 00001011
//12 00001100
//13 00001101
//14 00001110
BeforeQueueData = 15, // 00001111
QueueData = 16, //Queing data for Sending 00010000
AfterQueueData = 17, // 00010001
//
//
//.... Sending Data
BeforeSendData = 31,
SendData = 32,//Sending the data
AfterSendData = 33,
//34
//35
//36
//... Receiving Data
ReservedBeforeReceiveData = 59,
BeforeReceiveData = 60,
ReceiveData = 61,//Receiving data
ReceiveReserved = 62,
AfterReceiveData = 63,
ReservedAfterReceiveData = 64,
BeforeProcessData = 65,
ProcessingData = 66,
//67
//... Processing Data
//126
BeforeReservedDisconnect = 127,
ReservedDisconnect = 128,
BeforeDisconnected = 129,
Disconnected = 129,
AfterDisconnected = 130,
ReservedAfterDisconnected = 131,
//132
//... Reserved
//254
Invalid = byte.MaxValue
}
The PostMessage
is different from the Set and WaitOne
API in
the sense it specifically allows for larger sets of data on dedicated Pool’s
when those resources are required e.g. for processing or calculation and
subsequent callback.
Lets get back to the Generic Math Problem...
Generics and Math have long history of problems mostly due to how the C# compiler internally handles mathematical operations when generics are used.
This results in a developer usually having to take many steps such a building a delegate dynamically when required to perform a calculation on a generic type say
<T> = decimal and <U> = double inter alia.
CIL Has no problem with this, but it's the various Compilers e.g. VB.Net or C# however...
This brings me to another problem, the inability in C# to
define Binary properly, yes StructLayout
helps a great deal and without it I am
not sure how I would have achieved so much already however I aim to take that much further with the following types:
Enter Bits, Bitable and Number and Much much more...
They are what I hope will be the next way of thinking about managed types, as you will see they support unmanaged and managed style code with the same API. They allow unprecedented control over the binary aspects of types. (It could be separated and hidden and only shown under different interfaces but I like the current approach)
You will see everything has an interface to abstract away virtual call overhead in .NET.
This could be implemented just about anywhere and in any language but I have chosen C# because I wanted to display my skill with and love for the language.
ICoreUnit
- This represents the core units of energy the Framework is able to work with, right now only Transistor is implemented but in the future Qubit's could be easily implemented using this Framework with minor adjustments.
There is even a QuBit
and QuByte
implementation inside...
#region Quantum
/// <summary>
/// v
/// </summary>
public abstract class QuBit : IComparable<MultiBit>
{
public bool[] States { get; internal protected set; }
public System.Numerics.Complex Entanglement { get; set; }
//....
public abstract int CompareTo(MultiBit other);
}it
/// <summary>
/// //
/// </summary>
public abstract class QuByte : IComparable<Bitable>
{
public abstract IEnumerable<QuBit> QuBits { get; internal protected set; }
//....
public abstract int CompareTo(Bitable other);
}
#endregion
Transistor
- Implements a implicit boolean conversion to traditional C style language. In the future I imagine that this will be something else with many sates (e.g. a QuBit)Bit
- Implements the of a single ICoreUnit of energy in Today's computers.MultiBit
- Derives from Bit. Implements the use of Multi ICoreUnits of energy. It keeps the first bit and stores Bits1_N enumerable revealing the underlying count.CommonIntermediaLanguage
- A class which enables the use of Common Intermediate Language inline.IManipulator
- This represents the Hardware manipulations which occur. Since I didn't have time to make everything the way I wanted this class is static and I use theIManipulator
Interface which could and probably should also Implement a IHardware Interface...Since the default number complimenting system is already two's compliments I have decided to also leave this concept blank for artists of the future.StorageAllocator
- Just a reference allocator which takes memory from the System.GarbadgeCollector
- Just a class to keep the allocator and the allocations which occur along with their references.There should also eventually be a RunTime class which keeps the reference count.You will find support for 32 and 64 bit objects and the ability to convert them.
There should also eventually be a way to copy a .NET
object
into a Bitable
but that should be easy to add if you know what you are doing.
There is also a lot more then can do for computer science in general such as allow easier enumeration of underlying memory systems but I am off on another tangent so before I forget what I am writing about here we go:
Bits are ValueTypes
and Bitable’s
are classes (ReferenceTypes
) which have more
Bits
in them.
Here are the classes as I describe each one.
Bits
- A Representation of binary data. Bits don’t know what
Endian they are stored in nor do they care (nor should they because of their relative electrical nature, Endianess is only a thing we enforce on the system, it technically doesn't exist). They can be accessed in pointer
notation e.g. "data[0]" or using the static object oriented methods GetBit
,
SetBit
, CheckBit
, ToggleBit
. Bits are always 1 Byte in size and have no
additional properties or overhead. They are specially laid out structures.Each
Bits type supports Unsafe pointers as well as "Safe pointers"
#region Bits
[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Explicit,
Size = 1,//This field must be equal or greater than the total size, in bytes, of the members of the class or structure.
Pack = 0, //A value of 0 indicates that the packing alignment is set to the default for the current platform.
CharSet = System.Runtime.InteropServices.CharSet.Auto)]
public struct Bits : System.Collections.IEnumerable, IEnumerable<bool>
{
/// <summary>
/// The size of the structure in bytes
/// </summary>
public const int Size = 1;
public const int BitSize = 8;
[System.Runtime.InteropServices.FieldOffset(0)]
internal byte m_Bits;
unsafe byte* UnsafeBits
{
get
{
fixed (byte* memory = &m_Bits)
{
return memory;
}
}
}
public byte ManagedBits { get { return m_Bits; } }
public Bits(byte b) { m_Bits = b; }
public override bool Equals(object obj)
{
if (obj is Bits)
{
Bits unboxed = (Bits)obj;
if (unboxed != null) return unboxed == this;
else return false;
}
else return base.Equals(obj);
}
public override int GetHashCode()
{
return m_Bits.GetHashCode();
}
public bool this[int index]
{
get { return GetBit(this, index); }
set { SetBit(this, index); }
}
public static bool GetBit(Bits b, int index)
{
return (b.m_Bits & (Size << index)) > 0;
}
public static void SetBit(Bits b, int index)
{
b |= (Size << index);
}
public static void ClearBit(Bits b, int index)
{
b &= ~(Size << index);
}
public static void Toggle(Bits b, int index)
{
b ^= (byte)(Size << index);
}
public static implicit operator byte(Bits b) { return b.m_Bits; }
public static implicit operator int(Bits b) { return b.m_Bits; }
public static implicit operator Bits(byte b) { return new Bits(b); }
public static Bits operator ^(Bits b, int amount)
{
return new Bits((byte)(b.m_Bits ^ amount));
}
public static Bits operator |(Bits b, int amount)
{
return new Bits((byte)(b.m_Bits | amount));
}
public static Bits operator &(Bits b, int amount)
{
return new Bits((byte)(b.m_Bits & amount));
}
public static bool operator >(Bits b, int amount)
{
return b.m_Bits > amount;
}
public static bool operator <(Bits b, int amount)
{
return b.m_Bits > amount;
}
public static Bits operator >>(Bits b, int amount)
{
return new Bits((byte)(b.m_Bits >> amount));
}
public static Bits operator <<(Bits b, int amount)
{
return new Bits((byte)(b.m_Bits << amount));
}
public static Bits operator +(Bits b, int amount)
{
return new Bits((byte)(b.m_Bits + amount));
}
public static Bits operator -(Bits b, int amount)
{
return new Bits((byte)(b.m_Bits - amount));
}
public static Bits operator *(Bits b, int amount)
{
return new Bits((byte)(b.m_Bits * amount));
}
public static Bits operator /(Bits b, int amount)
{
return new Bits((byte)(b.m_Bits / amount));
}
//
public static Bits operator ^(Bits b, Bits other)
{
return new Bits((byte)(b.m_Bits ^ other.m_Bits));
}
public static Bits operator |(Bits b, Bits other)
{
return new Bits((byte)(b.m_Bits | other.m_Bits));
}
public static Bits operator &(Bits b, Bits other)
{
return new Bits((byte)(b.m_Bits & other.m_Bits));
}
public static bool operator >(Bits b, Bits other)
{
return b.m_Bits > other.m_Bits;
}
public static bool operator <(Bits b, Bits other)
{
return b.m_Bits > other.m_Bits;
}
public static Bits operator +(Bits b, Bits other)
{
return new Bits((byte)(b.m_Bits + other.m_Bits));
}
public static Bits operator -(Bits b, Bits other)
{
return new Bits((byte)(b.m_Bits - other.m_Bits));
}
public static Bits operator *(Bits b, Bits other)
{
return new Bits((byte)(b.m_Bits * other.m_Bits));
}
public static Bits operator /(Bits b, Bits other)
{
return new Bits((byte)(b.m_Bits / other.m_Bits));
}
//
public static bool operator ==(Bits b, int a) { return a == b.m_Bits; }
public static bool operator !=(Bits b, int a) { return !(a == b.m_Bits); }
public static bool operator ==(Bits b, byte a) { return a == b.m_Bits; }
public static bool operator !=(Bits b, byte a) { return !(a == b.m_Bits); }
public static bool operator ==(Bits b, Bits a)
{
return a.m_Bits == b.m_Bits;
}
public static bool operator !=(Bits b, Bits a)
{
return !(a == b);
}
public System.Collections.IEnumerator GetEnumerator()
{
return new BitsEnumerator(this);
}
IEnumerator<bool> IEnumerable<bool>.GetEnumerator()
{
return new BitsEnumerator(this);
}
}
#endregion
Bitable - A Representation of binary data which is Endian aware, it’s size it at 1 Byte but can be any number of Bytes which the system can support. Each Bitable type supports Unsafe pointers as well as "Safe pointers"
#region Bitable
public class Bitable : IEnumerable<Bits>, IEnumerable<byte> , IEnumerable<bool>
{
#region Statics
public static Endian SystemEndian = System.BitConverter.IsLittleEndian ? Endian.LittleEndian : Endian.BigEndian;
public readonly static Bitable SingleZero = new Bitable((Single)0);
public readonly static Bitable ByteZero = new Bitable((byte)0);
public readonly static Bitable ShortZero = new Bitable((short)0);
public readonly static Bitable IntZero = new Bitable(0);
public readonly static Bitable LongZero = new Bitable(0L);
public readonly static Bitable DoubleZero = new Bitable(0.0D);
public readonly static Bitable DecimalZero = new Bitable(0.0M);
public readonly static Bitable Null = new Bitable(SystemEndian);
#endregion
#region Properties
unsafe byte* UnmanagedBytes
{
get
{
fixed (byte* memory = Memory)
{
return memory;
}
}
}
public Endian Endian { get; protected set; }
public int Count { get { return Memory.Length; } }
public int BitCount { get { return Count * 8; } }
public byte this[int index]
{
get
{
return Memory[index];
}
set
{
Memory[index] = value;
}
}
#endregion
#region Fields
internal byte[] Memory;
#endregion
#region Constructors
public Bitable(Bitable other)
{
if (other.Memory != null)
{
Memory = new byte[other.Count];
other.Memory.CopyTo(Memory, 0);
}
Endian = other.Endian;
}
public Bitable(Bits bits, Endian endian = Common.Bits.Endian.Unknown)
{
Memory = new byte[1];
Memory[0] = bits.m_Bits;
Endian = endian;
}
internal Bitable(Endian? endian = null)
{
Endian = endian ?? (System.BitConverter.IsLittleEndian ? Endian.LittleEndian : Endian.BigEndian);
}
public Bitable(bool Boolean)
: this((byte)(Boolean ? 1 : 0)) { }
public Bitable(byte Byte, Endian? endian = null)
: this(endian)
{
Memory = new byte[] { Byte };
}
public Bitable(sbyte SByte, Endian? endian = null)
: this(endian)
{
Memory = new byte[] { (byte)SByte };
}
public Bitable(Int16 Int, Endian? endian = null)
: this(endian)
{
Memory = BitConverter.GetBytes(Int);
}
public Bitable(UInt16 Int, Endian? endian = null)
: this(endian)
{
Memory = BitConverter.GetBytes(Int);
}
public Bitable(Int32 Int, Endian? endian = null)
: this(endian)
{
Memory = BitConverter.GetBytes(Int);
}
public Bitable(UInt32 Int, Endian? endian = null)
: this(endian)
{
Memory = BitConverter.GetBytes(Int);
}
public Bitable(Int64 Int, Endian? endian = null)
: this(endian)
{
Memory = BitConverter.GetBytes(Int);
}
public Bitable(UInt64 Int, Endian? endian = null)
: this(endian)
{
Memory = BitConverter.GetBytes(Int);
}
public Bitable(Single Single, Endian? endian = null)
: this(endian)
{
Memory = BitConverter.GetBytes(Single);
}
public Bitable(Double Double, Endian? endian = null)
: this(endian)
{
Memory = BitConverter.GetBytes(Double);
}
public Bitable(Decimal Decimal, Endian? endian = null)
: this(endian)
{
Memory = System.Decimal.GetBits(Decimal).Select(a => BitConverter.GetBytes(a)).SelectMany(b => b).ToArray();
}
#endregion
IManipulator
- The default interface which defines the
implementation specifics about bit manipulation within a Bitable
.
Manipulator
- A static class which represents common operations
in computer science e.g. ShiftLeft, ShiftRight, Add, Substract etc.
IHardware
interface for a better design but again I didn't want to give everything away! See my notes in the bottom "Interesting Points
"
#region Manipulator
public sealed class Manipulator : IManipulator
{
public delegate Bitable Manipulation(Bitable a, Bitable b);
public delegate void ReferenceManipulation(ref Bitable a, ref Bitable b);
public delegate bool Evaluation(Bitable a, Bitable b);
public delegate bool ReferenceEvaluation(ref Bitable a, ref Bitable b);
public delegate void Operation(Bitable a, Bitable b);
public delegate void ReferenceOperation(ref Bitable a, ref Bitable b);
public static void Prepare(ref Bitable a, ref Bitable b)
{
if (b > a)
{
Bitable temp = b;
b = a;
a = temp;
}
}
public static Bitable Manipulate(Bitable a, Bitable b, Manipulation manipulation)
{
return manipulation(a, b);
}
public static void Manipulate(ref Bitable a, ref Bitable b, ReferenceManipulation referenceManipulation)
{
referenceManipulation(ref a, ref b);
}
public static void Addition(ref Bitable a, ref Bitable b)
{
for (int i = 0; i < Math.Min(a.Count, b.Count); ++i)
a[i] += b[i];
}
public static Bitable Add(Bitable a, Bitable b)
{
Prepare(ref a, ref b);
Bitable result = new Bitable(a);
Addition(ref result, ref b);
return result;
}
public static void Subtraction(ref Bitable a, ref Bitable b)
{
for (int i = 0; i < Math.Min(a.Count, b.Count); ++i)
a[i] -= b[i];
}
public static Bitable Subtract(Bitable a, Bitable b)
{
Prepare(ref a, ref b);
Bitable result = new Bitable(a);
Subtraction(ref result, ref b);
return result;
}
public static void Multiplication(ref Bitable a, ref Bitable b)
{
for (int i = 0; i < Math.Min(a.Count, b.Count); ++i)
a[i] *= b[i];
}
public static Bitable Multiply(Bitable a, Bitable b)
{
Prepare(ref a, ref b);
Bitable result = new Bitable(a);
Multiplication(ref result, ref b);
return result;
}
public static void Division(ref Bitable a, ref Bitable b)
{
for (int i = 0; i < Math.Min(a.Count, b.Count); ++i)
a[i] /= b[i];
}
public static Bitable Divide(Bitable a, Bitable b)
{
Prepare(ref a, ref b);
Bitable result = new Bitable(a);
Division(ref result, ref b);
return result;
}
public static void Modulo(ref Bitable a, ref Bitable b)
{
for (int i = 0; i < Math.Min(a.Count, b.Count); ++i)
a[i] %= b[i];
}
public static Bitable Modulus(Bitable a, Bitable b)
{
Prepare(ref a, ref b);
Bitable result = new Bitable(a);
Modulo(ref result, ref b);
return result;
}
public static bool GreaterThan(Bitable a, Bitable b)
{
return a.Count > b.Count;
}
public static bool LessThan(Bitable a, Bitable b)
{
return a < b;
}
public static void OR(ref Bitable a, ref Bitable b)
{
for (int i = 0; i < Math.Min(a.Count, b.Count); ++i)
a[i] |= b[i];
}
public static Bitable OR(Bitable a, Bitable b)
{
Prepare(ref a, ref b);
Bitable result = new Bitable(a);
OR(ref result, ref b);
return result;
}
public static void XOR(ref Bitable a, ref Bitable b)
{
for (int i = 0; i < Math.Min(a.Count, b.Count); ++i)
a[i] ^= b[i];
}
public static Bitable XOR(Bitable a, Bitable b)
{
Prepare(ref a, ref b);
Bitable result = new Bitable(a);
XOR(ref result, ref b);
return result;
}
public static void AND(ref Bitable a, ref Bitable b)
{
for (int i = 0; i < Math.Min(a.Count, b.Count); ++i)
a[i] &= b[i];
}
public static Bitable AND(Bitable a, Bitable b)
{
Prepare(ref a, ref b);
Bitable result = new Bitable(a);
AND(ref result, ref b);
return result;
}
public static void NOT(ref Bitable a, ref Bitable b)
{
for (int i = 0; i < Math.Min(a.Count, b.Count); ++i)
a[i] = (byte)~b[i];
}
public static Bitable NOT(Bitable a, Bitable b)
{
Prepare(ref a, ref b);
Bitable result = new Bitable(a);
NOT(ref result, ref b);
return result;
}
public static void NAND(ref Bitable a, ref Bitable b)
{
for (int i = 0; i < Math.Min(a.Count, b.Count); ++i)
a[i] &= (byte)(~b[i]);
}
public static Bitable NAND(Bitable a, Bitable b)
{
Prepare(ref a, ref b);
Bitable result = new Bitable(a);
NAND(ref result, ref b);
return result;
}
public static void NOR(ref Bitable a, ref Bitable b)
{
for (int i = 0; i < Math.Min(a.Count, b.Count); ++i)
a[i] |= (byte)(~b[i]);
}
public static Bitable NOR(Bitable a, Bitable b)
{
Prepare(ref a, ref b);
Bitable result = new Bitable(a);
NOR(ref result, ref b);
return result;
}
public static void ShiftLeft(ref Bitable a, ref int amount, ref int index)
{
for (int i = index; i < a.Count; ++i)
a[i] <<= amount;
}
public static Bitable ShiftLeft(Bitable a, int amount, int index = 0)
{
Bitable result = new Bitable(a);
ShiftLeft(ref result, ref amount, ref index);
return result;
}
public static void ShiftRight(ref Bitable a, ref int amount, ref int index)
{
for (int i = index; i < a.Count; ++i)
a[i] >>= amount;
}
public static Bitable ShiftRight(Bitable a, int amount, int index = 0)
{
Bitable result = new Bitable(a);
ShiftRight(ref result, ref amount, ref index);
return result;
}
//Circular
///
//Other fun things like IsOdd or IsEven ? :P
//Todo Rename above methods to {Name} + All
//make proper methods with carry?
//Or implemeant on Complimentor
}
#endregion
IComplementor
- The interface which defines Complementors.
#region IComplementor
public interface IComplementor
{
int Complements { get; }
IManipulator Manipulator { get; }
}
#endregion
#region Complementor
/// <summary>
/// The base class of all number complimentors.
/// Retrieves Numbers from a Bitables Memory
/// </summary>
public abstract class Complementor : IComplementor
{
public abstract int Complements { get; }
public abstract IManipulator Manipulator { get; }
}
#endregion
#region TwosComplementor
/// <summary>
/// A basic two's complementor
/// </summary>
public class TwosComplimentor : Complementor
{
public static int ComplementsOf = 2;
public override int Complements
{
get { return TwosComplimentor.ComplementsOf; }
}
public override IManipulator Manipulator
{
get { return Manipulator; }
}
}
#endregion
Complementor
- The base class of all Complementors.
Complementors. A complementor is responsible for reading numbers from a
Bitable
in a designed form.
#region Complementor
/// <summary>
/// The base class of all number complimentors.
/// Retrieves Numbers from a Bitables Memory
/// </summary>
public abstract class Complementor : IComplementor
{
public abstract int Complements { get; }
public abstract IManipulator Manipulator { get; }
}
#endregion
Number
- A Class which sits on top of Bitable
to provide the
default math system. It is aware of the SystemComplimentor as well as it’s own
Complimentor which is by default the TwosComplimentor
. All Compliments
have a
IManipulator
as an abstract property which should be responsible for all
operations.
It solves the Generic Math problem in a new and hopefully not to puzzling way! (Examples included)
#region Number
/// <summary>
/// Handles the conversion from a Bitable to a Mathematical Number
/// </summary>
public class Number : Bitable
{
#region Overrides
public override int GetHashCode()
{
return base.GetHashCode();
}
public override bool Equals(object obj)
{
if (obj is Number) return ((Number)obj) == this;
return base.Equals(obj);
}
#endregion
#region Constructors
public Number(Complementor complimentor = null) : base() { Complimentor = complimentor ?? DefaultComplimentor; }
public Number(Number other, Complementor complimentor = null) : base(other) { Complimentor = complimentor ?? DefaultComplimentor; }
public Number(Bitable other, Complementor complimentor = null) : base(other) { Complimentor = complimentor ?? DefaultComplimentor; }
public Number(Bits other, Complementor complimentor = null) : base(other) { Complimentor = complimentor ?? DefaultComplimentor; }
public Number(bool Boolean, Complementor complimentor = null)
: this((byte)(Boolean ? 1 : 0))
{
Complimentor = complimentor ?? DefaultComplimentor;
}
public Number(byte Byte, Endian? endian = null, Complementor complimentor = null)
: base(Byte, endian)
{
Complimentor = complimentor ?? DefaultComplimentor;
}
public Number(sbyte SByte, Endian? endian = null, Complementor complimentor = null)
: base(SByte, endian)
{
Complimentor = complimentor ?? DefaultComplimentor;
}
public Number(Int16 Int, Endian? endian = null, Complementor complimentor = null)
: base(Int, endian)
{
Complimentor = complimentor ?? DefaultComplimentor;
}
public Number(UInt16 Int, Endian? endian = null, Complementor complimentor = null)
: base(Int, endian)
{
Complimentor = complimentor ?? DefaultComplimentor;
}
public Number(Int32 Int, Endian? endian = null, Complementor complimentor = null)
: base(Int, endian)
{
Complimentor = complimentor ?? DefaultComplimentor;
}
public Number(UInt32 Int, Endian? endian = null, Complementor complimentor = null)
: base(Int, endian)
{
Complimentor = complimentor ?? DefaultComplimentor;
}
public Number(Int64 Int, Endian? endian = null, Complementor complimentor = null)
: base(Int, endian)
{
Complimentor = complimentor ?? DefaultComplimentor;
}
public Number(UInt64 Int, Endian? endian = null, Complementor complimentor = null)
: base(Int, endian)
{
Complimentor = complimentor ?? DefaultComplimentor;
}
public Number(Single Single, Endian? endian = null, Complementor complimentor = null)
: base(Single, endian)
{
Complimentor = complimentor ?? DefaultComplimentor;
}
public Number(Double Double, Endian? endian = null, Complementor complimentor = null)
: base(Double, endian)
{
Complimentor = complimentor ?? DefaultComplimentor;
}
public Number(Decimal Decimal, Endian? endian = null, Complementor complimentor = null)
: base(Decimal, endian)
{
Complimentor = complimentor ?? DefaultComplimentor;
}
#endregion
Number<T>
The generic version of Number
(Included) which solves the
generic math problem's of the future...
public class Number<T> : Number
{
#region Constructors
public Number() : base() { }
public Number(Number other) : base(other) { }
public Number(Bitable other) : base(other) { }
public Number(Bits other) : base(other) { }
public Number(bool Boolean)
: this((byte)(Boolean ? 1 : 0)) { }
public Number(byte Byte, Endian? endian = null)
: base(Byte, endian)
{
}
public Number(sbyte SByte, Endian? endian = null)
: base(SByte, endian)
{
}
public Number(Int16 Int, Endian? endian = null)
: base(Int, endian)
{
}
public Number(UInt16 Int, Endian? endian = null)
: base(Int, endian)
{
}
public Number(Int32 Int, Endian? endian = null)
: base(Int, endian)
{
}
public Number(UInt32 Int, Endian? endian = null)
: base(Int, endian)
{
}
public Number(Int64 Int, Endian? endian = null)
: base(Int, endian)
{
}
public Number(UInt64 Int, Endian? endian = null)
: base(Int, endian)
{
}
public Number(Single Single, Endian? endian = null)
: base(Single, endian)
{
}
public Number(Double Double, Endian? endian = null)
: base(Double, endian)
{
}
public Number(Decimal Decimal, Endian? endian = null)
: base(Decimal, endian)
{
}
#endregion
What is the purpose of this code?
Well with it you can now more quickly and efficiently emulate ANY type of hardware using any other type of hardware given you have the memory to compensate and the CPU speed required to perform the calculations efficiently.
These classes coupled with the Mono’s SIMD classes can allow developers previously un-thought of levels of performance and interoperability as well as new ways of using unmanaged languages within the managed language.
For instance I have the areas regioned off for BitableObject
and BitableStruct
etc.
Those classes would eventually be used for advanced serialization and deserialization.
For example I will only endeavor into talking about the
BitableStruct
.
Ideally say given known layout information
e.g. { int, bool, short, byte, string(4), byte[1] }
You can create a BitableObject
which has dynamically named
members with the values from the memory parsed in the format given to the
BitableObject
.
With this you could allow for new BitableStructLayout
Attributes based on bits
From the BitableObject
/ BitableStructure
SO with memory [0, 0 ,0, 0, 0, 0 ,0, 1] (In Binary) or (In Decimal = 1)
You can make each BIT field or something else and you don't care about the names of the properties so you would access them by var X = { Bool[0], Byte[0] }
I would eventually like to add other concepts which I might choose to add here if people comment but I don't want to give everything away for free but at the same time I want to help everyone progress and see things in new and interesting ways so I will outline a few things I have included also..
Interesting Points
Nothing Requires or utilizes ANY unsafe code or any Interop put it fully supports it!
Inside you will also find PointerGuard
technology (unfinished but the concept is real) which can protect a pointer from operations which you don't want or exceed a maximum address.
CommonIntermediateLanguage which can be used as in anywhere you need to support inline CIL.
Number<T>
- Not very useful and commented out for now...
This allows you to have crazy serialization and deserialization
potentials without relying on the System for BinaryFormatter
or anything else along with so MUCH MORE!
Much more! (PerpetualEnumerators
(Parallel)... )
#region PerpetuatingEnumerable /// <summary> /// Encapsulates the IEnumerator by always returning from the begining. If nothing is contained you will still be able to loop. /// </summary> /// <typeparam name="T">The type of the items contained in the PerpetuatingEnumerable</typeparam> /// <remarks> /// When past the end of the inital Enumerator Perpetual will be set to true. /// </remarks> public class PerpetuatingEnumerable<T> : IEnumerator<T>, IEnumerable<T>, System.Collections.IEnumerator, System.Collections.IEnumerable { #region Nested Types public class PerpetuatingInstruction : Exception { } public class BreakInstruction : PerpetuatingInstruction { } public class ContinueInstruction : PerpetuatingInstruction { } //public class SkipInstruction : PerpetuatingInstruction { } //public class TakeInstruction : PerpetuatingInstruction { } //public class TakeWhileInstruction : PerpetuatingInstruction { } public delegate void PerpetuatingEvent(PerpetuatingEnumerable<T> sender, T state); #endregion public event PerpetuatingEvent Perpetuated, Completed; IEnumerable<T> enumerable; IEnumerator<T> enumerator; internal protected void OnPerpetuated(PerpetuatingEnumerable<T> sender, T item) { sender.Perpetuated -= OnPerpetuated; sender.Perpetual = true; } internal protected void OnCompleted(PerpetuatingEnumerable<T> sender, T item) { sender.Completed -= OnCompleted; } public bool Perpetual { get; private set; } public T Current { get { if (enumerator == null) enumerator = enumerable.AsParallel().GetEnumerator(); return enumerator.Current; } } public PerpetuatingEnumerable(IEnumerable<T> toLoop) { if (toLoop == null) throw new ArgumentNullException(); enumerable = toLoop; enumerator = enumerable.GetEnumerator(); Perpetuated += OnPerpetuated; Completed += OnCompleted; } public PerpetuatingEnumerable(T item) : this(item.Yield()) { } public PerpetuatingEnumerable(System.Collections.IEnumerable toLoop) : this((IEnumerable<T>)toLoop) { } public void Dispose() { Completed(this, Current); enumerator.Dispose(); enumerator = null; enumerable = null; } public int Count { get { unchecked { return (int)enumerable.Count(); } } } object System.Collections.IEnumerator.Current { get { return enumerator.Current; } } public bool MoveNext() { try { if (enumerator.MoveNext()) { return true; } else if (enumerable != null) { try { enumerator = enumerable.GetEnumerator(); enumerator.MoveNext(); return true; } catch (InvalidOperationException) { return Perpetuate(); } catch (BreakInstruction) { return false; } catch (ContinueInstruction) { return true; } catch { throw; } finally { Perpetuated(this, Current); } } return false; } catch (BreakInstruction) { return false; } catch (ContinueInstruction) { return true; } catch (InvalidOperationException) { return Perpetuate(); } catch { throw; } } public void Reset() { enumerator.Reset(); } /// <summary> /// Provides a way to expand the concept without mucking with the core properties... /// </summary> /// <returns><see cref="PerpetuatingEnumerable.MoveNext"/></returns> public virtual bool Perpetuate() { return MoveNext(); } public IEnumerator<T> GetEnumerator() { return this; } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return (System.Collections.IEnumerator)GetEnumerator(); } } #endregion
Until Next Time! Play with these code samples: (Ran from a MTA Thread)
#region Sandbox enum StateMachineState : byte { None = 0, Start = 1, AfterStart = 2, BeforeEnd = 4, End = 8, Invalid = 255 } private delegate int IntSqaureInvoker(int a, int b); private delegate long LongSqaureInvoker(long a, long b); private delegate TReturn MyPrototype<TReturn, TParameter0, TParameter1>(TParameter0 p0, TParameter0 p1); public static void SandBox() { //Create the il to square given input values string ILSquare = @" ldarg.0 //Loads the argument at index 0 onto the evaluation stack. conv.i8 //Converts the value on top of the evaluation stack to int64. dup//Copies the current topmost value on the evaluation stack, and then pushes the copy onto the evaluation stack. mul//Multiplies two values and pushes the result on the evaluation stack. ret//Returns from the current method, pushing a return value (if present) from the callee's evaluation stack onto the caller's evaluation stack. "; //Only done so you don't have to pass the types manually... MyPrototype<int, int, int> prototype = new MyPrototype<int, int, int>((a, b) => 0); MyPrototype<int, int, int> compiledIl = (MyPrototype<int, int, int>)Media.Common.Bits.CommonIntermediaLanguage.CreateMethod(ILSquare, "Square", prototype); Console.WriteLine(compiledIl(2, 2)); //Or you can specify them manually if you require LongSqaureInvoker compiledIl2 = (LongSqaureInvoker)Media.Common.Bits.CommonIntermediaLanguage.CreateMethod(ILSquare, "Square", typeof(long), new Type[] { typeof(long), typeof(long) }, typeof(LongSqaureInvoker)); Console.WriteLine(compiledIl2(4, 2)); //Test Transistor / ICoreUnit Media.Common.Bits.Transistor t = new Common.Bits.Transistor() { Value = true }; Console.WriteLine(t.Value); t.Value = false; Console.WriteLine(t.Value); t.Value = true; Console.WriteLine(t.Value); Media.Common.Bits.Bits bits = new Media.Common.Bits.Bits(136); Console.WriteLine(string.Join(",", (bits as IEnumerable<bool>).ToArray())); Console.WriteLine(string.Join(",", (Media.Common.Bits.BitsExtensions.GetBits(bits, 0, 4)))); Console.WriteLine(string.Join(",", (Media.Common.Bits.BitsExtensions.GetBits(bits, 4, 4)))); Media.Common.Bits.Bitable bitss = 136; Console.WriteLine(string.Join(",", (Media.Common.Bits.BitsExtensions.GetBits(bitss)))); Media.Common.Bits.Bits two = 1 + 1; System.Console.WriteLine(two == 1 + 1); Media.Common.Bits.Bitable four = 2 + 2; System.Console.WriteLine(four == 2 + 2); Media.Common.Bits.Bitable overflow = (long)2 + int.MaxValue; System.Console.WriteLine(overflow == (long)int.MaxValue + 2); Media.Common.Bits.Number testNumber = 2; int result = testNumber + 2; System.Console.WriteLine(testNumber == 4); System.Console.WriteLine(result == 4); System.Console.WriteLine(testNumber + 4); testNumber += 4; System.Console.WriteLine(testNumber); List<decimal> xs = new List<decimal>() { 0.09m, 0.1m, 0.2m, 0.3m, 0.4m, 0.5m, }; List<Media.Common.Bits.Number> doubles = new List<Common.Bits.Number>(); double val = 0.1; //Doh!! //xs.ForEach(d => doubles.Add(d + (double)val)); //The best part.... no more Generic issues!!! xs.ForEach(d => doubles.Add(new Media.Common.Bits.Number((Media.Common.Bits.Number)d + (Media.Common.Bits.Number)val))); //Test ArraySegmentList Media.Common.ArraySegmentList<int> asl = new Media.Common.ArraySegmentList<int>(10); for (int x = 0; x < 105; ++x) { asl.Add(x); } foreach (ArraySegment<int> segment in asl.Segments) { Console.WriteLine(string.Join("-", segment.Array)); } //Test EnumerableByteStream System.IO.MemoryStream test = new System.IO.MemoryStream(); test.WriteByte(0); test.WriteByte(1); test.WriteByte(2); test.WriteByte(3); test.WriteByte(4); test.WriteByte(5); test.WriteByte(6); test.WriteByte(7); test.Position = 0; Media.Common.EnumerableByteStream ebs = new Common.EnumerableByteStream(test); foreach (byte b in ebs.Take(4)) Console.WriteLine(b); ebs[8] = 8; Console.WriteLine(ebs[7] == 7); Console.WriteLine(ebs[8] == 8); Console.WriteLine(ebs.IndexOf(7) + " " + (ebs[ebs.IndexOf(7)] == 7)); //Test LinkedStream and EnumerableByteStream together ebs.Insert(6, 7); Console.WriteLine(ebs.IndexOf(7) + " " + (ebs[ebs.IndexOf(7)] == 6)); ebs.Insert(7, 7); Console.WriteLine(ebs[ebs.IndexOf(7)]); //Reset the stream back to index 0 //ebs.Reset(); byte[] data = new byte[] { 0, 1, 2, 3 }; using (Media.Common.Iterator<byte> it = new Media.Common.Iterator<byte>(data)) { using (IEnumerator<byte> enumerator = it) { while (enumerator.MoveNext()) { Console.WriteLine(enumerator.Current); it.SetCurrent(7); Console.WriteLine(it.Current); Console.WriteLine(enumerator.Current); } //it.Current = 7; it.SetCurrent(7); it.Reset(); foreach (byte B in it) Console.WriteLine(B); } } foreach (byte B in data) Console.WriteLine(B); Media.Common.EnumerableByteStream ebsx = new Common.EnumerableByteStream(test, 0, 6); foreach (byte b in ebsx) { Console.WriteLine(b); } //Test PerpetuatingEnumerable var validStates = ((IEnumerable<StateMachineState>)Enum.GetValues(typeof(StateMachineState))).Where(s => s != StateMachineState.Invalid); var currentState = StateMachineState.Start; var perpetual = new Media.Common.PerpetuatingEnumerable<StateMachineState>(currentState); System.Threading.Tasks.Task simpleTask = new System.Threading.Tasks.Task(() => perpetual.Any(run => !validStates.Contains(run))); simpleTask.Start(); int i = 0; perpetual.Perpetuated += (p, s) => { if (s == StateMachineState.Invalid) throw new Media.Common.PerpetuatingEnumerable<StateMachineState>.BreakInstruction(); Console.Write("----------------------------" + ++i + "----------------------------"); }; while (!simpleTask.IsCompleted) { Console.WriteLine("Looping" + currentState); currentState++; } Console.WriteLine("Not Looping" + currentState); //currentState is Invalid } #endregion
I personally would have also have done more work on the Manipulator
and IManipulaor.
They need better definition and should follow an IHardware
interface to allow this.
The same has been done with the Complementor for obvious reasons (or not so)
GPU
should added via the same abstraction and should be able support other things besides GPU's
also...
I would also personally like to write a Real Time Kernel in C# but the uses would be very limited at this point as the hardware to run .Net in a native state are not commonly available.
Until that time I will be working on Managed Media Aggregation as well as other cool ideas like Net 7 CSharp or D#
Let me know if you liked this article or found any of the concepts provided useful or interesting!
v//