/** * @file ALGO_UCL_ATY.c * * @param Project ALGO_Algorithm_ATY_LIB * * @author ATY * * @copyright * - Copyright 2017 - 2025 MZ-ATY * - This code follows: * - MZ-ATY Various Contents Joint Statement - * * https://mengze.top/MZ-ATY_VCJS * - CC 4.0 BY-NC-SA - * * https://creativecommons.org/licenses/by-nc-sa/4.0/ * - Your use will be deemed to have accepted the terms of this statement. * * @brief Familiar functions of UCL algorithm * * @version * - 1_01_220605 > ATY * -# Preliminary version, first Release ******************************************************************************** */ #ifndef __ALGO_UCL_ATY_C #define __ALGO_UCL_ATY_C #include "ALGO_UCL_ATY.h" /******************************* For user *************************************/ /******************************************************************************/ /** * @brief count number of 2.83L convert to ft3 * @param count count number of 2.83L * @note 1ft3 = 28.3168466L, 0.1ft3 = 2.83L * @return convert number of ft3 */ uint32_t UCL_CountConvertFt3_1(uint32_t count) { return count * 10; } /** * @brief count number of 2.83L convert to ft3 * @param count count number group of 2.83L * @param size group size * @note 1ft3 = 28.3168466L, 0.1ft3 = 2.83L * @return convert number group of ft3 */ uint32_t* UCL_CountConvertFt3(uint32_t* count, uint8_t size) { uint32_t* temp_uint32; temp_uint32 = (uint32_t*)malloc(sizeof(uint32_t) * size); for(uint8_t i = 0; i < size; i++) temp_uint32[i] = count[i] * 10; return temp_uint32; } /** * @brief count number of 2.83L convert to m3 * @param count count number of 2.83L * @return convert number of m3 */ uint32_t UCL_CountConvertM3_1(uint32_t count) { float temp_f; uint32_t temp_uint32; temp_uint32 = (uint32_t)malloc(sizeof(uint32_t)); // temp_f = (count * 1000 / 2.83168466) * 10; temp_f = (count * 1000 / 2.83) * 10; temp_uint32 = (uint32_t)temp_f; // decimal point rounding (4-5) temp_uint32 = (uint32_t)((temp_uint32 % 10 >= 5) ? (temp_uint32 / 10 + 1) : (temp_uint32 / 10)); return temp_uint32; } /** * @brief count number of 2.83L convert to m3 * @param count count number group of 2.83L * @param size group size * @return convert number group of m3 */ uint32_t* UCL_CountConvertM3(uint32_t* count, uint8_t size) { float temp_f; uint32_t* temp_uint32; temp_uint32 = (uint32_t*)malloc(sizeof(uint32_t) * size); for(uint8_t i = 0; i < size; i++) { // temp_f = (count[i] * 1000 / 2.83168466) * 10; temp_f = (count[i] * 1000 / 2.83) * 10; temp_uint32[i] = (uint32_t)temp_f; // decimal point rounding (4-5) #ifdef __DEBUG_ALGO_UCL_ATY printf("CountConvertM3 - 1: temp_uint32[%d] = %d", i, temp_uint32); #endif /* __DEBUG_ALGO_UCL_ATY */ temp_uint32[i] = (uint32_t)((temp_uint32[i] % 10 >= 5) ? (temp_uint32[i] / 10 + 1) : (temp_uint32[i] / 10)); #ifdef __DEBUG_ALGO_UCL_ATY printf("CountConvertM3 - 1: temp_uint32[%d] = %d", i, temp_uint32); #endif /* __DEBUG_ALGO_UCL_ATY */ } return temp_uint32; } /** * @brief calculate average of particle concentration at a sampling point, grain/m3 * @param count count number group of particle concentration at a sampling point * @param size group size - number of samples at a sampling point * @note A = (C1 + C2 + ... + CN) / N * @return average of particle concentration - average_A */ uint32_t UCL_AAverageCalculate(uint32_t* count, uint8_t size) { float temp_f = 0.0; uint32_t temp_uint32; for(uint8_t i = 0; i < size; i++) temp_f += count[i]; temp_f = (temp_f / size) * 10; temp_uint32 = (uint32_t)temp_f; // decimal point rounding (4-5) temp_uint32 = (uint32_t)((temp_uint32 % 10 >= 5) ? (temp_uint32 / 10 + 1) : (temp_uint32 / 10)); return temp_uint32; } /** * @brief calculate average of average_A, grain/m3 * @param count count number group of average_A * @param size group size - total number of sampling points in a clean room * @note M = (A1 + A2 + ... + AL) / L * @return average of average_A - average_M */ uint32_t UCL_MAverageCalculate(uint32_t* count, uint8_t size) { return UCL_AAverageCalculate(count, size); } /** * @brief calculate standard error of average_M, grain/m3 * @param count count number group of average_A * @param size group size - total number of sampling points in a clean room * @param average_M average of average_A * @return standard error of average_M - SE */ uint32_t UCL_SE_Calculate(uint32_t* count, uint8_t size, uint32_t average_M) { float temp_f = 0.0; uint32_t temp_uint32; for(uint8_t i = 0; i < size; i++) temp_f += (count[i] - average_M) * (count[i] - average_M); temp_f = temp_f / (size * (size - 1)); temp_f = (uint32_t)(sqrt(temp_f) * 10); temp_uint32 = (uint32_t)temp_f; // decimal point rounding (4-5) temp_uint32 = (uint32_t)(temp_uint32 % 10 >= 5) ? (temp_uint32 / 10 + 1) : (temp_uint32 / 10); return temp_uint32; } /** * @brief calculate 95% UCL, grain/m3 * @param M average of average_A * @param SE standard error of average_M * @param L total number of sampling points in a clean room * @note UCL = M + t * SE * | **L** | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | >9 | * |:-----:|:----:|:----:|:----:|:----:|:----:|:----:|:----:|:----:|:---:| * | **t** | 6.31 | 2.92 | 2.35 | 2.13 | 2.02 | 1.94 | 1.90 | 1.86 | | * Note: UCL does not need to be calculated when sampling points are more than 9 * @return 95% UCL */ uint32_t UCL_Calculate(uint32_t M, uint32_t SE, uint8_t L) { if(L < 2) return 0; else if(L == 2) return (uint32_t)(M + 6.31 * SE); else if(L == 3) return (uint32_t)(M + 2.92 * SE); else if(L == 4) return (uint32_t)(M + 2.35 * SE); else if(L == 5) return (uint32_t)(M + 2.13 * SE); else if(L == 6) return (uint32_t)(M + 2.02 * SE); else if(L == 7) return (uint32_t)(M + 1.94 * SE); else if(L == 8) return (uint32_t)(M + 1.90 * SE); else if(L == 9) return (uint32_t)(M + 1.86 * SE); else return ~0; } #ifdef __DEBUG_ALGO_UCL_ATY #define STP 2 #define SSC 3 uint8_t samplingTotalPoint = STP; // L uint8_t samplingSingleCount = SSC; // N // 94464 // 65135 // 172332 uint32_t debugCollectData[STP * SSC] = { 291, 227, 284, // L1 219, 176, 158, // L2 }; // 6125 // 4829 // 9565 uint32_t debugCollectData1[STP * SSC] = { 21, 22, 9, 15, 14, 12, }; void UCL_CalculateTest(uint32_t* C, uint8_t N, uint8_t L) { uint8_t i, j; uint32_t* ut_32pt = UCL_CountConvertM3(C, N * L); uint32_t* avrA = (uint32_t*)malloc(sizeof(uint32_t) * L);; uint32_t avrM; uint32_t SE; uint32_t UCL; for(i = 0; i < L; i++) { avrA[i] = UCL_AAverageCalculate(ut_32pt + i * N, N); } avrM = UCL_MAverageCalculate(avrA, L); SE = UCL_SE_Calculate(avrA, L, avrM); UCL = UCL_Calculate(avrM, SE, L); for(i = 0; i < L; i++) { printf("Point %d: ", i); for(j = 0; j < N; j++) { // printf("%d ", C[i * N + j]); printf("%d_%d ", C[i * N + j], ut_32pt[i * N + j]); } printf("\r\n"); printf("A%d = %d\r\n", i, avrA[i]); } printf("SE = %d\r\n", SE); printf("M = %d\r\n", avrM); printf("95%% UCL = %d\r\n", UCL); printf("\r\n-------------------------------------\r\n"); free(ut_32pt); free(avrA); } void UCL_Test(void) { UCL_CalculateTest(debugCollectData, samplingSingleCount, samplingTotalPoint); UCL_CalculateTest(debugCollectData1, samplingSingleCount, samplingTotalPoint); } #endif /* __DEBUG_ALGO_UCL_ATY */ #endif /* __ALGO_UCL_ATY_C */ /******************************** End Of File *********************************/