Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C#: Generic Interface for Numbers

Tags:

c#

generics

I am trying to perform some generic number manipulation independent of the number type. However, I know of no way to use generics to do this. The first idea was to filter the incoming types with a where statement, but all of the number types are closed and are, therefore, not valid for a generic filter. Also, the generics don't allow standard numeric operations (addition, shift, etc), so the only solution I can come up with is to re-write each method non-generically. Any other ideas?

For reference, following is the code that I initially tried:

    private const int BYTE_SIZE = 8;

    private const int UINT16_SIZE = 16;

    private const int UINT32_SIZE = 32;

    private const int UINT64_SIZE = 64;

    public static byte[] ToBytes(UInt16[] pnaValues)
    {
        return ToSmaller<byte, UInt16>(pnaValues, BYTE_SIZE, UINT16_SIZE);
    }

    public static byte[] ToBytes(UInt32[] pnaValues)
    {
        return ToSmaller<byte, UInt32>(pnaValues, BYTE_SIZE, UINT32_SIZE);
    }

    ....

    public static UInt16[] ToUInt16s(byte[] pnaValues)
    {
        return ToLarger<UInt16, byte>(pnaValues, UINT16_SIZE, BYTE_SIZE);
    }

    public static UInt16[] ToUInt16s(UInt32[] pnaValues)
    {
        return ToSmaller<UInt16, UInt32>(pnaValues, UINT16_SIZE, UINT32_SIZE);
    }

    ...

    public static UInt64[] ToUInt64s(UInt32[] pnaValues)
    {
        return ToLarger<UInt64, UInt32>(pnaValues, UINT64_SIZE, UINT32_SIZE);
    }

    private static TLarger[] ToLarger<TLarger, TSmaller>(TSmaller[] pnaSmaller, int pnLargerSize, int pnSmallerSize)
        where TLarger : byte, UInt16, UInt32, UInt64
        where TSmaller : byte, UInt16, UInt32, UInt64
    {
        TLarger[] lnaRetVal = null;
        int lnSmallerPerLarger = pnLargerSize / pnSmallerSize;

        System.Diagnostics.Debug.Assert((pnLargerSize % pnSmallerSize) == 0);

        if (pnaSmaller != null)
        {
            System.Diagnostics.Debug.Assert((pnaSmaller % lnSmallerPerLarger) == 0);

            lnaRetVal = new TLarger[pnaSmaller.Length / lnSmallerPerLarger];

            for (int i = 0; i < lnaRetVal.Length; i++)
            {
                lnaRetVal[i] = 0;

                for (int j = 0; j < lnSmallerPerLarger; j++)
                {
                    lnaRetVal[i] = (lnaRetVal[i] << pnLargerSize) + pnaSmaller[i * lnSmallerPerLarger + j];
                }
            }
        }

        return lnaRetVal;
    }

    private static TSmaller[] ToSmaller<TSmaller, TLarger>(TLarger[] pnaLarger, int pnSmallerSize, int pnLargerSize)
        where TSmaller : byte, UInt16, UInt32, UInt64
        where TLarger : byte, UInt16, UInt32, UInt64
    {
        TSmaller[] lnaRetVal = null;
        int lnSmallerPerLarger = pnLargerSize / pnSmallerSize;

        System.Diagnostics.Debug.Assert((pnLargerSize % pnSmallerSize) == 0);

        if (pnaSmaller != null)
        {
            lnaRetVal = new TSmaller[pnaLarger.Length * lnSmallerPerLarger];

            for (int i = 0; i < lnaRetVal.Length; i++)
            {
                for (int j = 0; j < lnSmallerPerLarger; j++)
                {
                    lnaRetVal[i * lnSmallerPerLarger + (lnSmallerPerLarger - 1 - j)]
                        = pnaLarger[i] >> (j * pnLargerSize);
                }
            }
        }

        return lnaRetVal;
    }
like image 469
David Beckman Avatar asked Aug 24 '09 22:08

David Beckman


People also ask

What is\\ C?

\c means you are escaping the "c" character, allowing you to print c \c means you are escaping the "\" character, which allows you to print \c. Escaping a character means that you are making the compiler ignore the character, if it is used for any functions or is reserved within a string.

What C is used for?

C is a powerful general-purpose programming language. It can be used to develop software like operating systems, databases, compilers, and so on.

What is the full name of C?

In the real sense it has no meaning or full form. It was developed by Dennis Ritchie and Ken Thompson at AT&T bell Lab. First, they used to call it as B language then later they made some improvement into it and renamed it as C and its superscript as C++ which was invented by Dr.


1 Answers

There's no common interface for arithmetic operations implemented by numeric types. Generic operators might help solving your problem.

like image 108
mmx Avatar answered Sep 24 '22 15:09

mmx