25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

178 lines
4.4 KiB

  1. /* ----------------------------------------------------------------------
  2. * Project: CMSIS DSP Library
  3. * Title: arm_jensenshannon_distance_f16.c
  4. * Description: Jensen-Shannon distance between two vectors
  5. *
  6. * $Date: 23 April 2021
  7. * $Revision: V1.9.0
  8. *
  9. * Target Processor: Cortex-M and Cortex-A cores
  10. * -------------------------------------------------------------------- */
  11. /*
  12. * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved.
  13. *
  14. * SPDX-License-Identifier: Apache-2.0
  15. *
  16. * Licensed under the Apache License, Version 2.0 (the License); you may
  17. * not use this file except in compliance with the License.
  18. * You may obtain a copy of the License at
  19. *
  20. * www.apache.org/licenses/LICENSE-2.0
  21. *
  22. * Unless required by applicable law or agreed to in writing, software
  23. * distributed under the License is distributed on an AS IS BASIS, WITHOUT
  24. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  25. * See the License for the specific language governing permissions and
  26. * limitations under the License.
  27. */
  28. #include "dsp/distance_functions_f16.h"
  29. #if defined(ARM_FLOAT16_SUPPORTED)
  30. #include <limits.h>
  31. #include <math.h>
  32. /**
  33. @ingroup FloatDist
  34. */
  35. /**
  36. @defgroup JensenShannon Jensen-Shannon distance
  37. Jensen-Shannon distance
  38. */
  39. /**
  40. @addtogroup JensenShannon
  41. @{
  42. */
  43. #if !defined(ARM_MATH_MVE_FLOAT16) || defined(ARM_MATH_AUTOVECTORIZE)
  44. /// @private
  45. __STATIC_INLINE float16_t rel_entr(float16_t x, float16_t y)
  46. {
  47. return ((_Float16)x * (_Float16)logf((float32_t)((_Float16)x / (_Float16)y)));
  48. }
  49. #endif
  50. #if defined(ARM_MATH_MVE_FLOAT16) && !defined(ARM_MATH_AUTOVECTORIZE)
  51. #include "arm_helium_utils.h"
  52. #include "arm_vec_math_f16.h"
  53. float16_t arm_jensenshannon_distance_f16(const float16_t *pA,const float16_t *pB, uint32_t blockSize)
  54. {
  55. uint32_t blkCnt;
  56. float16_t tmp;
  57. f16x8_t a, b, t, tmpV, accumV;
  58. accumV = vdupq_n_f16(0.0f);
  59. blkCnt = blockSize >> 3;
  60. while (blkCnt > 0U) {
  61. a = vld1q(pA);
  62. b = vld1q(pB);
  63. t = vaddq(a, b);
  64. t = vmulq(t, 0.5f);
  65. tmpV = vmulq(a, vrecip_medprec_f16(t));
  66. tmpV = vlogq_f16(tmpV);
  67. accumV = vfmaq(accumV, a, tmpV);
  68. tmpV = vmulq_f16(b, vrecip_medprec_f16(t));
  69. tmpV = vlogq_f16(tmpV);
  70. accumV = vfmaq(accumV, b, tmpV);
  71. pA += 8;
  72. pB += 8;
  73. blkCnt--;
  74. }
  75. /*
  76. * tail
  77. * (will be merged thru tail predication)
  78. */
  79. blkCnt = blockSize & 7;
  80. if (blkCnt > 0U) {
  81. mve_pred16_t p0 = vctp16q(blkCnt);
  82. a = vldrhq_z_f16(pA, p0);
  83. b = vldrhq_z_f16(pB, p0);
  84. t = vaddq(a, b);
  85. t = vmulq(t, 0.5f);
  86. tmpV = vmulq_f16(a, vrecip_medprec_f16(t));
  87. tmpV = vlogq_f16(tmpV);
  88. accumV = vfmaq_m_f16(accumV, a, tmpV, p0);
  89. tmpV = vmulq_f16(b, vrecip_medprec_f16(t));
  90. tmpV = vlogq_f16(tmpV);
  91. accumV = vfmaq_m_f16(accumV, b, tmpV, p0);
  92. }
  93. arm_sqrt_f16((_Float16)vecAddAcrossF16Mve(accumV) / 2.0f16, &tmp);
  94. return (tmp);
  95. }
  96. #else
  97. /**
  98. * @brief Jensen-Shannon distance between two vectors
  99. *
  100. * This function is assuming that elements of second vector are > 0
  101. * and 0 only when the corresponding element of first vector is 0.
  102. * Otherwise the result of the computation does not make sense
  103. * and for speed reasons, the cases returning NaN or Infinity are not
  104. * managed.
  105. *
  106. * When the function is computing x log (x / y) with x == 0 and y == 0,
  107. * it will compute the right result (0) but a division by zero will occur
  108. * and should be ignored in client code.
  109. *
  110. * @param[in] pA First vector
  111. * @param[in] pB Second vector
  112. * @param[in] blockSize vector length
  113. * @return distance
  114. *
  115. */
  116. float16_t arm_jensenshannon_distance_f16(const float16_t *pA,const float16_t *pB, uint32_t blockSize)
  117. {
  118. _Float16 left, right,sum, tmp;
  119. float16_t result;
  120. uint32_t i;
  121. left = 0.0f16;
  122. right = 0.0f16;
  123. for(i=0; i < blockSize; i++)
  124. {
  125. tmp = ((_Float16)pA[i] + (_Float16)pB[i]) / 2.0f16;
  126. left += (_Float16)rel_entr(pA[i], tmp);
  127. right += (_Float16)rel_entr(pB[i], tmp);
  128. }
  129. sum = left + right;
  130. arm_sqrt_f16((_Float16)sum/2.0f16, &result);
  131. return(result);
  132. }
  133. #endif /* defined(ARM_MATH_MVEF) && !defined(ARM_MATH_AUTOVECTORIZE) */
  134. /**
  135. * @} end of JensenShannon group
  136. */
  137. #endif /* #if defined(ARM_FLOAT16_SUPPORTED) */