ALGO_UCL_ATY.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. /**
  2. * @file ALGO_UCL_ATY.c
  3. *
  4. * @param Project ALGO_Algorithm_ATY_LIB
  5. *
  6. * @author ATY
  7. *
  8. * @copyright
  9. * - Copyright 2017 - 2023 MZ-ATY
  10. * - This code follows:
  11. * - MZ-ATY Various Contents Joint Statement -
  12. * <a href="https://mengze.top/MZ-ATY_VCJS">
  13. * https://mengze.top/MZ-ATY_VCJS</a>
  14. * - CC 4.0 BY-NC-SA -
  15. * <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/">
  16. * https://creativecommons.org/licenses/by-nc-sa/4.0/</a>
  17. * - Your use will be deemed to have accepted the terms of this statement.
  18. *
  19. * @brief Familiar functions of UCL algorithm
  20. *
  21. * @version
  22. * - 1_01_220605 > ATY
  23. * -# Preliminary version, first Release
  24. ********************************************************************************
  25. */
  26. #ifndef __ALGO_UCL_ATY_C
  27. #define __ALGO_UCL_ATY_C
  28. #include "ALGO_UCL_ATY.h"
  29. /******************************* For user *************************************/
  30. /******************************************************************************/
  31. /**
  32. * @brief count number of 2.83L convert to ft3
  33. * @param count count number of 2.83L
  34. * @note 1ft3 = 28.3168466L, 0.1ft3 = 2.83L
  35. * @return convert number of ft3
  36. */
  37. uint32_t UCL_CountConvertFt3_1(uint32_t count)
  38. {
  39. return count * 10;
  40. }
  41. /**
  42. * @brief count number of 2.83L convert to ft3
  43. * @param count count number group of 2.83L
  44. * @param size group size
  45. * @note 1ft3 = 28.3168466L, 0.1ft3 = 2.83L
  46. * @return convert number group of ft3
  47. */
  48. uint32_t* UCL_CountConvertFt3(uint32_t* count, uint8_t size)
  49. {
  50. uint32_t* temp_uint32;
  51. temp_uint32 = (uint32_t*)malloc(sizeof(uint32_t) * size);
  52. for(uint8_t i = 0; i < size; i++)
  53. temp_uint32[i] = count[i] * 10;
  54. return temp_uint32;
  55. }
  56. /**
  57. * @brief count number of 2.83L convert to m3
  58. * @param count count number of 2.83L
  59. * @return convert number of m3
  60. */
  61. uint32_t UCL_CountConvertM3_1(uint32_t count)
  62. {
  63. float temp_f;
  64. uint32_t temp_uint32;
  65. temp_uint32 = (uint32_t)malloc(sizeof(uint32_t));
  66. // temp_f = (count * 1000 / 2.83168466) * 10;
  67. temp_f = (count * 1000 / 2.83) * 10;
  68. temp_uint32 = (uint32_t)temp_f;
  69. // decimal point rounding (4-5)
  70. temp_uint32 = (uint32_t)((temp_uint32 % 10 >= 5) ?
  71. (temp_uint32 / 10 + 1) : (temp_uint32 / 10));
  72. return temp_uint32;
  73. }
  74. /**
  75. * @brief count number of 2.83L convert to m3
  76. * @param count count number group of 2.83L
  77. * @param size group size
  78. * @return convert number group of m3
  79. */
  80. uint32_t* UCL_CountConvertM3(uint32_t* count, uint8_t size)
  81. {
  82. float temp_f;
  83. uint32_t* temp_uint32;
  84. temp_uint32 = (uint32_t*)malloc(sizeof(uint32_t) * size);
  85. for(uint8_t i = 0; i < size; i++)
  86. {
  87. // temp_f = (count[i] * 1000 / 2.83168466) * 10;
  88. temp_f = (count[i] * 1000 / 2.83) * 10;
  89. temp_uint32[i] = (uint32_t)temp_f;
  90. // decimal point rounding (4-5)
  91. #ifdef __DEBUG_ALGO_UCL_ATY
  92. printf("CountConvertM3 - 1: temp_uint32[%d] = %d", i, temp_uint32);
  93. #endif /* __DEBUG_ALGO_UCL_ATY */
  94. temp_uint32[i] = (uint32_t)((temp_uint32[i] % 10 >= 5) ?
  95. (temp_uint32[i] / 10 + 1) : (temp_uint32[i] / 10));
  96. #ifdef __DEBUG_ALGO_UCL_ATY
  97. printf("CountConvertM3 - 1: temp_uint32[%d] = %d", i, temp_uint32);
  98. #endif /* __DEBUG_ALGO_UCL_ATY */
  99. }
  100. return temp_uint32;
  101. }
  102. /**
  103. * @brief calculate average of particle concentration at a sampling point, grain/m3
  104. * @param count count number group of particle concentration at a sampling point
  105. * @param size group size - number of samples at a sampling point
  106. * @note A = (C1 + C2 + ... + CN) / N
  107. * @return average of particle concentration - average_A
  108. */
  109. uint32_t UCL_AAverageCalculate(uint32_t* count, uint8_t size)
  110. {
  111. float temp_f = 0.0;
  112. uint32_t temp_uint32;
  113. for(uint8_t i = 0; i < size; i++)
  114. temp_f += count[i];
  115. temp_f = (temp_f / size) * 10;
  116. temp_uint32 = (uint32_t)temp_f;
  117. // decimal point rounding (4-5)
  118. temp_uint32 = (uint32_t)((temp_uint32 % 10 >= 5) ?
  119. (temp_uint32 / 10 + 1) : (temp_uint32 / 10));
  120. return temp_uint32;
  121. }
  122. /**
  123. * @brief calculate average of average_A, grain/m3
  124. * @param count count number group of average_A
  125. * @param size group size - total number of sampling points in a clean room
  126. * @note M = (A1 + A2 + ... + AL) / L
  127. * @return average of average_A - average_M
  128. */
  129. uint32_t UCL_MAverageCalculate(uint32_t* count, uint8_t size)
  130. {
  131. return UCL_AAverageCalculate(count, size);
  132. }
  133. /**
  134. * @brief calculate standard error of average_M, grain/m3
  135. * @param count count number group of average_A
  136. * @param size group size - total number of sampling points in a clean room
  137. * @param average_M average of average_A
  138. * @return standard error of average_M - SE
  139. */
  140. uint32_t UCL_SE_Calculate(uint32_t* count, uint8_t size, uint32_t average_M)
  141. {
  142. float temp_f = 0.0;
  143. uint32_t temp_uint32;
  144. for(uint8_t i = 0; i < size; i++)
  145. temp_f += (count[i] - average_M) * (count[i] - average_M);
  146. temp_f = temp_f / (size * (size - 1));
  147. temp_f = (uint32_t)(sqrt(temp_f) * 10);
  148. temp_uint32 = (uint32_t)temp_f;
  149. // decimal point rounding (4-5)
  150. temp_uint32 = (uint32_t)(temp_uint32 % 10 >= 5) ?
  151. (temp_uint32 / 10 + 1) : (temp_uint32 / 10);
  152. return temp_uint32;
  153. }
  154. /**
  155. * @brief calculate 95% UCL, grain/m3
  156. * @param M average of average_A
  157. * @param SE standard error of average_M
  158. * @param L total number of sampling points in a clean room
  159. * @note UCL = M + t * SE
  160. * | **L** | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | >9 |
  161. * |:-----:|:----:|:----:|:----:|:----:|:----:|:----:|:----:|:----:|:---:|
  162. * | **t** | 6.31 | 2.92 | 2.35 | 2.13 | 2.02 | 1.94 | 1.90 | 1.86 | |
  163. * Note: UCL does not need to be calculated when sampling points are more than 9
  164. * @return 95% UCL
  165. */
  166. uint32_t UCL_Calculate(uint32_t M, uint32_t SE, uint8_t L)
  167. {
  168. if(L < 2) return 0;
  169. else if(L == 2) return (uint32_t)(M + 6.31 * SE);
  170. else if(L == 3) return (uint32_t)(M + 2.92 * SE);
  171. else if(L == 4) return (uint32_t)(M + 2.35 * SE);
  172. else if(L == 5) return (uint32_t)(M + 2.13 * SE);
  173. else if(L == 6) return (uint32_t)(M + 2.02 * SE);
  174. else if(L == 7) return (uint32_t)(M + 1.94 * SE);
  175. else if(L == 8) return (uint32_t)(M + 1.90 * SE);
  176. else if(L == 9) return (uint32_t)(M + 1.86 * SE);
  177. else return ~0;
  178. }
  179. #ifdef __DEBUG_ALGO_UCL_ATY
  180. #define STP 2
  181. #define SSC 3
  182. uint8_t samplingTotalPoint = STP; // L
  183. uint8_t samplingSingleCount = SSC; // N
  184. // 94464
  185. // 65135
  186. // 172332
  187. uint32_t debugCollectData[STP * SSC] = {
  188. 291, 227, 284, // L1
  189. 219, 176, 158, // L2
  190. };
  191. // 6125
  192. // 4829
  193. // 9565
  194. uint32_t debugCollectData1[STP * SSC] = {
  195. 21, 22, 9,
  196. 15, 14, 12,
  197. };
  198. void UCL_CalculateTest(uint32_t* C, uint8_t N, uint8_t L)
  199. {
  200. uint8_t i, j;
  201. uint32_t* ut_32pt = UCL_CountConvertM3(C, N * L);
  202. uint32_t* avrA = (uint32_t*)malloc(sizeof(uint32_t) * L);;
  203. uint32_t avrM;
  204. uint32_t SE;
  205. uint32_t UCL;
  206. for(i = 0; i < L; i++)
  207. {
  208. avrA[i] = UCL_AAverageCalculate(ut_32pt + i * N, N);
  209. }
  210. avrM = UCL_MAverageCalculate(avrA, L);
  211. SE = UCL_SE_Calculate(avrA, L, avrM);
  212. UCL = UCL_Calculate(avrM, SE, L);
  213. for(i = 0; i < L; i++)
  214. {
  215. printf("Point %d: ", i);
  216. for(j = 0; j < N; j++)
  217. {
  218. // printf("%d ", C[i * N + j]);
  219. printf("%d_%d ", C[i * N + j], ut_32pt[i * N + j]);
  220. }
  221. printf("\r\n");
  222. printf("A%d = %d\r\n", i, avrA[i]);
  223. }
  224. printf("SE = %d\r\n", SE);
  225. printf("M = %d\r\n", avrM);
  226. printf("95%% UCL = %d\r\n", UCL);
  227. printf("\r\n-------------------------------------\r\n");
  228. free(ut_32pt);
  229. free(avrA);
  230. }
  231. void UCL_Test(void)
  232. {
  233. UCL_CalculateTest(debugCollectData, samplingSingleCount, samplingTotalPoint);
  234. UCL_CalculateTest(debugCollectData1, samplingSingleCount, samplingTotalPoint);
  235. }
  236. #endif /* __DEBUG_ALGO_UCL_ATY */
  237. #endif /* __ALGO_UCL_ATY_C */
  238. /******************************** End Of File *********************************/