14
$\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$ Commented May 24, 2022 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$ Commented May 24, 2022 at 12:57

2 Answers 2

13
$\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$ Commented May 24, 2022 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$ Commented May 24, 2022 at 13:40
0
$\begingroup$

I don't have anything to add with respect to arithmetic on the NumericArray objects, which I feel Sjoerd covered well with their answer, but since OP asked about the package, I thought I would add this.

The functions inside the NumericArrayUtilities` package AFAIK are helper functions that are primarily of use to those developing new machine learning functionality and applications.

To see a list:

?NumericArrayUtilities`*

Doing this for any package will produce a nicely formatted grid of clickable links for each function in the package, that will (depending on output format!) look something like:

InformationDataGrid[{
    "ctx`" -> {
        "ctx`myFunctionName, ...
}}, ___]

if you are in input form, something slightly more terse in full form, or in a notebook,

A formatted InformationDataGrid[...]

Caveat: YMMV with subpackages and namespaces, etc... Grepping the function names in certain packages will also produce output that is extremely voluminous.

$\endgroup$
1
  • $\begingroup$ I asked about a package specifically for performing fast arithmetic operations on the NumericArray objects. Can you show, how this package can be used for this? $\endgroup$ Commented Feb 10, 2023 at 6:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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