aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Kunze <eric.kunze@arm.com>2021-03-11 15:38:22 -0800
committerEric Kunze <eric.kunze@arm.com>2021-03-11 15:39:53 -0800
commit839830a72ebb27c4a818e15d3334e79085906dc8 (patch)
tree9999a6fc050d75122eb0a46a215558c0665d6e91
parent8e4a9d33f0527107fda724fc0f7b6b7c1f42bf79 (diff)
downloadspecification-839830a72ebb27c4a818e15d3334e79085906dc8.tar.gz
Make pseudocode block tags consistent
They are all now [source,c++] and use ---- as the delimiter. Also made the pseudocode indentation consistent (4 spaces) in the introduction sections. Signed-off-by: Eric Kunze <eric.kunze@arm.com> Change-Id: I1287a60cfeae8b7e3c63b9fc8885b1ebf3d3386d
-rw-r--r--chapters/activation_funcs.adoc15
-rw-r--r--chapters/comparison.adoc6
-rw-r--r--chapters/control_flow.adoc4
-rw-r--r--chapters/data_layout.adoc12
-rw-r--r--chapters/ewise_binary.adoc30
-rw-r--r--chapters/ewise_ternary.adoc2
-rw-r--r--chapters/ewise_unary.adoc10
-rw-r--r--chapters/image.adoc2
-rw-r--r--chapters/introduction.adoc141
-rw-r--r--chapters/operators.adoc15
-rw-r--r--chapters/scatter_gather.adoc4
-rw-r--r--chapters/tensor_ops.adoc18
-rw-r--r--chapters/type_conversion.adoc12
13 files changed, 145 insertions, 126 deletions
diff --git a/chapters/activation_funcs.adoc b/chapters/activation_funcs.adoc
index 7a4a7b6..5c8e36f 100644
--- a/chapters/activation_funcs.adoc
+++ b/chapters/activation_funcs.adoc
@@ -25,13 +25,14 @@ Clamp to an arbitrary minimum and maximum value. Note that the maximum and minim
|===
*Operation Function:*
-....
+[source,c++]
+----
for_each(index in shape) {
acc_t value = tensor_read<in_t>(input, shape, index);
acc = (in_t)apply_clip<acc_t>(value, min_val, max_val);
tensor_write<in_t>(output, shape, index, acc);
}
-....
+----
*Supported Data Types:*
@@ -59,7 +60,7 @@ ReLU with a scalar maximum value.
*Operation Function:*
-[source,c]
+[source,c++]
----
for_each(index in shape) {
in_t value = tensor_read<in_t>(input, shape, index);
@@ -86,8 +87,8 @@ the following definition.
The sigmoid table has 513 entries each of 16-bit precision and covering the input range -16.0 to +16.0 in steps of 1/16.
-[source,c]
-....
+[source,c++]
+----
int sigmoid_reference(int x) {|// input x range is -256 to + 256 inclusive
F64 v = (double)x / (double)16;
v = 1.0/(1.0 + exp(-v));
@@ -95,7 +96,7 @@ int sigmoid_reference(int x) {|// input x range is -256 to + 256 inclusive
}
generate_lookup_table(&sigmoid_table, &sigmoid_reference);
-....
+----
*Arguments:*
@@ -123,7 +124,7 @@ the following definition.
The tanh_table has 513 entries each of 16-bit precision and covering the input range -8.0 to +8.0 in steps of 1/32. The table is specified by:
-[source,c]
+[source,c++]
----
int tanh_reference(int x) { // input x range is -256 to +256 inclusive
F64 v = (double)x/(double)32;
diff --git a/chapters/comparison.adoc b/chapters/comparison.adoc
index 289196f..3d7ae05 100644
--- a/chapters/comparison.adoc
+++ b/chapters/comparison.adoc
@@ -25,7 +25,7 @@ Elementwise comparison operation
*Operation Function:*
-[source,c]
+[source,c++]
----
for_each(index in shape) {
index1 = apply_broadcast(shape, shape1, index);
@@ -61,7 +61,7 @@ Elementwise greater than comparison operation
*Operation Function:*
-[source,c]
+[source,c++]
----
for_each(index in shape) {
index1 = apply_broadcast(shape, shape1, index);
@@ -97,7 +97,7 @@ Elementwise comparison operation
*Operation Function:*
-[source,c]
+[source,c++]
----
for_each(index in shape) {
index1 = apply_broadcast(shape, shape1, index);
diff --git a/chapters/control_flow.adoc b/chapters/control_flow.adoc
index 31bdf3c..611d2e5 100644
--- a/chapters/control_flow.adoc
+++ b/chapters/control_flow.adoc
@@ -29,7 +29,7 @@ Evaluates a Boolean condition and then takes one of two distinct execution paths
*Operation Function:*
-[source,c]
+[source,c++]
----
assert(tensor_list_shape(input_list)==tosa_input_shape(then_graph));
assert(tensor_list_shape(input_list)==tosa_input_shape(else_graph));
@@ -60,7 +60,7 @@ Generates and evaluates a Bool condition and either executes a loop body or exit
*Operation Function:*
-[source,c]
+[source,c++]
----
assert(tensor_list_shape(input_list)==tosa_list_shape(output_list));
assert(tensor_list_shape(input_list)==tosa_input_shape(cond_graph));
diff --git a/chapters/data_layout.adoc b/chapters/data_layout.adoc
index b5b5112..4b01d55 100644
--- a/chapters/data_layout.adoc
+++ b/chapters/data_layout.adoc
@@ -79,7 +79,7 @@ Zero-pads a tensor along borders of each dimension.
*Operation Function:*
-[source,c]
+[source,c++]
----
for_each(index in shape) {
index1 = index;
@@ -119,7 +119,7 @@ Returns a tensor with the same type/values as the input, with a new shape specif
*Operation Function:*
-[source,c]
+[source,c++]
----
assert(tensor_size(shape1) == tensor_size(shape));
for(i = 0; i < tensor_size(shape); i++) {
@@ -155,7 +155,7 @@ Returns a tensor with the same type/values as the input, with the data reversed
*Operation Function:*
-[source,c]
+[source,c++]
----
assert(0 <= axis && axis < rank(shape));
for_each(index in shape) {
@@ -195,7 +195,7 @@ No data conversion happens during a slice operation.
*Operation Function:*
-[source,c]
+[source,c++]
----
for_each(index in shape) {
tmp_index = index;
@@ -235,7 +235,7 @@ Replicates input1 multiplies times along each dimension.
*Operation Function:*
-[source,c]
+[source,c++]
----
for_each(index in shape) {
tmp_index = index;
@@ -276,7 +276,7 @@ Permutes the dimensions based on perm.
*Operation Function:*
-[source,c]
+[source,c++]
----
for_each(index in shape) {
tmp_index = index;
diff --git a/chapters/ewise_binary.adoc b/chapters/ewise_binary.adoc
index 2b8d321..c005611 100644
--- a/chapters/ewise_binary.adoc
+++ b/chapters/ewise_binary.adoc
@@ -26,7 +26,7 @@ Axis of size 1 will be broadcast, as necessary. Rank of input tensors must match
*Operation Function:*
-[source,c]
+[source,c++]
----
for_each(index in shape) {
index1 = apply_broadcast(shape, shape1, index);
@@ -64,7 +64,7 @@ Axis of size 1 will be broadcast, as necessary. Rank of input tensors must match
*Operation Function:*
-[source,c]
+[source,c++]
----
for_each(index in shape) {
index1 = apply_broadcast(shape, shape1, index);
@@ -108,7 +108,7 @@ Axis of size 1 will be broadcast as necessary. Rank of input tensors must match.
*Operation Function:*
-[source,c]
+[source,c++]
----
for_each(index in shape) {
index1 = apply_broadcast(shape, shape1, index);
@@ -147,7 +147,7 @@ Axis of size 1 will be broadcast as necessary. Rank of input tensors must match.
*Operation Function:*
-[source,c]
+[source,c++]
----
for_each(index in shape) {
index1 = apply_broadcast(shape, shape1, index);
@@ -186,7 +186,7 @@ Axis of size 1 will be broadcast as necessary. Rank of input tensors must match.
*Operation Function:*
-[source,c]
+[source,c++]
----
for_each(index in shape) {
index1 = apply_broadcast(shape, shape1, index);
@@ -229,7 +229,7 @@ None
*Operation Function:*
-[source,c]
+[source,c++]
----
for_each(index in shape) {
index1 = apply_broadcast(shape, shape1, index);
@@ -266,7 +266,7 @@ Axis of size 1 will be broadcast, as necessary. Rank of input tensors must match
*Operation Function:*
-[source,c]
+[source,c++]
----
for_each(index in shape) {
index1 = apply_broadcast(shape, shape1, index);
@@ -306,7 +306,7 @@ Axis of size 1 will be broadcast, as necessary. Rank of input tensors must match
*Operation Function:*
-[source,c]
+[source,c++]
----
for_each(index in shape) {
index1 = apply_broadcast(shape, shape1, index);
@@ -346,7 +346,7 @@ Axis of size 1 will be broadcast as necessary. Rank of input tensors must match.
*Operation Function:*
-[source,c]
+[source,c++]
----
for_each(index in shape) {
index1 = apply_broadcast(shape, shape1, index);
@@ -383,7 +383,7 @@ Axis of size 1 will be broadcast as necessary. Rank of input tensors must match.
*Operation Function:*
-[source,c]
+[source,c++]
----
for_each(index in shape) {
index1 = apply_broadcast(shape, shape1, index);
@@ -420,7 +420,7 @@ Axis of size 1 will be broadcast, as necessary. Rank of input tensors must match
*Operation Function:*
-[source,c]
+[source,c++]
----
for_each(index in shape) {
index1 = apply_broadcast(shape, shape1, index);
@@ -458,7 +458,7 @@ Axis of size 1 will be broadcast, as necessary. Rank of input tensors must match
*Operation Function:*
-[source,c]
+[source,c++]
----
for_each(index in shape) {
index1 = apply_broadcast(shape, shape1, index);
@@ -497,7 +497,7 @@ Axis of size 1 will be broadcast, as necessary. Rank of input tensors must match
*Operation Function:*
-[source,c]
+[source,c++]
----
assert(in_t == int32_t || shift == 0);
for_each(index in shape) {
@@ -568,7 +568,7 @@ Axis of size 1 will be broadcast as necessary. Rank of input tensors must match.
*Operation Function:*
-[source,c]
+[source,c++]
----
for_each(index in shape) {
index1 = apply_broadcast(shape, shape1, index);
@@ -621,7 +621,7 @@ None
*Operation Function:*
-[source,c]
+[source,c++]
----
for_each(index in shape) {
in_t value = tensor_read<in_t>(input, shape, index);
diff --git a/chapters/ewise_ternary.adoc b/chapters/ewise_ternary.adoc
index 4d20316..e7f8c2e 100644
--- a/chapters/ewise_ternary.adoc
+++ b/chapters/ewise_ternary.adoc
@@ -30,7 +30,7 @@ None
*Operation Function:*
-[source,c]
+[source,c++]
----
for_each(index in shape) {
index1 = apply_broadcast(shape, shape1, index);
diff --git a/chapters/ewise_unary.adoc b/chapters/ewise_unary.adoc
index 3784274..21b14ef 100644
--- a/chapters/ewise_unary.adoc
+++ b/chapters/ewise_unary.adoc
@@ -24,7 +24,7 @@ Elementwise absolute value operation
*Operation Function:*
-[source,c]
+[source,c++]
----
for_each(index in shape) {
in_t value1 = tensor_read<in_t>(input1, shape, index);
@@ -62,7 +62,7 @@ None
*Operation Function:*
-[source,c]
+[source,c++]
----
for_each(index in shape) {
in_t value1 = tensor_read<in_t>(input1, shape, index);
@@ -117,7 +117,7 @@ Elementwise count leading zeros operation
*Operation Function:*
-[source,c]
+[source,c++]
----
for_each(index in shape) {
in_t acc = 0;
@@ -216,7 +216,7 @@ None
*Operation Function:*
-[source,c]
+[source,c++]
----
for_each(index in shape) {
in_t value1 = tensor_read<in_t>(input1, shape1, index);
@@ -257,7 +257,7 @@ Elementwise negation operation
*Operation Function:*
-[source,c]
+[source,c++]
----
assert(in_t == int8_t || input1_zp == 0) // Zero point only for int8_t
assert(in_t == int8_t || output_zp == 0) // Zero point only for int8_t
diff --git a/chapters/image.adoc b/chapters/image.adoc
index b84cf63..e91b3da 100644
--- a/chapters/image.adoc
+++ b/chapters/image.adoc
@@ -51,7 +51,7 @@ None
*Operation Function*
-[source,c]
+[source,c++]
----
// scale assert prevents int32_t accumulator overflow for in_t==int8_t
assert((resize_t == float_t && shift == 0)||(0 < shift && shift <= 11));
diff --git a/chapters/introduction.adoc b/chapters/introduction.adoc
index 7039e27..d410121 100644
--- a/chapters/introduction.adoc
+++ b/chapters/introduction.adoc
@@ -194,7 +194,9 @@ The following pseudocode represents the operations that will happen to data elem
If in_t is 8-bit then out_t=int16_t. Otherwise out_t is set to the same as in_t.
If padding is specified, the size of the padding array should be 2 times the size of the shape.
The padding array represents the before and after pair for each dimension.
-....
+
+[source,c++]
+----
assert((pad == NULL) || size(pad) == 2 * size(shape));
out_t tensor_read<in_t>(in_t *address, dim_t shape, dim_t index, in_t zero_point=0, dim_t pad=NULL) {
assert(in_t == int8_t || zero_point == 0)
@@ -212,11 +214,12 @@ out_t tensor_read<in_t>(in_t *address, dim_t shape, dim_t index, in_t zero_point
}
return address[offset] - zero_point;
}
-....
+----
*Functionality of tensor write*
-....
+[source,c++]
+----
tensor_write<type>(<type> *address, dim_t shape, dim_t index, <type> value) {
unsigned offset = 0;
for (i = 0; i < rank(shape); i++) {
@@ -225,7 +228,7 @@ tensor_write<type>(<type> *address, dim_t shape, dim_t index, <type> value) {
}
address[offset] = value;
}
-....
+----
==== Broadcasting
@@ -236,18 +239,19 @@ to be the same. A RESHAPE can be done to create a compatible tensor with appropr
The following function maps an index in the output tensor to an index in the input tensor.
-....
+[source,c++]
+----
dim_t apply_broadcast(dim_t out_shape, dim_t in_shape, dim_t index) {
- assert(rank(out_shape) == rank(in_shape));
- for (i = 0; i < rank(out_shape); i++) {
- if (out_shape[i] != in_shape[i]) {
- assert(in_shape[i] == 1);
- index[i] = 0;
+ assert(rank(out_shape) == rank(in_shape));
+ for (i = 0; i < rank(out_shape); i++) {
+ if (out_shape[i] != in_shape[i]) {
+ assert(in_shape[i] == 1);
+ index[i] = 0;
+ }
}
- }
- return index;
+ return index;
}
-....
+----
=== Quantization
@@ -278,54 +282,57 @@ Most operations in TOSA do not contain quantization scaling in the operation, bu
The apply_scale functions provide a scaling of approximately (multiplier * 2^-shift^). The shift range is limited to allow a variety of implementations. The upper limit of 62 allows it to be decomposed as two right shifts of 31. The lower limit removes special cases in the rounding. These restrictions have little practical impact since the shift value to achieve a scaling of 1.0 is 30 for apply_scale_32 with multiplier=1<<30 and 14 for apply_scale_16 with scale=1<<14. It follows that a scaling range of 2^+12^ down to 2^-32^ is supported for both functions with normalized multiplier. (Smaller scales can be obtained by denormalizing the multiplier).
-....
+[source,c++]
+----
int32_t apply_scale_32(int32_t value, int32_t multipler, uint6_t shift, bool_t double_round=false) {
- assert(multiplier >= 0);
- assert(2 <= shift && shift <= 62);
- int64_t round = 1 << (shift - 1);
- if (double_round) {
- if (shift > 31 && value >= 0) round += 1<<30;
- if (shift > 31 && value < 0) round -= 1<<30;
- }
- int64_t result = (int64_t)value * multiplier + round;
- result = result >> shift;
- assert(result >= minimum<int32_t> && result <= maximum<int32_t>);
- return (int32_t)result;
+ assert(multiplier >= 0);
+ assert(2 <= shift && shift <= 62);
+ int64_t round = 1 << (shift - 1);
+ if (double_round) {
+ if (shift > 31 && value >= 0) round += 1<<30;
+ if (shift > 31 && value < 0) round -= 1<<30;
+ }
+ int64_t result = (int64_t)value * multiplier + round;
+ result = result >> shift;
+ assert(result >= minimum<int32_t> && result <= maximum<int32_t>);
+ return (int32_t)result;
}
int32_t apply_scale_16(int48_t value, int16_t multipler, uint6_t shift) {
- assert(multiplier >= 0);
- assert(2 <= shift && shift <= 62);
- int64_t round = (1 << (shift - 1));
- int64_t result = (int64_t)value * multiplier + round;
- result = result >> shift;
- assert(result >= minimum<int32_t> && result <= maximum<int32_t>);
- return (int32_t)result;
+ assert(multiplier >= 0);
+ assert(2 <= shift && shift <= 62);
+ int64_t round = (1 << (shift - 1));
+ int64_t result = (int64_t)value * multiplier + round;
+ result = result >> shift;
+ assert(result >= minimum<int32_t> && result <= maximum<int32_t>);
+ return (int32_t)result;
}
-....
+----
In some functions, the multiplier and shift are combined into a scale_t structure:
-....
+[source,c++]
+----
typedef struct {
- int32_t multiplier;
- uint6_t shift;
+ int32_t multiplier;
+ uint6_t shift;
} scale_t;
-....
+----
In places where a divide is required, we also use the function below to calculate an appropriate scaling value.
-....
+[source,c++]
+----
scale_t reciprocal_scale(uint32_t value) {
- assert(value > 0);
- scale_t scale;
- int k = 32 - count_leading_zeros(value - 1); // (1 << k) / 2 < value <= (1 << k)
- int64_t numerator = ((1 << 30) + 1) << k;
- scale.multiplier = numerator / value; // (1 << 30) <= multiplier < (1 << 31)
- scale.shift = 30 + k;
- return scale;
+ assert(value > 0);
+ scale_t scale;
+ int k = 32 - count_leading_zeros(value - 1); // (1 << k) / 2 < value <= (1 << k)
+ int64_t numerator = ((1 << 30) + 1) << k;
+ scale.multiplier = numerator / value; // (1 << 30) <= multiplier < (1 << 31)
+ scale.shift = 30 + k;
+ return scale;
}
-....
+----
==== Quantized Convolutions
@@ -349,7 +356,8 @@ General unary functions such as sigmoid(), tanh(), exp() for integer inputs are
This also allows for other operations with the addition of user-supplied tables (the TABLE operation).
All table lookups are based on the following reference lookup function that takes as input a table of 513 entries of 16 bits each.
-....
+[source,c++]
+----
int32_t apply_lookup(int16_t *table, int32_t value)
{
int16_t clipped_value = (int16_t)apply_clip<int32_t>(value, -32768, +32767);
@@ -360,12 +368,13 @@ int32_t apply_lookup(int16_t *table, int32_t value)
int32_t return_value = (base << 7) + (next - base) * fraction;
return return_value; // return interpolated value of 16 + 7 = 23 bits
}
-....
+----
Note that although the table lookup defined here has 16-bit precision, for 8-bit only operations an 8-bit table can be derived by applying the reference function to each of the possible 256 input values.
The following code constructs a 513-entry table based on a reference function.
-....
+[source,c++]
+----
void generate_lookup_table(int16_t *table, int32_t (*reference)(int32_t))
{
for (int i = -256; i <= 256; i++) {
@@ -373,7 +382,7 @@ void generate_lookup_table(int16_t *table, int32_t (*reference)(int32_t))
table[i + 256] = (int16_t)apply_clip<int32_t>(value, -32768, +32767)
}
}
-....
+----
=== Floating-point
@@ -416,7 +425,8 @@ This section contains general pseudocode utility functions used throughout the s
The following functions provide basic arithmetic with asserts that values stay in the valid range supported by TOSA.
-....
+[source,c++]
+----
acc_t apply_add<acc_t>(acc_t a, acc_t b) {
if (acc_t == float_t) return a + b;
int64_t c = (int64_t)a + (int64_t)b;
@@ -430,12 +440,13 @@ acc_t apply_sub<acc_t>(acc_t a, acc_t b) {
assert(c >= minimum<acc_t> && c <= maximum<acc_t>);
return (acc_t)c;
}
-....
+----
The following functions are used in the pseudocode to take maximum,
minimum, clip values to a range, or count leading zeros.
[[count_leading_zeros]]
-....
+[source,c++]
+----
<type> apply_max<type>(<type> a, <type> b) {
if (a >= b) return a; else return b;
}
@@ -464,10 +475,12 @@ int32_t count_leading_zeros(int32_t a) {
}
return acc;
}
-....
+----
The following definitions are used in pseudocode to do numeric conversions.
-....
+
+[source,c++]
+----
int round_to_nearest_int(float_t f)
Converts the floating-point value to f, with rounding to the nearest integer value.
@@ -482,16 +495,18 @@ out_t sign_extend(in_t input)
out_t truncate(in_t input)
output is the sizeof(out_t) least significant bits in input.
-....
+----
The following definition is used to flatten a list of lists into a single list
-....
+
+[source,c++]
+----
in_t* flatten(in_t lists[]) {
- in_t output = [];
- for_each(list in lists) {
- for_each(element in list) {
- output.append(element);
+ in_t output = [];
+ for_each(list in lists) {
+ for_each(element in list) {
+ output.append(element);
+ }
}
- }
}
-....
+----
diff --git a/chapters/operators.adoc b/chapters/operators.adoc
index fa8cd47..896931a 100644
--- a/chapters/operators.adoc
+++ b/chapters/operators.adoc
@@ -21,25 +21,28 @@ An operator processes input operands to produce output operands. An operator can
Some operators, such as control flow operators, take a graph of other operators as an attribute. The type tosa_graph_t will denote a graph of operators and the following functions define the tensor shape list for the graph input and outputs:
-....
+[source,c++]
+----
shape_list_t tosa_input_shape(tosa_graph_t graph);
shape_list_t tosa_output_shape(tosa_graph_t graph);
-....
+----
Similarly the type tensor_list_t will be used for a list of tensors and the following function returns the shape of a tensor list:
-....
+[source,c++]
+----
shape_list_t tensor_list_shape(tosa_list_t tensor_list);
-....
+----
The following function denotes the execution of a TOSA graph, on an input tensor list to produce an output tensor list.
-....
+[source,c++]
+----
tosa_execute_graph(tosa_graph_t graph, tosa_list_t input_list, tosa_list_t output_list) {
assert(tensor_list_shape(input_list)==tosa_input_shape(graph));
assert(tensor_list_shape(output_list)==tosa_output_shape(graph));
<Execute TOSA graph operators as defined in this specification>
}
-....
+----
Note that within the graph, each input operand is instantiated as a PLACEHOLDER operator.
diff --git a/chapters/scatter_gather.adoc b/chapters/scatter_gather.adoc
index c2fcbe4..a657f55 100644
--- a/chapters/scatter_gather.adoc
+++ b/chapters/scatter_gather.adoc
@@ -30,7 +30,7 @@ None
*Operation Function:*
-[source,c]
+[source,c++]
----
for_each(0 <= n < N, 0 <= w < W, 0 <= c < C) {
index_t k = tensor_read<index_t>(indices, [N,W], [n,w]);
@@ -75,7 +75,7 @@ None
*Operation Function:*
-[source,c]
+[source,c++]
----
// The following array is used to check compliance that an output position
diff --git a/chapters/tensor_ops.adoc b/chapters/tensor_ops.adoc
index b006c71..291751f 100644
--- a/chapters/tensor_ops.adoc
+++ b/chapters/tensor_ops.adoc
@@ -29,7 +29,7 @@ None
*Operation Function:*
-[source,c]
+[source,c++]
----
assert(axis >= 0 && axis < k && k <=4);
left_shape = shape1[0:axis-1];
@@ -85,7 +85,7 @@ This performs an average pooling over the given input tensor. A sliding window o
*Operation Function:*
-[source,c]
+[source,c++]
----
assert(in_t == int8_t || input_zp == 0); // Zero point only for int8_t
assert(in_t == int8_t || output_zp == 0); // Zero point only for int8_t
@@ -152,7 +152,7 @@ Performs a 2D convolution over the given tensor input, using the weight tensor.
*Operation Function*
-[source,c]
+[source,c++]
----
assert(in_t == int8_t || input_zp == 0); // Zero point only for int8_t
assert(weight_t == int8_t || weight_zp == 0);
@@ -213,7 +213,7 @@ Performs a 3D convolution over the given input tensor.
*Operation Function*
-[source,c]
+[source,c++]
----
assert(in_t == int8_t || input_zp == 0); // Zero point only for int8_t
assert(weight_t == int8_t || weight_zp == 0);
@@ -277,7 +277,7 @@ Performs 2D convolutions separately over each channel of the given tensor input,
*Operation Function*
-[source,c]
+[source,c++]
----
assert(in_t == int8_t || input_zp == 0); // Zero point only for int8_t
assert(weight_t == int8_t || weight_zp == 0);
@@ -335,7 +335,7 @@ Performs a fully connected network.
*Operation Function*
-[source,c]
+[source,c++]
----
assert(in_t == int8_t || input_zp == 0); // Zero point only for int8_t
assert(weight_t == int8_t || weight_zp == 0);
@@ -386,7 +386,7 @@ Performs two dimensional matrix multiplications. This allows both inputs to be a
*Operation Function*
-[source,c]
+[source,c++]
----
assert(in_t == int8_t || (A_zp == 0 && B_zp == 0)); // Zero point only for int8_t
for_each(0 <= n < N, 0 <= h < H, 0 <= w < W) {
@@ -431,7 +431,7 @@ None
*Operation Function:*
-[source,c]
+[source,c++]
----
pad = flatten([0,0], pad, [0,0]);
for_each(0 <= n < N, 0 <= oy < H, 0 <= ox < W, 0 <= c < C ) {
@@ -487,7 +487,7 @@ Performs a 2D transposed convolution over the given tensor input, using the weig
*Operation Function*
-[source,c]
+[source,c++]
----
assert(in_t == int8_t || input_zp == 0); // Zero point only allowed for int8_t
assert(weight_t == int8_t || weight_zp == 0);
diff --git a/chapters/type_conversion.adoc b/chapters/type_conversion.adoc
index 6701297..2ca505e 100644
--- a/chapters/type_conversion.adoc
+++ b/chapters/type_conversion.adoc
@@ -24,8 +24,8 @@ Casts a tensor from one data type to another.
*Operation Function:*
-[source,c]
-....
+[source,c++]
+----
for_each(index in shape) {
in_t in = tensor_read<in_t>(input, shape, index);
out_t out;
@@ -44,7 +44,7 @@ for_each(index in shape) {
}
tensor_write<out_t>(output, shape, index, out)
}
-....
+----
*Supported Data Types:*
@@ -100,8 +100,8 @@ Rescale quantized values into a new domain. This function scales by factor: mult
*Operation Function:*
-[source,c]
-....
+[source,c++]
+----
for_each(index in shape) {
assert(in_t == int8_t || in_t == uint8_t || input_zp == 0);
assert(out_t == int8_t || out_t == uint8_t || output_zp == 0);
@@ -114,7 +114,7 @@ for_each(index in shape) {
result = (out_t)apply_clip<int32_t>(result + output_zp, minimum<out_t>, maximum<out_t>);
tensor_write<out_t>(output, shape, index, result);
}
-....
+----
*Supported Data Types:*