Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
debug_log_numbers.cc
00001 /* Copyright 2018 The TensorFlow Authors. All Rights Reserved. 00002 00003 Licensed under the Apache License, Version 2.0 (the "License"); 00004 you may not use this file except in compliance with the License. 00005 You may obtain a copy of the License at 00006 00007 http://www.apache.org/licenses/LICENSE-2.0 00008 00009 Unless required by applicable law or agreed to in writing, software 00010 distributed under the License is distributed on an "AS IS" BASIS, 00011 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00012 See the License for the specific language governing permissions and 00013 limitations under the License. 00014 ==============================================================================*/ 00015 00016 // Implements debug logging for numbers by converting them into strings and then 00017 // calling the main DebugLog(char*) function. These are separated into a 00018 // different file so that platforms can just implement the string output version 00019 // of DebugLog() and then get the numerical variations without requiring any 00020 // more code. 00021 00022 #include "tensorflow/lite/experimental/micro/debug_log_numbers.h" 00023 00024 #include "tensorflow/lite/experimental/micro/debug_log.h" 00025 00026 namespace { 00027 00028 // All input buffers to the number conversion functions must be this long. 00029 static const int kFastToBufferSize = 48; 00030 00031 // Reverses a zero-terminated string in-place. 00032 char* ReverseStringInPlace(char* start, char* end) { 00033 char* p1 = start; 00034 char* p2 = end - 1; 00035 while (p1 < p2) { 00036 char tmp = *p1; 00037 *p1++ = *p2; 00038 *p2-- = tmp; 00039 } 00040 return start; 00041 } 00042 00043 // Appends a string to a string, in-place. You need to pass in the maximum 00044 // string length as the second argument. 00045 char* StrCatStr(char* main, int main_max_length, const char* to_append) { 00046 char* current = main; 00047 while (*current != 0) { 00048 ++current; 00049 } 00050 char* current_end = main + (main_max_length - 1); 00051 while ((*to_append != 0) && (current < current_end)) { 00052 *current = *to_append; 00053 ++current; 00054 ++to_append; 00055 } 00056 *current = 0; 00057 return current; 00058 } 00059 00060 // Populates the provided buffer with an ASCII representation of the number. 00061 char* FastUInt32ToBufferLeft(uint32_t i, char* buffer, int base) { 00062 char* start = buffer; 00063 do { 00064 int32_t digit = i % base; 00065 char character; 00066 if (digit < 10) { 00067 character = '0' + digit; 00068 } else { 00069 character = 'a' + (digit - 10); 00070 } 00071 *buffer++ = character; 00072 i /= base; 00073 } while (i > 0); 00074 *buffer = 0; 00075 ReverseStringInPlace(start, buffer); 00076 return buffer; 00077 } 00078 00079 // Populates the provided buffer with an ASCII representation of the number. 00080 char* FastInt32ToBufferLeft(int32_t i, char* buffer) { 00081 uint32_t u = i; 00082 if (i < 0) { 00083 *buffer++ = '-'; 00084 u = -u; 00085 } 00086 return FastUInt32ToBufferLeft(u, buffer, 10); 00087 } 00088 00089 // Converts a number to a string and appends it to another. 00090 char* StrCatInt32(char* main, int main_max_length, int32_t number) { 00091 char number_string[kFastToBufferSize]; 00092 FastInt32ToBufferLeft(number, number_string); 00093 return StrCatStr(main, main_max_length, number_string); 00094 } 00095 00096 // Converts a number to a string and appends it to another. 00097 char* StrCatUInt32(char* main, int main_max_length, uint32_t number, int base) { 00098 char number_string[kFastToBufferSize]; 00099 FastUInt32ToBufferLeft(number, number_string, base); 00100 return StrCatStr(main, main_max_length, number_string); 00101 } 00102 00103 // Populates the provided buffer with ASCII representation of the float number. 00104 // Avoids the use of any floating point instructions (since these aren't 00105 // supported on many microcontrollers) and as a consequence prints values with 00106 // power-of-two exponents. 00107 char* FastFloatToBufferLeft(float f, char* buffer) { 00108 char* current = buffer; 00109 char* current_end = buffer + (kFastToBufferSize - 1); 00110 // Access the bit fields of the floating point value to avoid requiring any 00111 // float instructions. These constants are derived from IEEE 754. 00112 const uint32_t sign_mask = 0x80000000; 00113 const uint32_t exponent_mask = 0x7f800000; 00114 const int32_t exponent_shift = 23; 00115 const int32_t exponent_bias = 127; 00116 const uint32_t fraction_mask = 0x007fffff; 00117 const uint32_t u = *reinterpret_cast<uint32_t*>(&f); 00118 const int32_t exponent = 00119 ((u & exponent_mask) >> exponent_shift) - exponent_bias; 00120 const uint32_t fraction = (u & fraction_mask); 00121 // Expect ~0x2B1B9D3 for fraction. 00122 if (u & sign_mask) { 00123 *current = '-'; 00124 current += 1; 00125 } 00126 *current = 0; 00127 // These are special cases for infinities and not-a-numbers. 00128 if (exponent == 128) { 00129 if (fraction == 0) { 00130 current = StrCatStr(current, (current_end - current), "Inf"); 00131 return current; 00132 } else { 00133 current = StrCatStr(current, (current_end - current), "NaN"); 00134 return current; 00135 } 00136 } 00137 // 0x007fffff (8388607) represents 0.99... for the fraction, so to print the 00138 // correct decimal digits we need to scale our value before passing it to the 00139 // conversion function. This scale should be 10000000/8388608 = 1.1920928955. 00140 // We can approximate this using multiply-adds and right-shifts using the 00141 // values in this array. The 1. portion of the number string is printed out 00142 // in a fixed way before the fraction, below. 00143 const int32_t scale_shifts_size = 13; 00144 const int8_t scale_shifts[13] = {3, 4, 8, 11, 13, 14, 17, 00145 18, 19, 20, 21, 22, 23}; 00146 uint32_t scaled_fraction = fraction; 00147 for (int i = 0; i < scale_shifts_size; ++i) { 00148 scaled_fraction += (fraction >> scale_shifts[i]); 00149 } 00150 *current = '1'; 00151 current += 1; 00152 *current = '.'; 00153 current += 1; 00154 *current = 0; 00155 current = StrCatUInt32(current, (current_end - current), scaled_fraction, 10); 00156 current = StrCatStr(current, (current_end - current), "*2^"); 00157 current = StrCatInt32(current, (current_end - current), exponent); 00158 return current; 00159 } 00160 00161 } // namespace 00162 00163 extern "C" void DebugLogInt32(int32_t i) { 00164 char number_string[kFastToBufferSize]; 00165 FastInt32ToBufferLeft(i, number_string); 00166 DebugLog(number_string); 00167 } 00168 00169 extern "C" void DebugLogUInt32(uint32_t i) { 00170 char number_string[kFastToBufferSize]; 00171 FastUInt32ToBufferLeft(i, number_string, 10); 00172 DebugLog(number_string); 00173 } 00174 00175 extern "C" void DebugLogHex(uint32_t i) { 00176 char number_string[kFastToBufferSize]; 00177 FastUInt32ToBufferLeft(i, number_string, 16); 00178 DebugLog(number_string); 00179 } 00180 00181 extern "C" void DebugLogFloat(float i) { 00182 char number_string[kFastToBufferSize]; 00183 FastFloatToBufferLeft(i, number_string); 00184 DebugLog(number_string); 00185 }
Generated on Wed Jul 13 2022 16:03:35 by
