esp_nn_softmax_ansi.c 3.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. // Copyright 2022 Espressif Systems (Shanghai) PTE LTD
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include "softmax_common.h"
  15. int32_t esp_nn_get_softmax_scratch_size_ansi(const int32_t width, const int32_t height)
  16. {
  17. (void) width;
  18. (void) height;
  19. return 0;
  20. }
  21. void esp_nn_set_softmax_scratch_buf_ansi(void *buffer)
  22. {
  23. (void) buffer;
  24. return;
  25. }
  26. void esp_nn_softmax_s8_ansi(const int8_t *input_data,
  27. const int32_t height,
  28. const int32_t width,
  29. const int32_t mult,
  30. const int32_t shift,
  31. const int32_t diff_min,
  32. int8_t *output_data)
  33. {
  34. // The representation chosen for the input to the exp() function is Q5.26.
  35. // We need to leave extra space since values that we skip might be as large as
  36. // -32 before multiplying by input mult, and therefore as large as
  37. // -16 afterwards. Note that exp(-8) is definitely not insignificant to
  38. // accumulation, but exp(-16) definitely is.
  39. #define ACCUM_BITS 12
  40. #define DIFF_BITS 5
  41. const int32_t mask = (1 << shift);
  42. int32_t col = 0;
  43. const int8_t *in_ptr = input_data;
  44. int8_t *out_ptr = output_data;
  45. for (int row_idx = 0; row_idx < height; row_idx++) {
  46. int8_t max_in_row = in_ptr[0];
  47. for (col = 1; col < width; col++) {
  48. max_in_row = max(max_in_row, in_ptr[col]);
  49. }
  50. int32_t input_diff = 0;
  51. int32_t sum_of_exps = 0;
  52. for (col = 0; col < width; col++) {
  53. input_diff = in_ptr[col] - max_in_row;
  54. if (input_diff >= diff_min) {
  55. const int32_t input_diff_rescaled = SAT_HIGH_MUL(input_diff * mask, mult);
  56. const int32_t exp_raw = esp_nn_exp_on_negative_values(input_diff_rescaled);
  57. sum_of_exps += DIV_POW2(exp_raw, ACCUM_BITS);
  58. }
  59. }
  60. const int32_t headroom_plus1 = esp_nn_clz32((uint32_t) sum_of_exps);
  61. const int32_t shifted_scale = ONE_OVER_ONE_X((sum_of_exps << headroom_plus1) - (1 << 31));
  62. const int32_t bits_over_unit = ACCUM_BITS - headroom_plus1 + 31 - sizeof(int8_t) * 8;
  63. for (col = 0; col < width; col++) {
  64. input_diff = in_ptr[col] - max_in_row;
  65. if (input_diff >= diff_min) {
  66. const int32_t input_diff_rescaled = SAT_HIGH_MUL(input_diff * mask, mult);
  67. const int32_t exp_raw = esp_nn_exp_on_negative_values(input_diff_rescaled);
  68. const int32_t shifted_output = SAT_HIGH_MUL(shifted_scale, exp_raw);
  69. const int32_t result = DIV_POW2(shifted_output, bits_over_unit) - 128;
  70. out_ptr[col] = (int8_t) esp_nn_saturate8(result);
  71. } else {
  72. out_ptr[col] = -128;
  73. }
  74. }
  75. in_ptr += width;
  76. out_ptr += width;
  77. }
  78. }