Skip to content

Commit

Permalink
Add NDArrays to cirq-google protos
Browse files Browse the repository at this point in the history
- This is a port of internal library to convert numpy ndarrays to proto
and back for serialization.
  • Loading branch information
dstrain115 committed Feb 4, 2025
1 parent 6c9db55 commit b5b28b4
Show file tree
Hide file tree
Showing 5 changed files with 1,278 additions and 0 deletions.
143 changes: 143 additions & 0 deletions cirq-google/cirq_google/api/v2/ndarrays.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
/*
* Packed arrays store n-dimensional, homogeneous numeric data in a serialized
* byte array, along with their shape and endianness. Their performance is
* competitive with labrad and flatbuffer serialization/deserialization due to
* the reduced scope of functionality (i.e. just arrays).
*
* Each packed type has:
* - shape: a list of integers that mimic numpy's shape parameter. That is,
* each element represents the length of a dimension. A 2-D n x m array would
* have the shape [n, m].
* - endianness: The endianness of encoding; client libraries are responsible
* for correcting mismatched endianness. We highly recommend client
* libraries to stick with consistent and, preferably, system-native
* endianness. Note that unspecified endianness defaults to little endian;
* this approximately reflects how protobufs are serialized on the wire.
*
* Note that different types are used to enforce typing in downstream data
* data sources without inspecting the proto data. (For instance, enforcing
* that a field stored as a proto is Complex128 requires only checking message
* type and not the data.)
*/
syntax = "proto3";
package cirq.google.api.v2;

option java_package = "com.google.cirq.google.api.v2";
option java_outer_classname = "NDArrayProto";
option java_multiple_files = true;


enum Endianness {
LITTLE_ENDIAN = 0;
BIG_ENDIAN = 1;
}

/*
* Array of interleaved (real, imaginary) pairs, each of which are 64-bit floats.
*/
message Complex128Array {
repeated uint32 shape = 1;
Endianness endianness = 2;
oneof data {
bytes flat_bytes = 3;
}
}

/*
* Array of interleaved (real, imaginary) pairs, each of which are 32-bit floats.
*/
message Complex64Array {
repeated uint32 shape = 1;
Endianness endianness = 2;
oneof data {
bytes flat_bytes = 3;
}
}

message Float16Array {
repeated uint32 shape = 1;
Endianness endianness = 2;
oneof data {
bytes flat_bytes = 3;
}
}

message Float32Array {
repeated uint32 shape = 1;
Endianness endianness = 2;
oneof data {
bytes flat_bytes = 3;
}
}

message Float64Array {
repeated uint32 shape = 1;
Endianness endianness = 2;
oneof data {
bytes flat_bytes = 3;
}
}

message Int64Array {
repeated uint32 shape = 1;
Endianness endianness = 2;
oneof data {
bytes flat_bytes = 3;
}
}

message Int32Array {
repeated uint32 shape = 1;
Endianness endianness = 2;
oneof data {
bytes flat_bytes = 3;
}
}

message Int16Array {
repeated uint32 shape = 1;
Endianness endianness = 2;
oneof data {
bytes flat_bytes = 3;
}
}

message Int8Array {
repeated uint32 shape = 1;
oneof data {
bytes flat_bytes = 2;
}
}

message UInt8Array {
repeated uint32 shape = 1;
oneof data {
bytes flat_bytes = 2;
}
}

/*
* BitArrays represent arbitrary shape bit arrays.
*
* They are packed into bytes, in big-endian bit order and therefore will
* consume ceil(product(shape) / 8) bytes.
*
* For example, say we have an array:
* array = [0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0]
* Where array[0] == 0, array[1] == 1, array[2] == 1, etc.
*
* It will get mapped into bytes as follows:
* 0 1 1 0 1 0 0 0 : 1 0 1 0
* [ byte 0 | byte 1 ]
* 7 6 5 4 3 2 1 0 : 7 6 5 4 3 2 1 0 <-- bit index in byte
* ^^^^^^^^^^^
* unused bits will be zeroed out
*
*/
message BitArray {
repeated uint32 shape = 1;
oneof data {
bytes flat_bytes = 2;
}
}

Loading

0 comments on commit b5b28b4

Please sign in to comment.