/**
* @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 *********************************/