9
$\begingroup$

Currently, NumericArrays are directly supported by the most important array-related functions, what makes them a very attractive data structure for implementing highly efficient algorithms. Here is a (possibly incomplete) list of functions from the current Documentation which directly support NumericArrays as input and output data structure:

Part, Take, Drop, Flatten, Join, FunctionCompile, NetEncoder.

Other functions which directly support NumericArrays according to the Documentation include:

Dimensions, Length, ArrayDepth, NumericArrayQ, NumericArrayType, Normal, Image, Image3D, Audio.

Testing shows that Total also accepts NumericArray as input:

Total[NumericArray[{1, 2, 3}, "UnsignedInteger8"]]
6

But what is missing is the support even for the basic arithmetic operations on NumericArrays. For example, an attempt to add two arrays of the same type and shape returns unevaluated:

NumericArray[{1, 2, 3}, "UnsignedInteger8"] + NumericArray[{3, 4, 5}, "UnsignedInteger8"]

screenshot

There is undocumented built-in package "NumericArrayUtilities`" with the Description

Utilities for doing high-performance numeric computations.

It includes several utilities:

Needs["NumericArrayUtilities`"]
Names["NumericArrayUtilities`*"] // Length
38

But it seems they don't offer the desired functionality either.

My question:

How can I perform basic arithmetic operations on NumericArrays without converting them to usual arrays?

I'm most interested in subtraction and addition.

$\endgroup$
2
  • 1
    $\begingroup$ I think you need to compile a function with FunctionCompile to do that. $\endgroup$ May 24 at 7:12
  • $\begingroup$ It would count as a solution if there is a package/paclet adding such functionality. It is really strange that I can't find anything... $\endgroup$ May 24 at 12:57

1 Answer 1

9
$\begingroup$

It seems like no one answered this yet, so let me elaborate a little on my comment. A simple example of using FunctionCompile to add NumericArrays would be:

n1 = NumericArray[{1, 2, 3}, "UnsignedInteger8"];
n2 = NumericArray[{3, 4, 5}, "UnsignedInteger8"];
add = FunctionCompile[
   Function[
    {
     Typed[x, TypeSpecifier["NumericArray"]["UnsignedInteger8", 1]],
     Typed[y, TypeSpecifier["NumericArray"]["UnsignedInteger8", 1]]
     },
    x + y
    ]
   ];
add[n1, n2]
Normal[%]

{4, 6, 8}

So as you can see, this is a bit tedious because you need to define a new function for each type of array. I believe that there is work ongoing in the compiler team to have polymorphic types that would make this easier, but for the time being you can do something like:

Clear[addArrays];
addArrays[type_String, depth_Integer] := (
   addArrays[type, depth] = FunctionCompile[
     Function[
      {
       Typed[x, TypeSpecifier["NumericArray"][type, depth]],
       Typed[y, TypeSpecifier["NumericArray"][type, depth]]
       },
      x + y
      ]
     ]
   );
addArrays[n1_?NumericArrayQ, n2_?NumericArrayQ] := With[{
   types = NumericArrayType /@ {n1, n2},
   depths = ArrayDepth /@ {n1, n2}
   },
  If[And[SameQ @@ types, SameQ @@ depths],
   addArrays[types[[1]], depths[[1]]][n1, n2]
   ]
  ];

addArrays[NumericArray[{1, 2}, "UnsignedInteger64"], NumericArray[{2, 2}, "UnsignedInteger64"]]
$\endgroup$
2
  • $\begingroup$ Thank you, it is helpful. The main drawback of FunctionCompile is significant compilation time: runing the first function from your answer in a fresh kernel of version 13.0.1 takes 12.2 seconds on my machine, successive runs with slight modifications of the function body (e.g. replace x + y with x - y) take about 1.7 seconds. Compile by default works much faster, but it seemingly doesn't support NumericArray at all. $\endgroup$ May 24 at 12:37
  • $\begingroup$ @AlexeyPopkov Correct, the compilation time for a function is quite slow and loading the compiler code in a fresh kernel session is also very slow. That said: after compilation is done, you have a function that's basically as fast as your processor will allow. Compile is old functionality that only works with packed arrays. $\endgroup$ May 24 at 13:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.