From 1d84a1e8269b3f61aaa12219221e3bbf68a61fc6 Mon Sep 17 00:00:00 2001
From: Eric Kunze <eric.kunze@arm.com>
Date: Wed, 14 Oct 2020 16:54:14 -0700
Subject: Use rank() instead of dimensions() in pseudocode

rank() is consistent with the rest of the specification.
Also add a bit of whitespace in the pseudocode for easier
reading.
Fix one typo.

Change-Id: Ifa794b2c332cb70cd52a141d9af219e26bd3dca0
Signed-off-by: Eric Kunze <eric.kunze@arm.com>
---
 chapters/introduction.adoc | 77 +++++++++++++++++++++++-----------------------
 1 file changed, 39 insertions(+), 38 deletions(-)

(limited to 'chapters/introduction.adoc')

diff --git a/chapters/introduction.adoc b/chapters/introduction.adoc
index ddc88c0..4137e8f 100644
--- a/chapters/introduction.adoc
+++ b/chapters/introduction.adoc
@@ -151,11 +151,11 @@ 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.
 ....
 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==aint8_t || zero_point==0)
+  assert(in_t == aint8_t || zero_point==0)
   unsigned offset = 0;
-  for (i=0; i<dimensions(shape); i++)
-    if (index[i]<0) { assert(pad && pad[2*i]+index[i]>=0); return 0; }
-    if (index[i]>=shape[i]) { assert(pad && index[i]<shape[i]+pad[2*i+1]); return 0; }
+  for (i = 0; i < rank(shape); i++)
+    if (index[i] < 0) { assert(pad && pad[2 * i] + index[i] >= 0); return 0; }
+    if (index[i] >= shape[i]) { assert(pad && index[i] < shape[i] + pad[2 * i + 1]); return 0; }
     offset = offset * shape[i] + index[i]
   }
   return address[offset] - zero_point;
@@ -167,8 +167,8 @@ out_t tensor_read<in_t>(in_t *address, dim_t shape, dim_t index, in_t zero_point
 ....
 tensor_write<type>(<type> *address, dim_t shape, dim_t index, <type> value) {
   unsigned offset = 0;
-  for (i=0; i<dimensions(shape); i++)
-    assert (index[i]>=0 && index[i]<shape[i]);
+  for (i = 0; i < rank(shape); i++)
+    assert (index[i] >= 0 && index[i] < shape[i]);
     offset = offset * shape[i] + index[i];
   }
   address[offset] = value;
@@ -177,7 +177,8 @@ tensor_write<type>(<type> *address, dim_t shape, dim_t index, <type> value) {
 
 ==== Broadcasting
 
-In operations where broadcasting is supported, an input shape dimension can be broadcast to an output shape dimension if the dimensions are equal or the input shape dimension is 1.
+In operations where broadcasting is supported, an input shape dimension can be broadcast to an output shape dimension if the dimensions are equal or the input shape dimension is 1. TOSA broadcast requires the rank of both tensors
+to be the same. A RESHAPE can be done to create a compatible tensor with appropriate dimensions of size 1.
 
 *Functionality of broadcast*
 
@@ -185,10 +186,10 @@ The following function maps an index in the output tensor to an index in the inp
 
 ....
 dim_t apply_broadcast(dim_t out_shape, dim_t in_shape, dim_t index) {
-  assert(dimensions(out_shape)==dimensions(in_shape));
-  for (i=0; i<dimensions(out_shape); i++) {
+  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);
+      assert(in_shape[i] == 1);
       index[i] = 0;
     }
   }
@@ -220,11 +221,11 @@ The apply_scale functions provide a scaling of approximately (multiplier * 2^-sh
 ....
 int32_t apply_scale_32(int32_t value, int32_t multipler, uint6_t shift, bool double_round) {
   assert(multiplier >= 0);
-  assert(2<=shift && shift<=62);
-  int64_t round = 1<<(shift-1);
+  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;
+    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;
@@ -234,8 +235,8 @@ int32_t apply_scale_32(int32_t value, int32_t multipler, uint6_t shift, bool dou
 
 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));
+  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>);
@@ -256,30 +257,30 @@ In places where a divide is required, we also use the function below to calculat
 
 ....
 scale_t reciprocal_scale(uint32_t value) {
-  assert(value > 0)
-  scale_t scale ;
-  int k = 32-count_leading_zero(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;
 }
 ....
 
-The following functuons provide basic arithmetic with asserts that values stay in the valid range supported by TOSA.
+The following functions provide basic arithmetic with asserts that values stay in the valid range supported by TOSA.
 
 ....
 acc_t apply_add<acc_t>(acc_t a, acc_t b) {
-    if (acc_t==float) return a+b;
+    if (acc_t == float) return a + b;
     int64_t c = (int64_t)a + (int64_t)b;
-    assert( c >= minimum<acc_t> && c <= maximum<acc_t> );
+    assert(c >= minimum<acc_t> && c <= maximum<acc_t>);
     return (acc_t)c;
 }
 
 acc_t apply_sub<acc_t>(acc_t a, acc_t b) {
-    if (acc_t==float) return a-b;
+    if (acc_t == float) return a - b;
     int64_t c = (int64_t)a - (int64_t)b;
-    assert( c >= minimum<acc_t> && c <= maximum<acc_t> );
+    assert(c >= minimum<acc_t> && c <= maximum<acc_t>);
     return (acc_t)c;
 }
 ....
@@ -288,18 +289,18 @@ The following functions are used in the pseudocode to take maximum, minimum or c
 
 ....
 <type> apply_max<type>(<type> a, <type> b) {
-    if (a>=b) return a ; else return b ;
+    if (a >= b) return a; else return b;
 }
 
 <type> apply_min<type>(<type> a, <type> b) {
-    if (a<b) return a ; else return b ;
+    if (a < b) return a; else return b;
 }
 
 <type> apply_clip<type>(<type> value, <type> min_val, <type> max_val) {
-    assert(min_val <= max_val)
-    value = apply_max(value, min_val) ;
-    value = apply_min(value, max_val) ;
-    return value ;
+    assert(min_val <= max_val);
+    value = apply_max(value, min_val);
+    value = apply_min(value, max_val);
+    return value;
 }
 ....
 
@@ -323,12 +324,12 @@ General unary functions such as sigmoid(), tanh(), exp() are expressed using loo
 int32_t apply_lookup(int16_t *table, int value)
 {
     value = apply_clip(value, -32768, +32767)
-    index = (value+32768) >> 7
+    index = (value + 32768) >> 7
     fraction = value & 0x7f
     base = table[index]
     next = table[index+1]
     value = (base << 7) + (next - base) * fraction
-    return value;	// return interpolated value of 16+7=23 bits
+    return value;	// return interpolated value of 16 + 7 = 23 bits
 }
 ....
 
@@ -338,9 +339,9 @@ The following code constructs a 513-entry table based on a reference function.
 ....
 void generate_lookup_table(int16_t *table, int (*reference)(int))
 {
-    for (int i=-256; i<=256; i++) {
+    for (int i = -256; i <= 256; i++) {
         value = (*reference)(i);
-        table[i+256] = clip(value, -32768, +32767)
+        table[i + 256] = clip(value, -32768, +32767)
     }
 }
 ....
-- 
cgit v1.2.1

