You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

utils.cpp 3.1 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. // Copyright 2021 Tencent
  2. // SPDX-License-Identifier: BSD-3-Clause
  3. #include "utils.h"
  4. #include <math.h>
  5. namespace pnnx {
  6. unsigned short float32_to_float16(float value)
  7. {
  8. // 1 : 8 : 23
  9. union
  10. {
  11. unsigned int u;
  12. float f;
  13. } tmp;
  14. tmp.f = value;
  15. // 1 : 8 : 23
  16. unsigned short sign = (tmp.u & 0x80000000) >> 31;
  17. unsigned short exponent = (tmp.u & 0x7F800000) >> 23;
  18. unsigned int significand = tmp.u & 0x7FFFFF;
  19. // NCNN_LOGE("%d %d %d", sign, exponent, significand);
  20. // 1 : 5 : 10
  21. unsigned short fp16;
  22. if (exponent == 0)
  23. {
  24. // zero or denormal, always underflow
  25. fp16 = (sign << 15) | (0x00 << 10) | 0x00;
  26. }
  27. else if (exponent == 0xFF)
  28. {
  29. // infinity or NaN
  30. fp16 = (sign << 15) | (0x1F << 10) | (significand ? 0x200 : 0x00);
  31. }
  32. else
  33. {
  34. // normalized
  35. short newexp = exponent + (-127 + 15);
  36. if (newexp >= 31)
  37. {
  38. // overflow, return infinity
  39. fp16 = (sign << 15) | (0x1F << 10) | 0x00;
  40. }
  41. else if (newexp <= 0)
  42. {
  43. // Some normal fp32 cannot be expressed as normal fp16
  44. fp16 = (sign << 15) | (0x00 << 10) | 0x00;
  45. }
  46. else
  47. {
  48. // normal fp16
  49. fp16 = (sign << 15) | (newexp << 10) | (significand >> 13);
  50. }
  51. }
  52. return fp16;
  53. }
  54. float float16_to_float32(unsigned short value)
  55. {
  56. // 1 : 5 : 10
  57. unsigned short sign = (value & 0x8000) >> 15;
  58. unsigned short exponent = (value & 0x7c00) >> 10;
  59. unsigned short significand = value & 0x03FF;
  60. // NCNN_LOGE("%d %d %d", sign, exponent, significand);
  61. // 1 : 8 : 23
  62. union
  63. {
  64. unsigned int u;
  65. float f;
  66. } tmp;
  67. if (exponent == 0)
  68. {
  69. if (significand == 0)
  70. {
  71. // zero
  72. tmp.u = (sign << 31);
  73. }
  74. else
  75. {
  76. // denormal
  77. exponent = 0;
  78. // find non-zero bit
  79. while ((significand & 0x200) == 0)
  80. {
  81. significand <<= 1;
  82. exponent++;
  83. }
  84. significand <<= 1;
  85. significand &= 0x3FF;
  86. tmp.u = (sign << 31) | ((-exponent + (-15 + 127)) << 23) | (significand << 13);
  87. }
  88. }
  89. else if (exponent == 0x1F)
  90. {
  91. // infinity or NaN
  92. tmp.u = (sign << 31) | (0xFF << 23) | (significand << 13);
  93. }
  94. else
  95. {
  96. // normalized
  97. tmp.u = (sign << 31) | ((exponent + (-15 + 127)) << 23) | (significand << 13);
  98. }
  99. return tmp.f;
  100. }
  101. void apply_weight_norm(std::vector<float>& weight, const std::vector<float>& weight_g, int dim0, int size)
  102. {
  103. for (int i = 0; i < dim0; i++)
  104. {
  105. float* pw = weight.data() + i * size;
  106. double norm = 0.f;
  107. for (int j = 0; j < size; j++)
  108. {
  109. float w = pw[j];
  110. norm += w * w;
  111. }
  112. norm = sqrt(norm);
  113. for (int j = 0; j < size; j++)
  114. {
  115. pw[j] = pw[j] * (weight_g[i] / norm);
  116. }
  117. }
  118. }
  119. } // namespace pnnx