C # General arrays and mathematical operations on it

I am currently participating in a project where I have very large volumes of images. These volumes must be processed very quickly (addition, subtraction, threshold value, etc.). In addition, most of the volume is so large that they do not fit into the system’s memory. For this reason, I created an abstract volume class (VoxelVolume), which places volume and image data and overloads operators so that regular mathematical operations on volumes can be performed. This opened up two more questions, which I will put in stackoverflow in two additional threads.

Here is my first question. My volume is implemented in such a way that it can contain only the data of the float array, but most of the data contained is from the image source UInt16. Only volume operations can create floating-point images.

When I started to implement such a volume, the class looked like this:

public abstract class VoxelVolume<T> 
{
...
}

but then I realized that overloading statements or return values ​​would become more complicated. An example is:

public abstract class VoxelVolume<T>
{
...
    public static VoxelVolume<T> Import<T>(param string[] files) 
    {
    } 
}

also adding two overload operators would be more complicated:

...
public static VoxelVolume<T> operator+(VoxelVolume<T> A, VoxelVolume<T> B)
{
...
}    

, , , . , , , . , , , . , , # . , , ++/CLR, , , 32- 64- -. , ++/CLR ( , ), (32 ), , (64-). ?

: . , # . (# → ++) .

,

float []A = new float[]{1,2,3};  
byte  []B = new byte[]{1,2,3};

float []C = A+B;

, , . , , :

public static class ArrayExt
{
    public static unsafe TResult[] Add<T1, T2, TResult>(T1 []A, T2 []B)
    {
       // Assume the length of both arrays is equal
       TResult[] result = new TResult[A.Length];

       GCHandle h1 = GCHandle.Alloc (A, Pinned);
       GCHandle h2 = GCHandle.Alloc (B, Pinned);
       GCHandle hR = GCHandle.Alloc (C, Pinned);

       void *ptrA = h1.ToPointer();
       void *ptrB = h2.ToPointer();
       void *ptrR = hR.ToPointer();

       for (int i=0; i<A.Length; i++)
       {
          *((TResult *)ptrR) = (TResult *)((T1)*ptrA + (T2)*ptrB));
       }

       h1.Free();
       h2.Free();
       hR.Free();

       return result;
    }
}

, , #. ? , , .


+3
4

() " INumerical ".

: , , + ((T1)*ptrA + (T2)*ptrB)).

+1

, float UInt32, , , VoxelVolume<UInt32> VoxelVolume<float> VoxelVolume<float>. . VoxelVolume<T1> VoxelVolume<T2> ( T1 T2). ,

public static VoxelVolume<T2> operator+(VoxelVolume<T1> A,VoxelVolume<T2> B)

T1 T2 , ?

+1

, , , . , T , .

, , , , -

++/CLI, , , generics, typename T , . , /clr:pure /clr:safe, MSIL, runnable AnyCPU, #.

+1

Admittedly, I did not read the whole question (this is too long), but:

  • VoxelVolume<T> where T : ISummand ... T a; a.Add(b)
  • static float Sum (this VoxelVolume<float> self, VoxelVolume<float> other) {...}
  • To add float to byte in any meaningful way, you need to convert bytes to float. Therefore, convert an array of bytes to an array of floats, and then add them, you will lose only some memory.
0
source

Source: https://habr.com/ru/post/1740675/


All Articles