137fe158a8611dd11ec0253ab1552399b780988dcGloria Wang/************************************************************************ 22da723a953a18e3c7fec194cec1216cf31130c86Gloria Wang * Copyright (C) 2002-2009, Xiph.org Foundation 32da723a953a18e3c7fec194cec1216cf31130c86Gloria Wang * Copyright (C) 2010, Robin Watts for Pinknoise Productions Ltd 437fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * All rights reserved. 537fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * 637fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * Redistribution and use in source and binary forms, with or without 72da723a953a18e3c7fec194cec1216cf31130c86Gloria Wang * modification, are permitted provided that the following conditions 82da723a953a18e3c7fec194cec1216cf31130c86Gloria Wang * are met: 937fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * 1037fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * * Redistributions of source code must retain the above copyright 1137fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * notice, this list of conditions and the following disclaimer. 1237fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * * Redistributions in binary form must reproduce the above 1337fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * copyright notice, this list of conditions and the following disclaimer 1437fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * in the documentation and/or other materials provided with the 1537fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * distribution. 162da723a953a18e3c7fec194cec1216cf31130c86Gloria Wang * * Neither the names of the Xiph.org Foundation nor Pinknoise 172da723a953a18e3c7fec194cec1216cf31130c86Gloria Wang * Productions Ltd nor the names of its contributors may be used to 182da723a953a18e3c7fec194cec1216cf31130c86Gloria Wang * endorse or promote products derived from this software without 192da723a953a18e3c7fec194cec1216cf31130c86Gloria Wang * specific prior written permission. 2037fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * 2137fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2237fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2337fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2437fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2537fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2637fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2737fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2837fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2937fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3037fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3137fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3237fe158a8611dd11ec0253ab1552399b780988dcGloria Wang ************************************************************************ 337913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 347913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang function: miscellaneous math and prototypes 357913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 3637fe158a8611dd11ec0253ab1552399b780988dcGloria Wang ************************************************************************/ 377913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 387913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#ifndef _V_RANDOM_H_ 397913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#define _V_RANDOM_H_ 407913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#include "ivorbiscodec.h" 417913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#include "os_types.h" 427913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 437913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang/*#define _VDBG_GRAPHFILE "_0.m"*/ 447913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 457913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 467913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#ifdef _VDBG_GRAPHFILE 477913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangextern void *_VDBG_malloc(void *ptr,long bytes,char *file,long line); 487913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangextern void _VDBG_free(void *ptr,char *file,long line); 497913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 507913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#undef _ogg_malloc 517913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#undef _ogg_calloc 527913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#undef _ogg_realloc 537913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#undef _ogg_free 547913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 557913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#define _ogg_malloc(x) _VDBG_malloc(NULL,(x),__FILE__,__LINE__) 567913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#define _ogg_calloc(x,y) _VDBG_malloc(NULL,(x)*(y),__FILE__,__LINE__) 577913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#define _ogg_realloc(x,y) _VDBG_malloc((x),(y),__FILE__,__LINE__) 587913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#define _ogg_free(x) _VDBG_free((x),__FILE__,__LINE__) 597913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#endif 607913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 617913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#include "asm_arm.h" 627913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 637913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#ifndef _V_WIDE_MATH 647913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#define _V_WIDE_MATH 657913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 667913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#ifndef _LOW_ACCURACY_ 677913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang/* 64 bit multiply */ 687913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 6997a3b7c33088e22bbf6cd494c5a014081a4a6d87Chih-Wei Huang#include <endian.h> 707913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#include <sys/types.h> 717913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 727913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#if BYTE_ORDER==LITTLE_ENDIAN 737913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangunion magic { 747913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang struct { 757913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_int32_t lo; 767913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_int32_t hi; 777913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } halves; 787913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_int64_t whole; 797913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang}; 807913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#endif 817913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 827913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#if BYTE_ORDER==BIG_ENDIAN 837913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangunion magic { 847913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang struct { 857913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_int32_t hi; 867913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_int32_t lo; 877913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } halves; 887913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_int64_t whole; 897913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang}; 907913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#endif 917913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 927913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangstatic inline ogg_int32_t MULT32(ogg_int32_t x, ogg_int32_t y) { 937913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang union magic magic; 947913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang magic.whole = (ogg_int64_t)x * y; 957913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return magic.halves.hi; 967913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 977913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 987913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangstatic inline ogg_int32_t MULT31(ogg_int32_t x, ogg_int32_t y) { 997913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return MULT32(x,y)<<1; 1007913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 1017913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1027913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangstatic inline ogg_int32_t MULT31_SHIFT15(ogg_int32_t x, ogg_int32_t y) { 1037913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang union magic magic; 1047913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang magic.whole = (ogg_int64_t)x * y; 1057913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return ((ogg_uint32_t)(magic.halves.lo)>>15) | ((magic.halves.hi)<<17); 1067913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 1077913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1087913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#else 1097913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang/* 32 bit multiply, more portable but less accurate */ 1107913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1117913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang/* 1127913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang * Note: Precision is biased towards the first argument therefore ordering 1137913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang * is important. Shift values were chosen for the best sound quality after 1147913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang * many listening tests. 1157913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang */ 1167913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1177913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang/* 1187913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang * For MULT32 and MULT31: The second argument is always a lookup table 1197913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang * value already preshifted from 31 to 8 bits. We therefore take the 1207913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang * opportunity to save on text space and use unsigned char for those 1217913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang * tables in this case. 1227913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang */ 1237913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1247913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangstatic inline ogg_int32_t MULT32(ogg_int32_t x, ogg_int32_t y) { 1257913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return (x >> 9) * y; /* y preshifted >>23 */ 1267913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 1277913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1287913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangstatic inline ogg_int32_t MULT31(ogg_int32_t x, ogg_int32_t y) { 1297913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return (x >> 8) * y; /* y preshifted >>23 */ 1307913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 1317913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1327913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangstatic inline ogg_int32_t MULT31_SHIFT15(ogg_int32_t x, ogg_int32_t y) { 1337913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return (x >> 6) * y; /* y preshifted >>9 */ 1347913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 1357913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1367913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#endif 1377913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1387913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang/* 1397913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang * This should be used as a memory barrier, forcing all cached values in 1407913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang * registers to wr writen back to memory. Might or might not be beneficial 1417913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang * depending on the architecture and compiler. 1427913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang */ 1437913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#define MB() 1447913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1457913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang/* 1467913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang * The XPROD functions are meant to optimize the cross products found all 1477913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang * over the place in mdct.c by forcing memory operation ordering to avoid 1487913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang * unnecessary register reloads as soon as memory is being written to. 1497913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang * However this is only beneficial on CPUs with a sane number of general 1507913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang * purpose registers which exclude the Intel x86. On Intel, better let the 1517913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang * compiler actually reload registers directly from original memory by using 1527913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang * macros. 1537913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang */ 1547913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1557913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#ifdef __i386__ 1567913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1577913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#define XPROD32(_a, _b, _t, _v, _x, _y) \ 1587913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang { *(_x)=MULT32(_a,_t)+MULT32(_b,_v); \ 1597913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang *(_y)=MULT32(_b,_t)-MULT32(_a,_v); } 1607913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#define XPROD31(_a, _b, _t, _v, _x, _y) \ 1617913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang { *(_x)=MULT31(_a,_t)+MULT31(_b,_v); \ 1627913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang *(_y)=MULT31(_b,_t)-MULT31(_a,_v); } 1637913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#define XNPROD31(_a, _b, _t, _v, _x, _y) \ 1647913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang { *(_x)=MULT31(_a,_t)-MULT31(_b,_v); \ 1657913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang *(_y)=MULT31(_b,_t)+MULT31(_a,_v); } 1667913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1677913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#else 1687913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1697913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangstatic inline void XPROD32(ogg_int32_t a, ogg_int32_t b, 1707913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_int32_t t, ogg_int32_t v, 1717913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_int32_t *x, ogg_int32_t *y) 1727913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang{ 1737913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang *x = MULT32(a, t) + MULT32(b, v); 1747913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang *y = MULT32(b, t) - MULT32(a, v); 1757913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 1767913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1777913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangstatic inline void XPROD31(ogg_int32_t a, ogg_int32_t b, 1787913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_int32_t t, ogg_int32_t v, 1797913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_int32_t *x, ogg_int32_t *y) 1807913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang{ 1817913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang *x = MULT31(a, t) + MULT31(b, v); 1827913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang *y = MULT31(b, t) - MULT31(a, v); 1837913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 1847913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1857913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangstatic inline void XNPROD31(ogg_int32_t a, ogg_int32_t b, 1867913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_int32_t t, ogg_int32_t v, 1877913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_int32_t *x, ogg_int32_t *y) 1887913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang{ 1897913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang *x = MULT31(a, t) - MULT31(b, v); 1907913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang *y = MULT31(b, t) + MULT31(a, v); 1917913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 1927913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1937913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#endif 1947913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1957913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#endif 1967913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1977913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#ifndef _V_CLIP_MATH 1987913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#define _V_CLIP_MATH 1997913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 2007913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangstatic inline ogg_int32_t CLIP_TO_15(ogg_int32_t x) { 2017913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang int ret=x; 2027913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ret-= ((x<=32767)-1)&(x-32767); 2037913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ret-= ((x>=-32768)-1)&(x+32768); 2047913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return(ret); 2057913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 2067913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 2077913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#endif 2087913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 2097913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#endif 2107913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 2117913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 2127913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 2137913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 214