14d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com/*
24d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
34d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com *
44d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com *  Use of this source code is governed by a BSD-style license
54d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com *  that can be found in the LICENSE file in the root of the source
64d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com *  tree. An additional intellectual property rights grant can be found
74d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com *  in the file PATENTS.  All contributing project authors may
84d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com *  be found in the AUTHORS file in the root of the source tree.
94d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com */
104d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com
114d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com#include "dl/api/omxtypes.h"
124d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com#include "dl/sp/api/armSP.h"
134d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com#include "dl/sp/api/omxSP.h"
144d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com
154d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.comextern void armSP_FFTFwd_CToC_FC32_Radix2_fs_OutOfPlace(
164d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com    const OMX_FC32* pSrc,
174d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com    OMX_FC32* pDst,
184d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com    OMX_FC32* pTwiddle,
194d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com    long* subFFTNum,
204d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com    long* subFFTSize);
214d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com
224d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.comextern void armSP_FFTFwd_CToC_FC32_Radix2_ls_OutOfPlace(
234d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com    const OMX_FC32* pSrc,
244d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com    OMX_FC32* pDst,
254d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com    OMX_FC32* pTwiddle,
264d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com    long* subFFTNum,
274d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com    long* subFFTSize);
284d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com
294d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.comextern void armSP_FFTFwd_CToC_FC32_Radix2_OutOfPlace(
304d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com    const OMX_FC32* pSrc,
314d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com    OMX_FC32* pDst,
324d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com    OMX_FC32* pTwiddle,
334d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com    long* subFFTNum,
344d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com    long* subFFTSize);
354d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com
364d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.comextern void armSP_FFTFwd_CToC_FC32_Radix4_fs_OutOfPlace(
374d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com    const OMX_FC32* pSrc,
384d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com    OMX_FC32* pDst,
394d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com    OMX_FC32* pTwiddle,
404d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com    long* subFFTNum,
414d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com    long* subFFTSize);
424d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com
434d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.comextern void armSP_FFTFwd_CToC_FC32_Radix4_OutOfPlace(
444d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com    const OMX_FC32* pSrc,
454d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com    OMX_FC32* pDst,
464d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com    OMX_FC32* pTwiddle,
474d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com    long* subFFTNum,
484d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com    long* subFFTSize);
494d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com
504d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.comextern void armSP_FFTFwd_CToC_FC32_Radix4_ls_OutOfPlace(
514d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com    const OMX_FC32* pSrc,
524d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com    OMX_FC32* pDst,
534d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com    OMX_FC32* pTwiddle,
544d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com    long* subFFTNum,
554d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com    long* subFFTSize);
564d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com
574d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.comextern void armSP_FFTFwd_CToC_FC32_Radix8_fs_OutOfPlace(
584d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com    const OMX_FC32* pSrc,
594d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com    OMX_FC32* pDst,
604d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com    OMX_FC32* pTwiddle,
614d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com    long* subFFTNum,
624d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com    long* subFFTSize);
634d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com
644d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com/**
654d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com * Function:  omxSP_FFTFwd_CToC_FC32_Sfs   (2.2.4.2.2)
664d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com *
674d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com * Description:
684d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com * Compute an FFT for a complex signal of length of 2^order,
694d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com * where 0 <= order <= 15.
704d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com * Transform length is determined by the specification structure, which
714d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com * must be initialized prior to calling the FFT function using the appropriate
724d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com * helper, i.e., <FFTInit_C_sc32> or <FFTInit_C_SC16>. The relationship
734d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com * between the input and output sequences can be expressed in terms of the
744d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com * DFT, i.e.,
754d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com *
764d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com *      X[k] = SUM[n=0...N-1]x[n].e^(-jnk.2.pi/N)
774d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com *      k = 0,1,2,..., N-1
784d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com *      N = 2^order
794d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com *
804d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com * Input Arguments:
814d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com *   pSrc - pointer to the input signal, a complex-valued vector of length
824d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com *            2^order; must be aligned on a 32 byte boundary.
834d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com *   pFFTSpec - pointer to the preallocated and initialized specification
844d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com *            structure
854d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com *
864d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com * Output Arguments:
874d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com *   pDst - pointer to the complex-valued output vector, of length 2^order;
884d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com *            must be aligned on an 32-byte boundary.
894d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com *
904d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com * Return Value:
914d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com *
924d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com *    OMX_Sts_NoErr - no error
934d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com *    OMX_Sts_BadArgErr - returned if one or more of the following conditions
944d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com *              is true:
954d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com *    -   one or more of the following pointers is NULL: pSrc, pDst, or
964d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com *              pFFTSpec.
974d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com *    -    pSrc or pDst is not 32-byte aligned
984d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com *
994d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com */
1004d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com
1014d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.comOMXResult omxSP_FFTFwd_CToC_FC32_Sfs(const OMX_FC32* pSrc,
1024d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com                                     OMX_FC32* pDst,
1034d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com                                     const OMXFFTSpec_C_FC32* pFFTSpec) {
1044d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com  ARMsFFTSpec_FC32* spec = (ARMsFFTSpec_FC32*)pFFTSpec;
1054d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com  int order;
1064d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com  long subFFTSize;
1074d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com  long subFFTNum;
1084d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com  OMX_FC32* pTwiddle;
1094d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com  OMX_FC32* pOut;
1104d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com
1114d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com  /*
1124d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com   * Check args are not NULL and the source and destination pointers
1134d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com   * are properly aligned.
1144d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com   */
1154d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com  if (!validateParametersFC32(pSrc, pDst, spec))
1164d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com    return OMX_Sts_BadArgErr;
1174d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com
1184d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com  order = fastlog2(spec->N);
1194d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com
1204d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com  subFFTSize = 1;
1214d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com  subFFTNum = spec->N;
1224d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com  pTwiddle = spec->pTwiddle;
1234d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com  pOut = spec->pBuf;
1244d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com
1254d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com  if (order > 3) {
1264d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com    OMX_FC32* argDst;
1274d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com
1284d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com    /*
1294d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com     * Set up argDst and pOut appropriately so that pOut = pDst for
1304d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com     * the very last FFT stage.
1314d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com     */
1324d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com    if ((order & 2) == 0) {
1334d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com      argDst = pOut;
1344d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com      pOut = pDst;
1354d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com    } else {
1364d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com      argDst = pDst;
1374d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com    }
1384d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com
1394d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com    /*
1404d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com     * Odd order uses a radix 8 first stage; even order, a radix 4
1414d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com     * first stage.
1424d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com     */
1434d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com    if (order & 1) {
1444d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com      armSP_FFTFwd_CToC_FC32_Radix8_fs_OutOfPlace(
1454d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com          pSrc, argDst, pTwiddle, &subFFTNum, &subFFTSize);
1464d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com    } else {
1474d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com      armSP_FFTFwd_CToC_FC32_Radix4_fs_OutOfPlace(
1484d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com          pSrc, argDst, pTwiddle, &subFFTNum, &subFFTSize);
1494d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com    }
1504d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com
1514d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com    /*
1524d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com     * Now use radix 4 stages to finish rest of the FFT
1534d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com     */
1544d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com    if (subFFTNum >= 4) {
1554d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com      while (subFFTNum > 4) {
1564d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com        OMX_FC32* tmp;
1574d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com
1584d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com        armSP_FFTFwd_CToC_FC32_Radix4_OutOfPlace(
1594d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com            argDst, pOut, pTwiddle, &subFFTNum, &subFFTSize);
1604d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com        /*
1614d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com         * Swap argDst and pOut
1624d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com         */
1634d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com        tmp = pOut;
1644d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com        pOut = argDst;
1654d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com        argDst = tmp;
1664d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com      }
1674d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com
1684d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com      armSP_FFTFwd_CToC_FC32_Radix4_ls_OutOfPlace(
1694d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com          argDst, pOut, pTwiddle, &subFFTNum, &subFFTSize);
1704d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com    }
1714d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com  } else if (order == 3) {
1724d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com    armSP_FFTFwd_CToC_FC32_Radix2_fs_OutOfPlace(
1734d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com        pSrc, pDst, pTwiddle, &subFFTNum, &subFFTSize);
1744d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com    armSP_FFTFwd_CToC_FC32_Radix2_OutOfPlace(
1754d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com        pDst, pOut, pTwiddle, &subFFTNum, &subFFTSize);
1764d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com    armSP_FFTFwd_CToC_FC32_Radix2_ls_OutOfPlace(
1774d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com        pOut, pDst, pTwiddle, &subFFTNum, &subFFTSize);
1784d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com  } else if (order == 2) {
1794d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com    armSP_FFTFwd_CToC_FC32_Radix2_fs_OutOfPlace(
1804d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com        pSrc, pOut, pTwiddle, &subFFTNum, &subFFTSize);
1814d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com    armSP_FFTFwd_CToC_FC32_Radix2_ls_OutOfPlace(
1824d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com        pOut, pDst, pTwiddle, &subFFTNum, &subFFTSize);
1834d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com  } else {
1844d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com    /* Order = 1 */
1854d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com    armSP_FFTFwd_CToC_FC32_Radix2_fs_OutOfPlace(
1864d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com        pSrc, pDst, pTwiddle, &subFFTNum, &subFFTSize);
1874d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com  }
1884d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com
1894d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com  return OMX_Sts_NoErr;
1904d09f5abfba45163d1296272ac7d2ddc2cd5f9fbrtoy@google.com}
191