33
$\begingroup$

RawArray seems to be able to efficiently hold integer and floating point data of various sizes.

What is RawArray good for? How can we use it?

$\endgroup$
32
$\begingroup$

This is a community wiki answer. Feel free to improve it.

Introduction

RawArray is an atomic array type that can hold data in any of the following formats:

"Integer8", "UnsignedInteger8", "Integer16", "UnsignedInteger16",
"Integer32", "UnsignedInteger32", "Integer64", "UnsignedInteger64",
"Real32", "Real64", "Complex64", "Complex128"

(Some aliases can also be used for the format names, e.g. "Byte" = "UnsignedInteger8", "Real" = "Real64", etc.)

It can be converted to/from standard numerical arrays.

It can be passed to LibraryLink functions and manipulated in C. The required header file, WolframRawArrayLibrary.h, was introduced in Mathematica 10.4.

The main use for this data structure appears to be C–Mathematica communication through LibraryLink (??). It allows having expressions which hold our data in its original binary format, and can be manipulated through functions we implement in C/LibraryLink. Indeed, the usual places to come across a RawArray in Mathematica are inside expressions such as Image, Audio, Raster, ColorProfileData, etc.

Manipulating arrays in Mathematica

The relevant functions are in the Developer context. Try ?Developer`*Raw*. Below, you will find example uses for each function:

Create a RawArray out of a normal list:

ra = RawArray["Real64", {1, 2, 3}]
(* RawArray[Real64,<3>] *)

Allocate a 3 by 3 array of 8-bit integers without specifying its data:

ra = Developer`AllocateRawArray["Integer8", {3, 3}]
(* RawArray[Integer8,<3,3>] *)

Developer`RawArrayQ[ra]
(* True *)

Developer`RawArrayType[ra]
(* "Integer8" *)

Convert to 32-bit integers:

ra2 = Developer`RawArrayConvert[ra, "Integer32"]
(* RawArray[Integer32,<3,3>] *)

Convert to a list (actually, packed array):

Developer`FromRawArray[ra]
(* {{-48, 73, -89}, {25, 1, 0}, {0, 0, 0}} *)

Normal[ra]
(* {{-48, 73, -89}, {25, 1, 0}, {0, 0, 0}} *)

Note that when the raw array was allocated, it wasn't initialized. The values inside are unpredictable.

Notes on RawArrayConvert:

RawArrayConvert takes a 3rd argument which can be True or False and controls how to do the conversion. I do not fully understand this yet, but it appears that:

When converting to a smaller type:

  • True takes the upper bits
  • False takes the lower bits

When converting to a larger type:

  • True repeats the bits to fill out all the available digits
  • False only fills in the lower digits

The default is True.

Functions that work on RawArray expressions

The following functions work and do what you would expect:

Dimensions, Length, ArrayDepth, Flatten, Join, Take, Drop, TakeDrop, ArrayReshape.

SameQ and Equal work and require the type to match.

The following do not work:

Part, Extract, First/Rest/Most/Last.

As a general guideline, functions which can potentially return or transform individual elements (such as Part) do not work.

Note that empty RawArrays decay to {}, e.g. RawArray["Byte",{}] -> {} or Take[ra, 0] -> {}.

Missing: What other standard functions can be used on RawArray?

Other ways to manipulate RawArrays

The methods in this section work on ByteArrays as well.

  • ra[k] gives the k+1th element, regardless of rank (i.e. it uses 0-based linear indexing). Warning: Modifying arrays this way is unsafe, as it does not trigger copy-on-write! ra2 = ra; ra2[0] = 0 will modify ra as well.

  • ra["Type"] returns the element type.

  • ra["Length"] returns the number of elements. This is not the same as Length[ra], which returns the first dimension.

  • ra["Dimensions"] returns the dimensions.

  • ra["Rank"] returns the tensor rank.

Manipulating arrays in C

RawArray objects can be passed between C and Mathematica using LibraryLink. The type specification to use in LibraryFunctionLoad is "RawArray", but RawArray or LibraryDataType[RawArray] also work. The type and dimensions cannot be given in the type specification (as they can for packed arrays).

In C,

#include "WolframLibrary.h"
#include "WolframRawArrayLibrary.h"

These headers must be included in this specific order.

The raw array handling functions are in libData->rawarrayLibraryFunctions instead of libData. Their names and uses are completely analogous to that of MTensor handling functions. Look into the header file WolframRawArrayLibrary.h to see what is available.

The raw array type is MRawArray, which is a pointer, just like MTensor.

Some notable differences from MTensors:

  • rawarray_t is an enum for the different element types the raw array can hold (i.e. "Integer8", etc.)

  • We have MRawArray_getType to get the type

  • We have a single void *MRawArray_getData(MRawArray) function instead of different functions for each type.

  • There is a function for converting between raw arrays with different element types: MRawArray MRawArray_convertType(MRawArray, rawarray_t)

  • The type specification in LibraryFunctionLoad is "RawArray", RawArray or LibraryDataType[RawArray]. It is not possible to restrict the element type or rank (or to request an automatic conversion to a certain element type), as is the case with packed arrays / MTensors.

LTemplate has experimental support for RawArray though GenericRawArray (unspecialized) and RawArrayRef<T> (specialized for a type). Unlike plain LibraryLink, LTemplate allows explicit element type specifications for raw arrays (only for type checking, not auto-conversion).

Missing: How does MRawArray_convertType compare to RawArrayConvert and its third argument?

Other applications in Mathematica

  • Image[ra, type] can create an image from a raw array. The image type must be specified and it must be compatible with the element type of the raw array.

  • Audio[ra, ...] can create an audio object from a RawArray of compatible type

  • RawArray["Byte", ba] can create an "UnsignedInteger8"-type raw array from the ByteArray ba.

$\endgroup$
  • $\begingroup$ This is far from complete, need many more details. Please edit this post if you can add something. $\endgroup$ – Szabolcs Dec 16 '16 at 14:06
  • $\begingroup$ I try to use MatrixForm/@Table[Normal[Developer`AllocateRawArray["Integer8",{3,3}]],10] to produce a random matrix,but it is seem not very random? $\endgroup$ – yode Dec 16 '16 at 17:38
  • 3
    $\begingroup$ @yode Unpredictable $\ne$ random. It's like when you allocate memory in C. You have no way of telling what the block of memory that you get contains already. But it is definitely not statistically random. I should have used the work uninitialized. $\endgroup$ – Szabolcs Dec 16 '16 at 18:58

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.