153a5a1b3Sopenharmony_ci/* Copyright (C) 2002 Jean-Marc Valin */
253a5a1b3Sopenharmony_ci/**
353a5a1b3Sopenharmony_ci   @file math_approx.h
453a5a1b3Sopenharmony_ci   @brief Various math approximation functions for Speex
553a5a1b3Sopenharmony_ci*/
653a5a1b3Sopenharmony_ci/*
753a5a1b3Sopenharmony_ci   Redistribution and use in source and binary forms, with or without
853a5a1b3Sopenharmony_ci   modification, are permitted provided that the following conditions
953a5a1b3Sopenharmony_ci   are met:
1053a5a1b3Sopenharmony_ci
1153a5a1b3Sopenharmony_ci   - Redistributions of source code must retain the above copyright
1253a5a1b3Sopenharmony_ci   notice, this list of conditions and the following disclaimer.
1353a5a1b3Sopenharmony_ci
1453a5a1b3Sopenharmony_ci   - Redistributions in binary form must reproduce the above copyright
1553a5a1b3Sopenharmony_ci   notice, this list of conditions and the following disclaimer in the
1653a5a1b3Sopenharmony_ci   documentation and/or other materials provided with the distribution.
1753a5a1b3Sopenharmony_ci
1853a5a1b3Sopenharmony_ci   - Neither the name of the Xiph.org Foundation nor the names of its
1953a5a1b3Sopenharmony_ci   contributors may be used to endorse or promote products derived from
2053a5a1b3Sopenharmony_ci   this software without specific prior written permission.
2153a5a1b3Sopenharmony_ci
2253a5a1b3Sopenharmony_ci   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2353a5a1b3Sopenharmony_ci   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2453a5a1b3Sopenharmony_ci   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2553a5a1b3Sopenharmony_ci   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
2653a5a1b3Sopenharmony_ci   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
2753a5a1b3Sopenharmony_ci   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2853a5a1b3Sopenharmony_ci   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
2953a5a1b3Sopenharmony_ci   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
3053a5a1b3Sopenharmony_ci   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
3153a5a1b3Sopenharmony_ci   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
3253a5a1b3Sopenharmony_ci   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3353a5a1b3Sopenharmony_ci*/
3453a5a1b3Sopenharmony_ci
3553a5a1b3Sopenharmony_ci#ifndef MATH_APPROX_H
3653a5a1b3Sopenharmony_ci#define MATH_APPROX_H
3753a5a1b3Sopenharmony_ci
3853a5a1b3Sopenharmony_ci#include "arch.h"
3953a5a1b3Sopenharmony_ci
4053a5a1b3Sopenharmony_ci#ifndef FIXED_POINT
4153a5a1b3Sopenharmony_ci
4253a5a1b3Sopenharmony_ci#define spx_sqrt sqrt
4353a5a1b3Sopenharmony_ci#define spx_acos acos
4453a5a1b3Sopenharmony_ci#define spx_exp exp
4553a5a1b3Sopenharmony_ci#define spx_cos_norm(x) (cos((.5f*M_PI)*(x)))
4653a5a1b3Sopenharmony_ci#define spx_atan atan
4753a5a1b3Sopenharmony_ci
4853a5a1b3Sopenharmony_ci/** Generate a pseudo-random number */
4953a5a1b3Sopenharmony_cistatic inline spx_word16_t speex_rand(spx_word16_t std, spx_int32_t *seed)
5053a5a1b3Sopenharmony_ci{
5153a5a1b3Sopenharmony_ci   const unsigned int jflone = 0x3f800000;
5253a5a1b3Sopenharmony_ci   const unsigned int jflmsk = 0x007fffff;
5353a5a1b3Sopenharmony_ci   union {int i; float f;} ran;
5453a5a1b3Sopenharmony_ci   *seed = 1664525 * *seed + 1013904223;
5553a5a1b3Sopenharmony_ci   ran.i = jflone | (jflmsk & *seed);
5653a5a1b3Sopenharmony_ci   ran.f -= 1.5;
5753a5a1b3Sopenharmony_ci   return 3.4642*std*ran.f;
5853a5a1b3Sopenharmony_ci}
5953a5a1b3Sopenharmony_ci
6053a5a1b3Sopenharmony_ci
6153a5a1b3Sopenharmony_ci#endif
6253a5a1b3Sopenharmony_ci
6353a5a1b3Sopenharmony_ci
6453a5a1b3Sopenharmony_cistatic inline spx_int16_t spx_ilog2(spx_uint32_t x)
6553a5a1b3Sopenharmony_ci{
6653a5a1b3Sopenharmony_ci   int r=0;
6753a5a1b3Sopenharmony_ci   if (x>=(spx_int32_t)65536)
6853a5a1b3Sopenharmony_ci   {
6953a5a1b3Sopenharmony_ci      x >>= 16;
7053a5a1b3Sopenharmony_ci      r += 16;
7153a5a1b3Sopenharmony_ci   }
7253a5a1b3Sopenharmony_ci   if (x>=256)
7353a5a1b3Sopenharmony_ci   {
7453a5a1b3Sopenharmony_ci      x >>= 8;
7553a5a1b3Sopenharmony_ci      r += 8;
7653a5a1b3Sopenharmony_ci   }
7753a5a1b3Sopenharmony_ci   if (x>=16)
7853a5a1b3Sopenharmony_ci   {
7953a5a1b3Sopenharmony_ci      x >>= 4;
8053a5a1b3Sopenharmony_ci      r += 4;
8153a5a1b3Sopenharmony_ci   }
8253a5a1b3Sopenharmony_ci   if (x>=4)
8353a5a1b3Sopenharmony_ci   {
8453a5a1b3Sopenharmony_ci      x >>= 2;
8553a5a1b3Sopenharmony_ci      r += 2;
8653a5a1b3Sopenharmony_ci   }
8753a5a1b3Sopenharmony_ci   if (x>=2)
8853a5a1b3Sopenharmony_ci   {
8953a5a1b3Sopenharmony_ci      r += 1;
9053a5a1b3Sopenharmony_ci   }
9153a5a1b3Sopenharmony_ci   return r;
9253a5a1b3Sopenharmony_ci}
9353a5a1b3Sopenharmony_ci
9453a5a1b3Sopenharmony_cistatic inline spx_int16_t spx_ilog4(spx_uint32_t x)
9553a5a1b3Sopenharmony_ci{
9653a5a1b3Sopenharmony_ci   int r=0;
9753a5a1b3Sopenharmony_ci   if (x>=(spx_int32_t)65536)
9853a5a1b3Sopenharmony_ci   {
9953a5a1b3Sopenharmony_ci      x >>= 16;
10053a5a1b3Sopenharmony_ci      r += 8;
10153a5a1b3Sopenharmony_ci   }
10253a5a1b3Sopenharmony_ci   if (x>=256)
10353a5a1b3Sopenharmony_ci   {
10453a5a1b3Sopenharmony_ci      x >>= 8;
10553a5a1b3Sopenharmony_ci      r += 4;
10653a5a1b3Sopenharmony_ci   }
10753a5a1b3Sopenharmony_ci   if (x>=16)
10853a5a1b3Sopenharmony_ci   {
10953a5a1b3Sopenharmony_ci      x >>= 4;
11053a5a1b3Sopenharmony_ci      r += 2;
11153a5a1b3Sopenharmony_ci   }
11253a5a1b3Sopenharmony_ci   if (x>=4)
11353a5a1b3Sopenharmony_ci   {
11453a5a1b3Sopenharmony_ci      r += 1;
11553a5a1b3Sopenharmony_ci   }
11653a5a1b3Sopenharmony_ci   return r;
11753a5a1b3Sopenharmony_ci}
11853a5a1b3Sopenharmony_ci
11953a5a1b3Sopenharmony_ci#ifdef FIXED_POINT
12053a5a1b3Sopenharmony_ci
12153a5a1b3Sopenharmony_ci/** Generate a pseudo-random number */
12253a5a1b3Sopenharmony_cistatic inline spx_word16_t speex_rand(spx_word16_t std, spx_int32_t *seed)
12353a5a1b3Sopenharmony_ci{
12453a5a1b3Sopenharmony_ci   spx_word32_t res;
12553a5a1b3Sopenharmony_ci   *seed = 1664525 * *seed + 1013904223;
12653a5a1b3Sopenharmony_ci   res = MULT16_16(EXTRACT16(SHR32(*seed,16)),std);
12753a5a1b3Sopenharmony_ci   return EXTRACT16(PSHR32(SUB32(res, SHR32(res, 3)),14));
12853a5a1b3Sopenharmony_ci}
12953a5a1b3Sopenharmony_ci
13053a5a1b3Sopenharmony_ci/* sqrt(x) ~= 0.22178 + 1.29227*x - 0.77070*x^2 + 0.25723*x^3 (for .25 < x < 1) */
13153a5a1b3Sopenharmony_ci/*#define C0 3634
13253a5a1b3Sopenharmony_ci#define C1 21173
13353a5a1b3Sopenharmony_ci#define C2 -12627
13453a5a1b3Sopenharmony_ci#define C3 4215*/
13553a5a1b3Sopenharmony_ci
13653a5a1b3Sopenharmony_ci/* sqrt(x) ~= 0.22178 + 1.29227*x - 0.77070*x^2 + 0.25659*x^3 (for .25 < x < 1) */
13753a5a1b3Sopenharmony_ci#define C0 3634
13853a5a1b3Sopenharmony_ci#define C1 21173
13953a5a1b3Sopenharmony_ci#define C2 -12627
14053a5a1b3Sopenharmony_ci#define C3 4204
14153a5a1b3Sopenharmony_ci
14253a5a1b3Sopenharmony_cistatic inline spx_word16_t spx_sqrt(spx_word32_t x)
14353a5a1b3Sopenharmony_ci{
14453a5a1b3Sopenharmony_ci   int k;
14553a5a1b3Sopenharmony_ci   spx_word32_t rt;
14653a5a1b3Sopenharmony_ci   k = spx_ilog4(x)-6;
14753a5a1b3Sopenharmony_ci   x = VSHR32(x, (k<<1));
14853a5a1b3Sopenharmony_ci   rt = ADD16(C0, MULT16_16_Q14(x, ADD16(C1, MULT16_16_Q14(x, ADD16(C2, MULT16_16_Q14(x, (C3)))))));
14953a5a1b3Sopenharmony_ci   rt = VSHR32(rt,7-k);
15053a5a1b3Sopenharmony_ci   return rt;
15153a5a1b3Sopenharmony_ci}
15253a5a1b3Sopenharmony_ci
15353a5a1b3Sopenharmony_ci/* log(x) ~= -2.18151 + 4.20592*x - 2.88938*x^2 + 0.86535*x^3 (for .5 < x < 1) */
15453a5a1b3Sopenharmony_ci
15553a5a1b3Sopenharmony_ci
15653a5a1b3Sopenharmony_ci#define A1 16469
15753a5a1b3Sopenharmony_ci#define A2 2242
15853a5a1b3Sopenharmony_ci#define A3 1486
15953a5a1b3Sopenharmony_ci
16053a5a1b3Sopenharmony_cistatic inline spx_word16_t spx_acos(spx_word16_t x)
16153a5a1b3Sopenharmony_ci{
16253a5a1b3Sopenharmony_ci   int s=0;
16353a5a1b3Sopenharmony_ci   spx_word16_t ret;
16453a5a1b3Sopenharmony_ci   spx_word16_t sq;
16553a5a1b3Sopenharmony_ci   if (x<0)
16653a5a1b3Sopenharmony_ci   {
16753a5a1b3Sopenharmony_ci      s=1;
16853a5a1b3Sopenharmony_ci      x = NEG16(x);
16953a5a1b3Sopenharmony_ci   }
17053a5a1b3Sopenharmony_ci   x = SUB16(16384,x);
17153a5a1b3Sopenharmony_ci
17253a5a1b3Sopenharmony_ci   x = x >> 1;
17353a5a1b3Sopenharmony_ci   sq = MULT16_16_Q13(x, ADD16(A1, MULT16_16_Q13(x, ADD16(A2, MULT16_16_Q13(x, (A3))))));
17453a5a1b3Sopenharmony_ci   ret = spx_sqrt(SHL32(EXTEND32(sq),13));
17553a5a1b3Sopenharmony_ci
17653a5a1b3Sopenharmony_ci   /*ret = spx_sqrt(67108864*(-1.6129e-04 + 2.0104e+00*f + 2.7373e-01*f*f + 1.8136e-01*f*f*f));*/
17753a5a1b3Sopenharmony_ci   if (s)
17853a5a1b3Sopenharmony_ci      ret = SUB16(25736,ret);
17953a5a1b3Sopenharmony_ci   return ret;
18053a5a1b3Sopenharmony_ci}
18153a5a1b3Sopenharmony_ci
18253a5a1b3Sopenharmony_ci
18353a5a1b3Sopenharmony_ci#define K1 8192
18453a5a1b3Sopenharmony_ci#define K2 -4096
18553a5a1b3Sopenharmony_ci#define K3 340
18653a5a1b3Sopenharmony_ci#define K4 -10
18753a5a1b3Sopenharmony_ci
18853a5a1b3Sopenharmony_cistatic inline spx_word16_t spx_cos(spx_word16_t x)
18953a5a1b3Sopenharmony_ci{
19053a5a1b3Sopenharmony_ci   spx_word16_t x2;
19153a5a1b3Sopenharmony_ci
19253a5a1b3Sopenharmony_ci   if (x<12868)
19353a5a1b3Sopenharmony_ci   {
19453a5a1b3Sopenharmony_ci      x2 = MULT16_16_P13(x,x);
19553a5a1b3Sopenharmony_ci      return ADD32(K1, MULT16_16_P13(x2, ADD32(K2, MULT16_16_P13(x2, ADD32(K3, MULT16_16_P13(K4, x2))))));
19653a5a1b3Sopenharmony_ci   } else {
19753a5a1b3Sopenharmony_ci      x = SUB16(25736,x);
19853a5a1b3Sopenharmony_ci      x2 = MULT16_16_P13(x,x);
19953a5a1b3Sopenharmony_ci      return SUB32(-K1, MULT16_16_P13(x2, ADD32(K2, MULT16_16_P13(x2, ADD32(K3, MULT16_16_P13(K4, x2))))));
20053a5a1b3Sopenharmony_ci   }
20153a5a1b3Sopenharmony_ci}
20253a5a1b3Sopenharmony_ci
20353a5a1b3Sopenharmony_ci#define L1 32767
20453a5a1b3Sopenharmony_ci#define L2 -7651
20553a5a1b3Sopenharmony_ci#define L3 8277
20653a5a1b3Sopenharmony_ci#define L4 -626
20753a5a1b3Sopenharmony_ci
20853a5a1b3Sopenharmony_cistatic inline spx_word16_t _spx_cos_pi_2(spx_word16_t x)
20953a5a1b3Sopenharmony_ci{
21053a5a1b3Sopenharmony_ci   spx_word16_t x2;
21153a5a1b3Sopenharmony_ci
21253a5a1b3Sopenharmony_ci   x2 = MULT16_16_P15(x,x);
21353a5a1b3Sopenharmony_ci   return ADD16(1,MIN16(32766,ADD32(SUB16(L1,x2), MULT16_16_P15(x2, ADD32(L2, MULT16_16_P15(x2, ADD32(L3, MULT16_16_P15(L4, x2))))))));
21453a5a1b3Sopenharmony_ci}
21553a5a1b3Sopenharmony_ci
21653a5a1b3Sopenharmony_cistatic inline spx_word16_t spx_cos_norm(spx_word32_t x)
21753a5a1b3Sopenharmony_ci{
21853a5a1b3Sopenharmony_ci   x = x&0x0001ffff;
21953a5a1b3Sopenharmony_ci   if (x>SHL32(EXTEND32(1), 16))
22053a5a1b3Sopenharmony_ci      x = SUB32(SHL32(EXTEND32(1), 17),x);
22153a5a1b3Sopenharmony_ci   if (x&0x00007fff)
22253a5a1b3Sopenharmony_ci   {
22353a5a1b3Sopenharmony_ci      if (x<SHL32(EXTEND32(1), 15))
22453a5a1b3Sopenharmony_ci      {
22553a5a1b3Sopenharmony_ci         return _spx_cos_pi_2(EXTRACT16(x));
22653a5a1b3Sopenharmony_ci      } else {
22753a5a1b3Sopenharmony_ci         return NEG32(_spx_cos_pi_2(EXTRACT16(65536-x)));
22853a5a1b3Sopenharmony_ci      }
22953a5a1b3Sopenharmony_ci   } else {
23053a5a1b3Sopenharmony_ci      if (x&0x0000ffff)
23153a5a1b3Sopenharmony_ci         return 0;
23253a5a1b3Sopenharmony_ci      else if (x&0x0001ffff)
23353a5a1b3Sopenharmony_ci         return -32767;
23453a5a1b3Sopenharmony_ci      else
23553a5a1b3Sopenharmony_ci         return 32767;
23653a5a1b3Sopenharmony_ci   }
23753a5a1b3Sopenharmony_ci}
23853a5a1b3Sopenharmony_ci
23953a5a1b3Sopenharmony_ci/*
24053a5a1b3Sopenharmony_ci K0 = 1
24153a5a1b3Sopenharmony_ci K1 = log(2)
24253a5a1b3Sopenharmony_ci K2 = 3-4*log(2)
24353a5a1b3Sopenharmony_ci K3 = 3*log(2) - 2
24453a5a1b3Sopenharmony_ci*/
24553a5a1b3Sopenharmony_ci#define D0 16384
24653a5a1b3Sopenharmony_ci#define D1 11356
24753a5a1b3Sopenharmony_ci#define D2 3726
24853a5a1b3Sopenharmony_ci#define D3 1301
24953a5a1b3Sopenharmony_ci/* Input in Q11 format, output in Q16 */
25053a5a1b3Sopenharmony_cistatic inline spx_word32_t spx_exp2(spx_word16_t x)
25153a5a1b3Sopenharmony_ci{
25253a5a1b3Sopenharmony_ci   int integer;
25353a5a1b3Sopenharmony_ci   spx_word16_t frac;
25453a5a1b3Sopenharmony_ci   integer = SHR16(x,11);
25553a5a1b3Sopenharmony_ci   if (integer>14)
25653a5a1b3Sopenharmony_ci      return 0x7fffffff;
25753a5a1b3Sopenharmony_ci   else if (integer < -15)
25853a5a1b3Sopenharmony_ci      return 0;
25953a5a1b3Sopenharmony_ci   frac = SHL16(x-SHL16(integer,11),3);
26053a5a1b3Sopenharmony_ci   frac = ADD16(D0, MULT16_16_Q14(frac, ADD16(D1, MULT16_16_Q14(frac, ADD16(D2 , MULT16_16_Q14(D3,frac))))));
26153a5a1b3Sopenharmony_ci   return VSHR32(EXTEND32(frac), -integer-2);
26253a5a1b3Sopenharmony_ci}
26353a5a1b3Sopenharmony_ci
26453a5a1b3Sopenharmony_ci/* Input in Q11 format, output in Q16 */
26553a5a1b3Sopenharmony_cistatic inline spx_word32_t spx_exp(spx_word16_t x)
26653a5a1b3Sopenharmony_ci{
26753a5a1b3Sopenharmony_ci   if (x>21290)
26853a5a1b3Sopenharmony_ci      return 0x7fffffff;
26953a5a1b3Sopenharmony_ci   else if (x<-21290)
27053a5a1b3Sopenharmony_ci      return 0;
27153a5a1b3Sopenharmony_ci   else
27253a5a1b3Sopenharmony_ci      return spx_exp2(MULT16_16_P14(23637,x));
27353a5a1b3Sopenharmony_ci}
27453a5a1b3Sopenharmony_ci#define M1 32767
27553a5a1b3Sopenharmony_ci#define M2 -21
27653a5a1b3Sopenharmony_ci#define M3 -11943
27753a5a1b3Sopenharmony_ci#define M4 4936
27853a5a1b3Sopenharmony_ci
27953a5a1b3Sopenharmony_cistatic inline spx_word16_t spx_atan01(spx_word16_t x)
28053a5a1b3Sopenharmony_ci{
28153a5a1b3Sopenharmony_ci   return MULT16_16_P15(x, ADD32(M1, MULT16_16_P15(x, ADD32(M2, MULT16_16_P15(x, ADD32(M3, MULT16_16_P15(M4, x)))))));
28253a5a1b3Sopenharmony_ci}
28353a5a1b3Sopenharmony_ci
28453a5a1b3Sopenharmony_ci#undef M1
28553a5a1b3Sopenharmony_ci#undef M2
28653a5a1b3Sopenharmony_ci#undef M3
28753a5a1b3Sopenharmony_ci#undef M4
28853a5a1b3Sopenharmony_ci
28953a5a1b3Sopenharmony_ci/* Input in Q15, output in Q14 */
29053a5a1b3Sopenharmony_cistatic inline spx_word16_t spx_atan(spx_word32_t x)
29153a5a1b3Sopenharmony_ci{
29253a5a1b3Sopenharmony_ci   if (x <= 32767)
29353a5a1b3Sopenharmony_ci   {
29453a5a1b3Sopenharmony_ci      return SHR16(spx_atan01(x),1);
29553a5a1b3Sopenharmony_ci   } else {
29653a5a1b3Sopenharmony_ci      int e = spx_ilog2(x);
29753a5a1b3Sopenharmony_ci      if (e>=29)
29853a5a1b3Sopenharmony_ci         return 25736;
29953a5a1b3Sopenharmony_ci      x = DIV32_16(SHL32(EXTEND32(32767),29-e), EXTRACT16(SHR32(x, e-14)));
30053a5a1b3Sopenharmony_ci      return SUB16(25736, SHR16(spx_atan01(x),1));
30153a5a1b3Sopenharmony_ci   }
30253a5a1b3Sopenharmony_ci}
30353a5a1b3Sopenharmony_ci#else
30453a5a1b3Sopenharmony_ci
30553a5a1b3Sopenharmony_ci#ifndef M_PI
30653a5a1b3Sopenharmony_ci#define M_PI           3.14159265358979323846  /* pi */
30753a5a1b3Sopenharmony_ci#endif
30853a5a1b3Sopenharmony_ci
30953a5a1b3Sopenharmony_ci#define C1 0.9999932946f
31053a5a1b3Sopenharmony_ci#define C2 -0.4999124376f
31153a5a1b3Sopenharmony_ci#define C3 0.0414877472f
31253a5a1b3Sopenharmony_ci#define C4 -0.0012712095f
31353a5a1b3Sopenharmony_ci
31453a5a1b3Sopenharmony_ci
31553a5a1b3Sopenharmony_ci#define SPX_PI_2 1.5707963268
31653a5a1b3Sopenharmony_cistatic inline spx_word16_t spx_cos(spx_word16_t x)
31753a5a1b3Sopenharmony_ci{
31853a5a1b3Sopenharmony_ci   if (x<SPX_PI_2)
31953a5a1b3Sopenharmony_ci   {
32053a5a1b3Sopenharmony_ci      x *= x;
32153a5a1b3Sopenharmony_ci      return C1 + x*(C2+x*(C3+C4*x));
32253a5a1b3Sopenharmony_ci   } else {
32353a5a1b3Sopenharmony_ci      x = M_PI-x;
32453a5a1b3Sopenharmony_ci      x *= x;
32553a5a1b3Sopenharmony_ci      return NEG16(C1 + x*(C2+x*(C3+C4*x)));
32653a5a1b3Sopenharmony_ci   }
32753a5a1b3Sopenharmony_ci}
32853a5a1b3Sopenharmony_ci
32953a5a1b3Sopenharmony_ci#endif
33053a5a1b3Sopenharmony_ci
33153a5a1b3Sopenharmony_ci
33253a5a1b3Sopenharmony_ci#endif
333