<commit_before>/*
 * Copyright (c) 2016-2018 ARM Limited
 * All rights reserved
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder. You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * Copyright (c) 2004-2005 The Regents of The University of Michigan
 * Copyright (c) 2013 Advanced Micro Devices, Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef __CPU_O3_REGFILE_HH__
#define __CPU_O3_REGFILE_HH__

#include <cstring>
#include <vector>

#include "arch/generic/isa.hh"
#include "arch/vecregs.hh"
#include "base/trace.hh"
#include "config/the_isa.hh"
#include "cpu/o3/comm.hh"
#include "cpu/regfile.hh"
#include "debug/IEW.hh"

namespace gem5
{

namespace o3
{

class UnifiedFreeList;

/**
 * Simple physical register file class.
 */
class PhysRegFile
{
  private:

    using PhysIds = std::vector<PhysRegId>;
  public:
    using IdRange = std::pair<PhysIds::iterator,
                              PhysIds::iterator>;
  private:
    /** Integer register file. */
    RegFile intRegFile;
    std::vector<PhysRegId> intRegIds;
    RegId zeroReg;

    /** Floating point register file. */
    RegFile floatRegFile;
    std::vector<PhysRegId> floatRegIds;

    /** Vector register file. */
    RegFile vectorRegFile;
    std::vector<PhysRegId> vecRegIds;

    /** Vector element register file. */
    RegFile vectorElemRegFile;
    std::vector<PhysRegId> vecElemIds;

    /** Predicate register file. */
    RegFile vecPredRegFile;
    std::vector<PhysRegId> vecPredRegIds;

    /** Condition-code register file. */
    RegFile ccRegFile;
    std::vector<PhysRegId> ccRegIds;

    /** Misc Reg Ids */
    std::vector<PhysRegId> miscRegIds;

    /**
     * Number of physical general purpose registers
     */
    unsigned numPhysicalIntRegs;

    /**
     * Number of physical floating point registers
     */
    unsigned numPhysicalFloatRegs;

    /**
     * Number of physical vector registers
     */
    unsigned numPhysicalVecRegs;

    /**
     * Number of physical vector element registers
     */
    unsigned numPhysicalVecElemRegs;

    /**
     * Number of physical predicate registers
     */
    unsigned numPhysicalVecPredRegs;

    /**
     * Number of physical CC registers
     */
    unsigned numPhysicalCCRegs;

    /** Total number of physical registers. */
    unsigned totalNumRegs;

  public:
    /**
     * Constructs a physical register file with the specified amount of
     * integer and floating point registers.
     */
    PhysRegFile(unsigned _numPhysicalIntRegs,
                unsigned _numPhysicalFloatRegs,
                unsigned _numPhysicalVecRegs,
                unsigned _numPhysicalVecPredRegs,
                unsigned _numPhysicalCCRegs,
                const BaseISA::RegClasses &classes);

    /**
     * Destructor to free resources
     */
    ~PhysRegFile() {}

    /** Initialize the free list */
    void initFreeList(UnifiedFreeList *freeList);

    /** @return the total number of physical registers. */
    unsigned totalNumPhysRegs() const { return totalNumRegs; }

    /** Gets a misc register PhysRegIdPtr. */
    PhysRegIdPtr getMiscRegId(RegIndex reg_idx) {
        return &miscRegIds[reg_idx];
    }

    RegVal
    getReg(PhysRegIdPtr phys_reg) const
    {
        const RegClassType type = phys_reg->classValue();
        const RegIndex idx = phys_reg->index();

        RegVal val;
        switch (type) {
          case IntRegClass:
            val = intRegFile.reg(idx);
            DPRINTF(IEW, "RegFile: Access to int register %i, has data %#x\n",
                    idx, val);
            return val;
          case FloatRegClass:
            val = floatRegFile.reg(idx);
            DPRINTF(IEW, "RegFile: Access to float register %i has data %#x\n",
                    idx, val);
            return val;
          case VecElemClass:
            val = vectorElemRegFile.reg(idx);
            DPRINTF(IEW, "RegFile: Access to vector element register %i "
                    "has data %#x\n", idx, val);
            return val;
          case CCRegClass:
            val = ccRegFile.reg(idx);
            DPRINTF(IEW, "RegFile: Access to cc register %i has data %#x\n",
                    idx, val);
            return val;
          default:
            panic("Unsupported register class type %d.", type);
        }
    }

    void
    getReg(PhysRegIdPtr phys_reg, void *val) const
    {
        const RegClassType type = phys_reg->classValue();
        const RegIndex idx = phys_reg->index();

        switch (type) {
          case IntRegClass:
            *(RegVal *)val = getReg(phys_reg);
            break;
          case FloatRegClass:
            *(RegVal *)val = getReg(phys_reg);
            break;
          case VecRegClass:
            vectorRegFile.get(idx, val);
            DPRINTF(IEW, "RegFile: Access to vector register %i, has "
                    "data %s\n", idx, *(TheISA::VecRegContainer *)val);
            break;
          case VecElemClass:
            *(RegVal *)val = getReg(phys_reg);
            break;
          case VecPredRegClass:
            vecPredRegFile.get(idx, val);
            DPRINTF(IEW, "RegFile: Access to predicate register %i, has "
                    "data %s\n", idx, *(TheISA::VecRegContainer *)val);
            break;
          case CCRegClass:
            *(RegVal *)val = getReg(phys_reg);
            break;
          default:
            panic("Unrecognized register class type %d.", type);
        }
    }

    void *
    getWritableReg(PhysRegIdPtr phys_reg)
    {
        const RegClassType type = phys_reg->classValue();
        const RegIndex idx = phys_reg->index();

        switch (type) {
          case VecRegClass:
            return vectorRegFile.ptr(idx);
          case VecPredRegClass:
            return vecPredRegFile.ptr(idx);
          default:
            panic("Unrecognized register class type %d.", type);
        }
    }

    void
    setReg(PhysRegIdPtr phys_reg, RegVal val)
    {
        const RegClassType type = phys_reg->classValue();
        const RegIndex idx = phys_reg->index();

        switch (type) {
          case IntRegClass:
            if (phys_reg->index() != zeroReg.index())
                intRegFile.reg(idx) = val;
            DPRINTF(IEW, "RegFile: Setting int register %i to %#x\n",
                    idx, val);
            break;
          case FloatRegClass:
            floatRegFile.reg(idx) = val;
            DPRINTF(IEW, "RegFile: Setting float register %i to %#x\n",
                    idx, val);
            break;
          case VecElemClass:
            vectorElemRegFile.reg(idx) = val;
            DPRINTF(IEW, "RegFile: Setting vector element register %i to "
                    "%#x\n", idx, val);
            break;
          case CCRegClass:
            ccRegFile.reg(idx) = val;
            DPRINTF(IEW, "RegFile: Setting cc register %i to %#x\n",
                    idx, val);
            break;
          default:
            panic("Unsupported register class type %d.", type);
        }
    }

    void
    setReg(PhysRegIdPtr phys_reg, const void *val)
    {
        const RegClassType type = phys_reg->classValue();
        const RegIndex idx = phys_reg->index();

        switch (type) {
          case IntRegClass:
            setReg(phys_reg, *(RegVal *)val);
            break;
          case FloatRegClass:
            setReg(phys_reg, *(RegVal *)val);
            break;
          case VecRegClass:
            DPRINTF(IEW, "RegFile: Setting vector register %i to %s\n",
                    idx, *(TheISA::VecRegContainer *)val);
            vectorRegFile.set(idx, val);
            break;
          case VecElemClass:
            setReg(phys_reg, *(RegVal *)val);
            break;
          case VecPredRegClass:
            DPRINTF(IEW, "RegFile: Setting predicate register %i to %s\n",
                    idx, *(TheISA::VecRegContainer *)val);
            vecPredRegFile.set(idx, val);
            break;
          case CCRegClass:
            setReg(phys_reg, *(RegVal *)val);
            break;
          default:
            panic("Unrecognized register class type %d.", type);
        }
    }

    /**
     * Get the PhysRegIds of the elems of all vector registers.
     * Auxiliary function to transition from Full vector mode to Elem mode
     * and to initialise the rename map.
     */
    IdRange getRegIds(RegClassType cls);

    /**
     * Get the true physical register id.
     * As many parts work with PhysRegIdPtr, we need to be able to produce
     * the pointer out of just class and register idx.
     */
    PhysRegIdPtr getTrueId(PhysRegIdPtr reg);
};

} // namespace o3
} // namespace gem5

#endif //__CPU_O3_REGFILE_HH__
<commit_msg>cpu-o3: Print vec and vec pred reg values with valString.<commit_after>/*
 * Copyright (c) 2016-2018 ARM Limited
 * All rights reserved
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder. You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * Copyright (c) 2004-2005 The Regents of The University of Michigan
 * Copyright (c) 2013 Advanced Micro Devices, Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef __CPU_O3_REGFILE_HH__
#define __CPU_O3_REGFILE_HH__

#include <cstring>
#include <vector>

#include "arch/generic/isa.hh"
#include "arch/vecregs.hh"
#include "base/trace.hh"
#include "config/the_isa.hh"
#include "cpu/o3/comm.hh"
#include "cpu/regfile.hh"
#include "debug/IEW.hh"

namespace gem5
{

namespace o3
{

class UnifiedFreeList;

/**
 * Simple physical register file class.
 */
class PhysRegFile
{
  private:

    using PhysIds = std::vector<PhysRegId>;
  public:
    using IdRange = std::pair<PhysIds::iterator,
                              PhysIds::iterator>;
  private:
    /** Integer register file. */
    RegFile intRegFile;
    std::vector<PhysRegId> intRegIds;
    RegId zeroReg;

    /** Floating point register file. */
    RegFile floatRegFile;
    std::vector<PhysRegId> floatRegIds;

    /** Vector register file. */
    RegFile vectorRegFile;
    std::vector<PhysRegId> vecRegIds;

    /** Vector element register file. */
    RegFile vectorElemRegFile;
    std::vector<PhysRegId> vecElemIds;

    /** Predicate register file. */
    RegFile vecPredRegFile;
    std::vector<PhysRegId> vecPredRegIds;

    /** Condition-code register file. */
    RegFile ccRegFile;
    std::vector<PhysRegId> ccRegIds;

    /** Misc Reg Ids */
    std::vector<PhysRegId> miscRegIds;

    /**
     * Number of physical general purpose registers
     */
    unsigned numPhysicalIntRegs;

    /**
     * Number of physical floating point registers
     */
    unsigned numPhysicalFloatRegs;

    /**
     * Number of physical vector registers
     */
    unsigned numPhysicalVecRegs;

    /**
     * Number of physical vector element registers
     */
    unsigned numPhysicalVecElemRegs;

    /**
     * Number of physical predicate registers
     */
    unsigned numPhysicalVecPredRegs;

    /**
     * Number of physical CC registers
     */
    unsigned numPhysicalCCRegs;

    /** Total number of physical registers. */
    unsigned totalNumRegs;

  public:
    /**
     * Constructs a physical register file with the specified amount of
     * integer and floating point registers.
     */
    PhysRegFile(unsigned _numPhysicalIntRegs,
                unsigned _numPhysicalFloatRegs,
                unsigned _numPhysicalVecRegs,
                unsigned _numPhysicalVecPredRegs,
                unsigned _numPhysicalCCRegs,
                const BaseISA::RegClasses &classes);

    /**
     * Destructor to free resources
     */
    ~PhysRegFile() {}

    /** Initialize the free list */
    void initFreeList(UnifiedFreeList *freeList);

    /** @return the total number of physical registers. */
    unsigned totalNumPhysRegs() const { return totalNumRegs; }

    /** Gets a misc register PhysRegIdPtr. */
    PhysRegIdPtr getMiscRegId(RegIndex reg_idx) {
        return &miscRegIds[reg_idx];
    }

    RegVal
    getReg(PhysRegIdPtr phys_reg) const
    {
        const RegClassType type = phys_reg->classValue();
        const RegIndex idx = phys_reg->index();

        RegVal val;
        switch (type) {
          case IntRegClass:
            val = intRegFile.reg(idx);
            DPRINTF(IEW, "RegFile: Access to int register %i, has data %#x\n",
                    idx, val);
            return val;
          case FloatRegClass:
            val = floatRegFile.reg(idx);
            DPRINTF(IEW, "RegFile: Access to float register %i has data %#x\n",
                    idx, val);
            return val;
          case VecElemClass:
            val = vectorElemRegFile.reg(idx);
            DPRINTF(IEW, "RegFile: Access to vector element register %i "
                    "has data %#x\n", idx, val);
            return val;
          case CCRegClass:
            val = ccRegFile.reg(idx);
            DPRINTF(IEW, "RegFile: Access to cc register %i has data %#x\n",
                    idx, val);
            return val;
          default:
            panic("Unsupported register class type %d.", type);
        }
    }

    void
    getReg(PhysRegIdPtr phys_reg, void *val) const
    {
        const RegClassType type = phys_reg->classValue();
        const RegIndex idx = phys_reg->index();

        switch (type) {
          case IntRegClass:
            *(RegVal *)val = getReg(phys_reg);
            break;
          case FloatRegClass:
            *(RegVal *)val = getReg(phys_reg);
            break;
          case VecRegClass:
            vectorRegFile.get(idx, val);
            DPRINTF(IEW, "RegFile: Access to vector register %i, has "
                    "data %s\n", idx, vectorRegFile.regClass.valString(val));
            break;
          case VecElemClass:
            *(RegVal *)val = getReg(phys_reg);
            break;
          case VecPredRegClass:
            vecPredRegFile.get(idx, val);
            DPRINTF(IEW, "RegFile: Access to predicate register %i, has "
                    "data %s\n", idx, vecPredRegFile.regClass.valString(val));
            break;
          case CCRegClass:
            *(RegVal *)val = getReg(phys_reg);
            break;
          default:
            panic("Unrecognized register class type %d.", type);
        }
    }

    void *
    getWritableReg(PhysRegIdPtr phys_reg)
    {
        const RegClassType type = phys_reg->classValue();
        const RegIndex idx = phys_reg->index();

        switch (type) {
          case VecRegClass:
            return vectorRegFile.ptr(idx);
          case VecPredRegClass:
            return vecPredRegFile.ptr(idx);
          default:
            panic("Unrecognized register class type %d.", type);
        }
    }

    void
    setReg(PhysRegIdPtr phys_reg, RegVal val)
    {
        const RegClassType type = phys_reg->classValue();
        const RegIndex idx = phys_reg->index();

        switch (type) {
          case IntRegClass:
            if (phys_reg->index() != zeroReg.index())
                intRegFile.reg(idx) = val;
            DPRINTF(IEW, "RegFile: Setting int register %i to %#x\n",
                    idx, val);
            break;
          case FloatRegClass:
            floatRegFile.reg(idx) = val;
            DPRINTF(IEW, "RegFile: Setting float register %i to %#x\n",
                    idx, val);
            break;
          case VecElemClass:
            vectorElemRegFile.reg(idx) = val;
            DPRINTF(IEW, "RegFile: Setting vector element register %i to "
                    "%#x\n", idx, val);
            break;
          case CCRegClass:
            ccRegFile.reg(idx) = val;
            DPRINTF(IEW, "RegFile: Setting cc register %i to %#x\n",
                    idx, val);
            break;
          default:
            panic("Unsupported register class type %d.", type);
        }
    }

    void
    setReg(PhysRegIdPtr phys_reg, const void *val)
    {
        const RegClassType type = phys_reg->classValue();
        const RegIndex idx = phys_reg->index();

        switch (type) {
          case IntRegClass:
            setReg(phys_reg, *(RegVal *)val);
            break;
          case FloatRegClass:
            setReg(phys_reg, *(RegVal *)val);
            break;
          case VecRegClass:
            DPRINTF(IEW, "RegFile: Setting vector register %i to %s\n",
                    idx, vectorRegFile.regClass.valString(val));
            vectorRegFile.set(idx, val);
            break;
          case VecElemClass:
            setReg(phys_reg, *(RegVal *)val);
            break;
          case VecPredRegClass:
            DPRINTF(IEW, "RegFile: Setting predicate register %i to %s\n",
                    idx, vectorRegFile.regClass.valString(val));
            vecPredRegFile.set(idx, val);
            break;
          case CCRegClass:
            setReg(phys_reg, *(RegVal *)val);
            break;
          default:
            panic("Unrecognized register class type %d.", type);
        }
    }

    /**
     * Get the PhysRegIds of the elems of all vector registers.
     * Auxiliary function to transition from Full vector mode to Elem mode
     * and to initialise the rename map.
     */
    IdRange getRegIds(RegClassType cls);

    /**
     * Get the true physical register id.
     * As many parts work with PhysRegIdPtr, we need to be able to produce
     * the pointer out of just class and register idx.
     */
    PhysRegIdPtr getTrueId(PhysRegIdPtr reg);
};

} // namespace o3
} // namespace gem5

#endif //__CPU_O3_REGFILE_HH__
<|endoftext|>


<commit_before>#include "blockstream.h"

#define MASK_5BIT  0x000001F
#define MASK_10BIT 0x00003FF
#define MASK_16BIT 0x000FFFF
#define MASK_26BIT 0x3FFFFFF
#define MASK_28BIT 0xFFFFFFF

#define MAX_ERR_LEN 3

namespace redsea {

namespace {

uint32_t rol10(uint32_t word, int k) {
  uint32_t result = word;
  uint32_t l;
  for (int i=0; i<k; i++) {
    l       = (result & 0x200);
    result  = (result << 1) & 0x3FF;
    result ^= l;
  }
  return result;
}

uint32_t calcSyndrome(uint32_t vec) {

  uint32_t synd_reg = 0x000;
  uint32_t bit,l;

  for (int k=25; k>=0; k--) {
    bit       = (vec & (1 << k));
    l         = (synd_reg & 0x200);      // Store lefmost bit of register
    synd_reg  = (synd_reg << 1) & 0x3FF; // Rotate register
    synd_reg ^= (bit ? 0x31B : 0x00);    // Premultiply input by x^325 mod g(x)
    synd_reg ^= (l   ? 0x1B9 : 0x00);    // Division mod 2 by g(x)
  }

  return synd_reg;
}

uint32_t calcCheckBits(uint32_t dataWord) {
  uint32_t generator = 0x1B9;
  uint32_t result    = 0;

  for (int k=0; k<16; k++) {
    if ((dataWord >> k) & 0x01) {
      result ^= rol10(generator, k);
    }
  }
  return result;
}

}

BlockStream::BlockStream() : has_sync_for_(5), group_data_(4), has_block_(5),
  bitcount_(0), left_to_read_(0), bit_stream_(), wideblock_(0), block_has_errors_(50)

{

  offset_word_ = {0x0FC, 0x198, 0x168, 0x350, 0x1B4};

  block_for_offset_ = {0, 1, 2, 2, 3};

  for (uint32_t e=1; e < (1<<MAX_ERR_LEN); e++) {
    for (int shift=0; shift < 16; shift++) {
      uint32_t errvec = (e << shift) & MASK_16BIT;

      uint32_t m = calcCheckBits(0x01);
      uint32_t sy = calcSyndrome(((1<<10) + m) ^ errvec);
      error_lookup_[sy] = errvec;
    }
  }

}

void BlockStream::uncorrectable() {
  printf(":offset %d: not received\n",expected_offset_);
  int data_length = 0;

  // TODO: return partial group
  /*if (has_block_[A]) {
    data_length = 1;

    if (has_block_[B]) {
      data_length = 2;

      if (has_block_[C] || has_block_[CI]) {
        data_length = 3;
      }
    }
  }*/

  block_has_errors_[block_counter_ % block_has_errors_.size()] = true;

  int erroneous_blocks = 0;
  for (bool e : block_has_errors_) {
    if (e)
      erroneous_blocks ++;
  }

  // Sync is lost when >45 out of last 50 blocks are erroneous (Section C.1.2)
  if (is_in_sync_ && erroneous_blocks > 45) {
    is_in_sync_ = false;
    for (int i=0; i<(int)block_has_errors_.size(); i++)
      block_has_errors_[i] = false;
    pi_ = 0x0000;
    printf(":too many errors, sync lost\n");
  }

  for (int o=A; o<=D; o++)
    has_block_[o] = false;

}

std::vector<uint16_t> BlockStream::getNextGroup() {

  has_whole_group_ = false;

  while (!(has_whole_group_ || isEOF())) {

    // Compensate for clock slip corrections
    bitcount_ += 26 - left_to_read_;

    // Read from radio
    for (int i=0; i < (is_in_sync_ ? left_to_read_ : 1); i++, bitcount_++) {
      wideblock_ = (wideblock_ << 1) + bit_stream_.getNextBit();
    }

    left_to_read_ = 26;
    wideblock_ &= MASK_28BIT;

    uint32_t block = (wideblock_ >> 1) & MASK_26BIT;

    // Find the offsets for which the calcSyndrome is zero
    bool has_sync_for_any = false;
    for (int o=A; o<=D; o++) {
      has_sync_for_[o] = (calcSyndrome(block ^ offset_word_[o]) == 0x000);
      has_sync_for_any |= has_sync_for_[o];
    }

    // Acquire sync

    if (!is_in_sync_) {
      if (has_sync_for_any) {
        for (int o=A; o<=D; o++) {
          if (has_sync_for_[o]) {
            int dist = bitcount_ - prevbitcount_;

            if (dist % 26 == 0 && dist <= 156 &&
                (block_for_offset_[prevsync_] + dist/26) % 4 == block_for_offset_[o]) {
              is_in_sync_ = true;
              expected_offset_ = o;
              printf(":sync!\n");
            } else {
              prevbitcount_ = bitcount_;
              prevsync_ = o;
            }
          }
        }
      }
    }

    // Synchronous decoding

    if (is_in_sync_) {

      block_counter_ ++;
      uint16_t message = block >> 10;

      if (expected_offset_ == C && !has_sync_for_[C] && has_sync_for_[CI]) {
        expected_offset_ = CI;
      }

      if ( !has_sync_for_[expected_offset_]) {

        // If message is a correct PI, error was probably in check bits
        if (expected_offset_ == A && message == pi_ && pi_ != 0) {
          has_sync_for_[A] = true;
          printf(":offset 0: ignoring error in check bits\n");
        } else if (expected_offset_ == C && message == pi_ && pi_ != 0) {
          has_sync_for_[CI] = true;
          printf(":offset 0: ignoring error in check bits\n");

        // Detect & correct clock slips (Section C.1.2)
        } else if (expected_offset_ == A && pi_ != 0 &&
            ((wideblock_ >> 12) & MASK_16BIT) == pi_) {
          message = pi_;
          wideblock_ >>= 1;
          has_sync_for_[A] = true;
          printf(":offset 0: clock slip corrected\n");
        } else if (expected_offset_ == A && pi_ != 0 &&
            ((wideblock_ >> 10) & MASK_16BIT) == pi_) {
          message = pi_;
          wideblock_ = (wideblock_ << 1) + bit_stream_.getNextBit();
          has_sync_for_[A] = true;
          left_to_read_ = 25;
          printf(":offset 0: clock slip corrected\n");

        // Detect & correct burst errors (Section B.2.2)
        } else {

          uint16_t synd_reg = calcSyndrome(block ^ offset_word_[expected_offset_]);

          if (pi_ != 0 && expected_offset_ == A) {
            printf(":offset 0: expecting PI%04x, got %04x, xor %04x, syndrome %03x\n",
                pi_, block>>10, pi_ ^ (block>>10), synd_reg);
          }

          if (error_lookup_.find(synd_reg) != error_lookup_.end()) {
            message = (block >> 10) ^ error_lookup_[synd_reg];
            has_sync_for_[expected_offset_] = true;

            printf(":offset %d: error corrected using vector %04x for syndrome %03x\n",
                expected_offset_, error_lookup_[synd_reg], synd_reg);

          }

        }

        // Still no sync pulse
        if ( !has_sync_for_[expected_offset_]) {
          uncorrectable();
        }
      }

      // Error-free block received

      if (has_sync_for_[expected_offset_]) {

        group_data_[block_for_offset_[expected_offset_]] = message;
        has_block_[expected_offset_] = true;

        if (expected_offset_ == A) {
          pi_ = message;
        }

        // Complete group received
        if (has_block_[A] && has_block_[B] && (has_block_[C] ||
            has_block_[CI]) && has_block_[D]) {
          has_whole_group_ = true;
        }
      }

      expected_offset_ = (expected_offset_ == C ? D : (expected_offset_ + 1) % 5);

      if (expected_offset_ == A) {
        for (int o=A; o<=D; o++)
          has_block_[o] = false;
      }

    }

  }

  return group_data_;

}

bool BlockStream::isEOF() const {
  return bit_stream_.isEOF();
}

} // namespace redsea
<commit_msg>rename complete<commit_after>#include "bits2blocks.h"

#define MASK_5BIT  0x000001F
#define MASK_10BIT 0x00003FF
#define MASK_16BIT 0x000FFFF
#define MASK_26BIT 0x3FFFFFF
#define MASK_28BIT 0xFFFFFFF

#define MAX_ERR_LEN 3

namespace redsea {

namespace {

uint32_t rol10(uint32_t word, int k) {
  uint32_t result = word;
  uint32_t l;
  for (int i=0; i<k; i++) {
    l       = (result & 0x200);
    result  = (result << 1) & 0x3FF;
    result ^= l;
  }
  return result;
}

uint32_t calcSyndrome(uint32_t vec) {

  uint32_t synd_reg = 0x000;
  uint32_t bit,l;

  for (int k=25; k>=0; k--) {
    bit       = (vec & (1 << k));
    l         = (synd_reg & 0x200);      // Store lefmost bit of register
    synd_reg  = (synd_reg << 1) & 0x3FF; // Rotate register
    synd_reg ^= (bit ? 0x31B : 0x00);    // Premultiply input by x^325 mod g(x)
    synd_reg ^= (l   ? 0x1B9 : 0x00);    // Division mod 2 by g(x)
  }

  return synd_reg;
}

uint32_t calcCheckBits(uint32_t dataWord) {
  uint32_t generator = 0x1B9;
  uint32_t result    = 0;

  for (int k=0; k<16; k++) {
    if ((dataWord >> k) & 0x01) {
      result ^= rol10(generator, k);
    }
  }
  return result;
}

}

BlockStream::BlockStream() : has_sync_for_(5), group_data_(4), has_block_(5),
  bitcount_(0), left_to_read_(0), bit_stream_(), wideblock_(0), block_has_errors_(50)

{

  offset_word_ = {0x0FC, 0x198, 0x168, 0x350, 0x1B4};

  block_for_offset_ = {0, 1, 2, 2, 3};

  for (uint32_t e=1; e < (1<<MAX_ERR_LEN); e++) {
    for (int shift=0; shift < 16; shift++) {
      uint32_t errvec = (e << shift) & MASK_16BIT;

      uint32_t m = calcCheckBits(0x01);
      uint32_t sy = calcSyndrome(((1<<10) + m) ^ errvec);
      error_lookup_[sy] = errvec;
    }
  }

}

void BlockStream::uncorrectable() {
  printf(":offset %d: not received\n",expected_offset_);
  int data_length = 0;

  // TODO: return partial group
  /*if (has_block_[A]) {
    data_length = 1;

    if (has_block_[B]) {
      data_length = 2;

      if (has_block_[C] || has_block_[CI]) {
        data_length = 3;
      }
    }
  }*/

  block_has_errors_[block_counter_ % block_has_errors_.size()] = true;

  int erroneous_blocks = 0;
  for (bool e : block_has_errors_) {
    if (e)
      erroneous_blocks ++;
  }

  // Sync is lost when >45 out of last 50 blocks are erroneous (Section C.1.2)
  if (is_in_sync_ && erroneous_blocks > 45) {
    is_in_sync_ = false;
    for (int i=0; i<(int)block_has_errors_.size(); i++)
      block_has_errors_[i] = false;
    pi_ = 0x0000;
    printf(":too many errors, sync lost\n");
  }

  for (int o=A; o<=D; o++)
    has_block_[o] = false;

}

std::vector<uint16_t> BlockStream::getNextGroup() {

  has_whole_group_ = false;

  while (!(has_whole_group_ || isEOF())) {

    // Compensate for clock slip corrections
    bitcount_ += 26 - left_to_read_;

    // Read from radio
    for (int i=0; i < (is_in_sync_ ? left_to_read_ : 1); i++, bitcount_++) {
      wideblock_ = (wideblock_ << 1) + bit_stream_.getNextBit();
    }

    left_to_read_ = 26;
    wideblock_ &= MASK_28BIT;

    uint32_t block = (wideblock_ >> 1) & MASK_26BIT;

    // Find the offsets for which the calcSyndrome is zero
    bool has_sync_for_any = false;
    for (int o=A; o<=D; o++) {
      has_sync_for_[o] = (calcSyndrome(block ^ offset_word_[o]) == 0x000);
      has_sync_for_any |= has_sync_for_[o];
    }

    // Acquire sync

    if (!is_in_sync_) {
      if (has_sync_for_any) {
        for (int o=A; o<=D; o++) {
          if (has_sync_for_[o]) {
            int dist = bitcount_ - prevbitcount_;

            if (dist % 26 == 0 && dist <= 156 &&
                (block_for_offset_[prevsync_] + dist/26) % 4 == block_for_offset_[o]) {
              is_in_sync_ = true;
              expected_offset_ = o;
              printf(":sync!\n");
            } else {
              prevbitcount_ = bitcount_;
              prevsync_ = o;
            }
          }
        }
      }
    }

    // Synchronous decoding

    if (is_in_sync_) {

      block_counter_ ++;
      uint16_t message = block >> 10;

      if (expected_offset_ == C && !has_sync_for_[C] && has_sync_for_[CI]) {
        expected_offset_ = CI;
      }

      if ( !has_sync_for_[expected_offset_]) {

        // If message is a correct PI, error was probably in check bits
        if (expected_offset_ == A && message == pi_ && pi_ != 0) {
          has_sync_for_[A] = true;
          printf(":offset 0: ignoring error in check bits\n");
        } else if (expected_offset_ == C && message == pi_ && pi_ != 0) {
          has_sync_for_[CI] = true;
          printf(":offset 0: ignoring error in check bits\n");

        // Detect & correct clock slips (Section C.1.2)
        } else if (expected_offset_ == A && pi_ != 0 &&
            ((wideblock_ >> 12) & MASK_16BIT) == pi_) {
          message = pi_;
          wideblock_ >>= 1;
          has_sync_for_[A] = true;
          printf(":offset 0: clock slip corrected\n");
        } else if (expected_offset_ == A && pi_ != 0 &&
            ((wideblock_ >> 10) & MASK_16BIT) == pi_) {
          message = pi_;
          wideblock_ = (wideblock_ << 1) + bit_stream_.getNextBit();
          has_sync_for_[A] = true;
          left_to_read_ = 25;
          printf(":offset 0: clock slip corrected\n");

        // Detect & correct burst errors (Section B.2.2)
        } else {

          uint16_t synd_reg = calcSyndrome(block ^ offset_word_[expected_offset_]);

          if (pi_ != 0 && expected_offset_ == A) {
            printf(":offset 0: expecting PI%04x, got %04x, xor %04x, syndrome %03x\n",
                pi_, block>>10, pi_ ^ (block>>10), synd_reg);
          }

          if (error_lookup_.find(synd_reg) != error_lookup_.end()) {
            message = (block >> 10) ^ error_lookup_[synd_reg];
            has_sync_for_[expected_offset_] = true;

            printf(":offset %d: error corrected using vector %04x for syndrome %03x\n",
                expected_offset_, error_lookup_[synd_reg], synd_reg);

          }

        }

        // Still no sync pulse
        if ( !has_sync_for_[expected_offset_]) {
          uncorrectable();
        }
      }

      // Error-free block received

      if (has_sync_for_[expected_offset_]) {

        group_data_[block_for_offset_[expected_offset_]] = message;
        has_block_[expected_offset_] = true;

        if (expected_offset_ == A) {
          pi_ = message;
        }

        // Complete group received
        if (has_block_[A] && has_block_[B] && (has_block_[C] ||
            has_block_[CI]) && has_block_[D]) {
          has_whole_group_ = true;
        }
      }

      expected_offset_ = (expected_offset_ == C ? D : (expected_offset_ + 1) % 5);

      if (expected_offset_ == A) {
        for (int o=A; o<=D; o++)
          has_block_[o] = false;
      }

    }

  }

  return group_data_;

}

bool BlockStream::isEOF() const {
  return bit_stream_.isEOF();
}

} // namespace redsea
<|endoftext|>


<commit_before>// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/renderer/renderer_font_platform_win.h"

#include <dwrite.h>
#include <string>
#include <vector>
#include <wrl/implements.h>
#include <wrl/wrappers/corewrappers.h>

#include "base/debug/alias.h"
#include "base/debug/crash_logging.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_path.h"
#include "base/files/memory_mapped_file.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/scoped_vector.h"
#include "base/path_service.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "base/win/iat_patch_function.h"
#include "base/win/registry.h"
#include "base/win/scoped_comptr.h"

namespace {

namespace mswr = Microsoft::WRL;
namespace mswrw = Microsoft::WRL::Wrappers;

static const char kFontKeyName[] = "font_key_name";

class FontCollectionLoader
    : public mswr::RuntimeClass<mswr::RuntimeClassFlags<mswr::ClassicCom>,
                                IDWriteFontCollectionLoader> {
 public:
  // IDWriteFontCollectionLoader methods.
  virtual HRESULT STDMETHODCALLTYPE
      CreateEnumeratorFromKey(IDWriteFactory* factory,
                              void const* key,
                              UINT32 key_size,
                              IDWriteFontFileEnumerator** file_enumerator);

  static HRESULT Initialize(IDWriteFactory* factory);

  UINT32 GetFontMapSize();

  std::wstring GetFontNameFromKey(UINT32 idx);

  bool LoadFontListFromRegistry();

  FontCollectionLoader() {};
  virtual ~FontCollectionLoader() {};

 private:
  mswr::ComPtr<IDWriteFontFileLoader> file_loader_;

  std::vector<std::wstring> reg_fonts_;
};

mswr::ComPtr<FontCollectionLoader> g_font_loader;

class FontFileStream
    : public mswr::RuntimeClass<mswr::RuntimeClassFlags<mswr::ClassicCom>,
                                IDWriteFontFileStream> {
 public:
  // IDWriteFontFileStream methods.
  virtual HRESULT STDMETHODCALLTYPE
  ReadFileFragment(void const** fragment_start,
                   UINT64 file_offset,
                   UINT64 fragment_size,
                   void** context) {
    if (!memory_.get() || !memory_->IsValid() ||
        file_offset >= memory_->length() ||
        (file_offset + fragment_size) > memory_->length())
      return E_FAIL;

    *fragment_start = static_cast<BYTE const*>(memory_->data()) +
                      static_cast<size_t>(file_offset);
    *context = NULL;
    return S_OK;
  }

  virtual void STDMETHODCALLTYPE ReleaseFileFragment(void* context) {}

  virtual HRESULT STDMETHODCALLTYPE GetFileSize(UINT64* file_size) {
    if (!memory_.get() || !memory_->IsValid())
      return E_FAIL;

    *file_size = memory_->length();
    return S_OK;
  }

  virtual HRESULT STDMETHODCALLTYPE GetLastWriteTime(UINT64* last_write_time) {
    if (!memory_.get() || !memory_->IsValid())
      return E_FAIL;

    // According to MSDN article http://goo.gl/rrSYzi the "last modified time"
    // is used by DirectWrite font selection algorithms to determine whether
    // one font resource is more up to date than another one.
    // So by returning 0 we are assuming that it will treat all fonts to be
    // equally up to date.
    // TODO(shrikant): We should further investigate this.
    *last_write_time = 0;
    return S_OK;
  }

  FontFileStream::FontFileStream() : font_key_(0) {
  };

  HRESULT RuntimeClassInitialize(UINT32 font_key) {
    base::FilePath path;
    PathService::Get(base::DIR_WINDOWS_FONTS, &path);
    std::wstring font_key_name(g_font_loader->GetFontNameFromKey(font_key));
    path = path.Append(font_key_name.c_str());
    memory_.reset(new base::MemoryMappedFile());

    // Put some debug information on stack.
    WCHAR font_name[256];
    path.value().copy(font_name, arraysize(font_name));
    base::debug::Alias(font_name);

    if (!memory_->Initialize(path)) {
      memory_.reset();
      return E_FAIL;
    }

    font_key_ = font_key;

    base::debug::SetCrashKeyValue(kFontKeyName,
                                  base::WideToUTF8(font_key_name));
    return S_OK;
  }

  virtual ~FontFileStream() {}

  UINT32 font_key_;
  scoped_ptr<base::MemoryMappedFile> memory_;
};

class FontFileLoader
    : public mswr::RuntimeClass<mswr::RuntimeClassFlags<mswr::ClassicCom>,
                                IDWriteFontFileLoader> {
 public:
  // IDWriteFontFileLoader methods.
  virtual HRESULT STDMETHODCALLTYPE
  CreateStreamFromKey(void const* ref_key,
                      UINT32 ref_key_size,
                      IDWriteFontFileStream** stream) {
    if (ref_key_size != sizeof(UINT32))
      return E_FAIL;

    UINT32 font_key = *static_cast<const UINT32*>(ref_key);
    mswr::ComPtr<FontFileStream> font_stream;
    HRESULT hr = mswr::MakeAndInitialize<FontFileStream>(&font_stream,
                                                         font_key);
    if (SUCCEEDED(hr)) {
      *stream = font_stream.Detach();
      return S_OK;
    }
    return E_FAIL;
  }

  FontFileLoader() {}
  virtual ~FontFileLoader() {}
};

class FontFileEnumerator
    : public mswr::RuntimeClass<mswr::RuntimeClassFlags<mswr::ClassicCom>,
                                IDWriteFontFileEnumerator> {
 public:
  // IDWriteFontFileEnumerator methods.
  virtual HRESULT STDMETHODCALLTYPE MoveNext(BOOL* has_current_file) {
    *has_current_file = FALSE;

    if (current_file_)
      current_file_.ReleaseAndGetAddressOf();

    if (font_idx_ < g_font_loader->GetFontMapSize()) {
      HRESULT hr =
          factory_->CreateCustomFontFileReference(&font_idx_,
                                                  sizeof(UINT32),
                                                  file_loader_.Get(),
                                                  current_file_.GetAddressOf());
      DCHECK(SUCCEEDED(hr));
      *has_current_file = TRUE;
      font_idx_++;
    }
    return S_OK;
  }

  virtual HRESULT STDMETHODCALLTYPE
  GetCurrentFontFile(IDWriteFontFile** font_file) {
    if (!current_file_) {
      *font_file = NULL;
      return E_FAIL;
    }

    *font_file = current_file_.Detach();
    return S_OK;
  }

  FontFileEnumerator(const void* keys,
                     UINT32 buffer_size,
                     IDWriteFactory* factory,
                     IDWriteFontFileLoader* file_loader)
      : factory_(factory), file_loader_(file_loader), font_idx_(0) {}

  virtual ~FontFileEnumerator() {}

  mswr::ComPtr<IDWriteFactory> factory_;
  mswr::ComPtr<IDWriteFontFile> current_file_;
  mswr::ComPtr<IDWriteFontFileLoader> file_loader_;
  UINT32 font_idx_;
};

// IDWriteFontCollectionLoader methods.
HRESULT STDMETHODCALLTYPE FontCollectionLoader::CreateEnumeratorFromKey(
    IDWriteFactory* factory,
    void const* key,
    UINT32 key_size,
    IDWriteFontFileEnumerator** file_enumerator) {
  *file_enumerator = mswr::Make<FontFileEnumerator>(
                         key, key_size, factory, file_loader_.Get()).Detach();
  return S_OK;
}

// static
HRESULT FontCollectionLoader::Initialize(IDWriteFactory* factory) {
  DCHECK(g_font_loader == NULL);

  g_font_loader = mswr::Make<FontCollectionLoader>();
  if (!g_font_loader) {
    DCHECK(FALSE);
    return E_FAIL;
  }

  CHECK(g_font_loader->LoadFontListFromRegistry());

  g_font_loader->file_loader_ = mswr::Make<FontFileLoader>().Detach();

  factory->RegisterFontFileLoader(g_font_loader->file_loader_.Get());
  factory->RegisterFontCollectionLoader(g_font_loader.Get());

  return S_OK;
}

UINT32 FontCollectionLoader::GetFontMapSize() {
  return reg_fonts_.size();
}

std::wstring FontCollectionLoader::GetFontNameFromKey(UINT32 idx) {
  DCHECK(idx < reg_fonts_.size());
  return reg_fonts_[idx];
}

bool FontCollectionLoader::LoadFontListFromRegistry() {
  const wchar_t kFontsRegistry[] =
      L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Fonts";
  CHECK(reg_fonts_.empty());
  base::win::RegKey regkey;
  if (regkey.Open(HKEY_LOCAL_MACHINE, kFontsRegistry, KEY_READ) !=
      ERROR_SUCCESS) {
    return false;
  }

  std::wstring name;
  std::wstring value;
  for (DWORD idx = 0; idx < regkey.GetValueCount(); idx++) {
    if (regkey.GetValueNameAt(idx, &name) == ERROR_SUCCESS &&
        regkey.ReadValue(name.c_str(), &value) == ERROR_SUCCESS) {
      base::FilePath path(value.c_str());
      // We need to check if file name is the only component that exists,
      // we will ignore all other registry entries.
      std::vector<base::FilePath::StringType> components;
      path.GetComponents(&components);
      if (components.size() == 1) {
        reg_fonts_.push_back(value.c_str());
      }
    }
  }
  return true;
}

}  // namespace

namespace content {

mswr::ComPtr<IDWriteFontCollection> g_font_collection;

IDWriteFontCollection* GetCustomFontCollection(IDWriteFactory* factory) {
  if (g_font_collection.Get() != NULL)
    return g_font_collection.Get();

  base::TimeTicks start_tick = base::TimeTicks::Now();

  FontCollectionLoader::Initialize(factory);

  HRESULT hr = factory->CreateCustomFontCollection(
      g_font_loader.Get(), NULL, 0, g_font_collection.GetAddressOf());

  base::TimeDelta time_delta = base::TimeTicks::Now() - start_tick;
  int64 delta = time_delta.ToInternalValue();
  base::debug::Alias(&delta);
  UINT32 size = g_font_loader->GetFontMapSize();
  base::debug::Alias(&size);

  CHECK(SUCCEEDED(hr));
  CHECK(g_font_collection.Get() != NULL);

  base::debug::ClearCrashKey(kFontKeyName);

  return g_font_collection.Get();
}

}  // namespace content
<commit_msg>Added restricted font fallback to custom font collection loader. After few experiments/crashes it seems that some users have enormous number of fonts in the registry. On suspect that we have for failing to load collection is that direct write cache is unable to load/handle those many fonts. In this CL we are trying to see if we can put arbitrary limit on number of fonts that could be loaded. We also added a fallback mechanism where in if loading from registry fails, we will try to load only default fonts. Definition of 'default' is taken from file prefs_tab_helper.cc ~ kDefaultFonts.<commit_after>// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/renderer/renderer_font_platform_win.h"

#include <dwrite.h>
#include <string>
#include <vector>
#include <wrl/implements.h>
#include <wrl/wrappers/corewrappers.h>

#include "base/debug/alias.h"
#include "base/debug/crash_logging.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_path.h"
#include "base/files/memory_mapped_file.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/scoped_vector.h"
#include "base/path_service.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "base/win/iat_patch_function.h"
#include "base/win/registry.h"
#include "base/win/scoped_comptr.h"

namespace {

namespace mswr = Microsoft::WRL;
namespace mswrw = Microsoft::WRL::Wrappers;

static const char kFontKeyName[] = "font_key_name";

class FontCollectionLoader
    : public mswr::RuntimeClass<mswr::RuntimeClassFlags<mswr::ClassicCom>,
                                IDWriteFontCollectionLoader> {
 public:
  // IDWriteFontCollectionLoader methods.
  virtual HRESULT STDMETHODCALLTYPE
      CreateEnumeratorFromKey(IDWriteFactory* factory,
                              void const* key,
                              UINT32 key_size,
                              IDWriteFontFileEnumerator** file_enumerator);

  static HRESULT Initialize(IDWriteFactory* factory);

  UINT32 GetFontMapSize();

  std::wstring GetFontNameFromKey(UINT32 idx);

  bool LoadFontListFromRegistry();
  bool LoadRestrictedFontList();

  FontCollectionLoader() {};
  virtual ~FontCollectionLoader() {};

 private:
  mswr::ComPtr<IDWriteFontFileLoader> file_loader_;

  std::vector<std::wstring> reg_fonts_;
};

mswr::ComPtr<FontCollectionLoader> g_font_loader;

class FontFileStream
    : public mswr::RuntimeClass<mswr::RuntimeClassFlags<mswr::ClassicCom>,
                                IDWriteFontFileStream> {
 public:
  // IDWriteFontFileStream methods.
  virtual HRESULT STDMETHODCALLTYPE
  ReadFileFragment(void const** fragment_start,
                   UINT64 file_offset,
                   UINT64 fragment_size,
                   void** context) {
    if (!memory_.get() || !memory_->IsValid() ||
        file_offset >= memory_->length() ||
        (file_offset + fragment_size) > memory_->length())
      return E_FAIL;

    *fragment_start = static_cast<BYTE const*>(memory_->data()) +
                      static_cast<size_t>(file_offset);
    *context = NULL;
    return S_OK;
  }

  virtual void STDMETHODCALLTYPE ReleaseFileFragment(void* context) {}

  virtual HRESULT STDMETHODCALLTYPE GetFileSize(UINT64* file_size) {
    if (!memory_.get() || !memory_->IsValid())
      return E_FAIL;

    *file_size = memory_->length();
    return S_OK;
  }

  virtual HRESULT STDMETHODCALLTYPE GetLastWriteTime(UINT64* last_write_time) {
    if (!memory_.get() || !memory_->IsValid())
      return E_FAIL;

    // According to MSDN article http://goo.gl/rrSYzi the "last modified time"
    // is used by DirectWrite font selection algorithms to determine whether
    // one font resource is more up to date than another one.
    // So by returning 0 we are assuming that it will treat all fonts to be
    // equally up to date.
    // TODO(shrikant): We should further investigate this.
    *last_write_time = 0;
    return S_OK;
  }

  FontFileStream::FontFileStream() : font_key_(0) {
  };

  HRESULT RuntimeClassInitialize(UINT32 font_key) {
    base::FilePath path;
    PathService::Get(base::DIR_WINDOWS_FONTS, &path);
    std::wstring font_key_name(g_font_loader->GetFontNameFromKey(font_key));
    path = path.Append(font_key_name.c_str());
    memory_.reset(new base::MemoryMappedFile());

    // Put some debug information on stack.
    WCHAR font_name[256];
    path.value().copy(font_name, arraysize(font_name));
    base::debug::Alias(font_name);

    if (!memory_->Initialize(path)) {
      memory_.reset();
      return E_FAIL;
    }

    font_key_ = font_key;

    base::debug::SetCrashKeyValue(kFontKeyName,
                                  base::WideToUTF8(font_key_name));
    return S_OK;
  }

  virtual ~FontFileStream() {}

  UINT32 font_key_;
  scoped_ptr<base::MemoryMappedFile> memory_;
};

class FontFileLoader
    : public mswr::RuntimeClass<mswr::RuntimeClassFlags<mswr::ClassicCom>,
                                IDWriteFontFileLoader> {
 public:
  // IDWriteFontFileLoader methods.
  virtual HRESULT STDMETHODCALLTYPE
  CreateStreamFromKey(void const* ref_key,
                      UINT32 ref_key_size,
                      IDWriteFontFileStream** stream) {
    if (ref_key_size != sizeof(UINT32))
      return E_FAIL;

    UINT32 font_key = *static_cast<const UINT32*>(ref_key);
    mswr::ComPtr<FontFileStream> font_stream;
    HRESULT hr = mswr::MakeAndInitialize<FontFileStream>(&font_stream,
                                                         font_key);
    if (SUCCEEDED(hr)) {
      *stream = font_stream.Detach();
      return S_OK;
    }
    return E_FAIL;
  }

  FontFileLoader() {}
  virtual ~FontFileLoader() {}
};

class FontFileEnumerator
    : public mswr::RuntimeClass<mswr::RuntimeClassFlags<mswr::ClassicCom>,
                                IDWriteFontFileEnumerator> {
 public:
  // IDWriteFontFileEnumerator methods.
  virtual HRESULT STDMETHODCALLTYPE MoveNext(BOOL* has_current_file) {
    *has_current_file = FALSE;

    if (current_file_)
      current_file_.ReleaseAndGetAddressOf();

    if (font_idx_ < g_font_loader->GetFontMapSize()) {
      HRESULT hr =
          factory_->CreateCustomFontFileReference(&font_idx_,
                                                  sizeof(UINT32),
                                                  file_loader_.Get(),
                                                  current_file_.GetAddressOf());
      DCHECK(SUCCEEDED(hr));
      *has_current_file = TRUE;
      font_idx_++;
    }
    return S_OK;
  }

  virtual HRESULT STDMETHODCALLTYPE
  GetCurrentFontFile(IDWriteFontFile** font_file) {
    if (!current_file_) {
      *font_file = NULL;
      return E_FAIL;
    }

    *font_file = current_file_.Detach();
    return S_OK;
  }

  FontFileEnumerator(const void* keys,
                     UINT32 buffer_size,
                     IDWriteFactory* factory,
                     IDWriteFontFileLoader* file_loader)
      : factory_(factory), file_loader_(file_loader), font_idx_(0) {}

  virtual ~FontFileEnumerator() {}

  mswr::ComPtr<IDWriteFactory> factory_;
  mswr::ComPtr<IDWriteFontFile> current_file_;
  mswr::ComPtr<IDWriteFontFileLoader> file_loader_;
  UINT32 font_idx_;
};

// IDWriteFontCollectionLoader methods.
HRESULT STDMETHODCALLTYPE FontCollectionLoader::CreateEnumeratorFromKey(
    IDWriteFactory* factory,
    void const* key,
    UINT32 key_size,
    IDWriteFontFileEnumerator** file_enumerator) {
  *file_enumerator = mswr::Make<FontFileEnumerator>(
                         key, key_size, factory, file_loader_.Get()).Detach();
  return S_OK;
}

// static
HRESULT FontCollectionLoader::Initialize(IDWriteFactory* factory) {
  DCHECK(g_font_loader == NULL);

  g_font_loader = mswr::Make<FontCollectionLoader>();
  if (!g_font_loader) {
    DCHECK(FALSE);
    return E_FAIL;
  }

  CHECK(g_font_loader->LoadFontListFromRegistry());

  g_font_loader->file_loader_ = mswr::Make<FontFileLoader>().Detach();

  factory->RegisterFontFileLoader(g_font_loader->file_loader_.Get());
  factory->RegisterFontCollectionLoader(g_font_loader.Get());

  return S_OK;
}

UINT32 FontCollectionLoader::GetFontMapSize() {
  return reg_fonts_.size();
}

std::wstring FontCollectionLoader::GetFontNameFromKey(UINT32 idx) {
  DCHECK(idx < reg_fonts_.size());
  return reg_fonts_[idx];
}

bool FontCollectionLoader::LoadFontListFromRegistry() {
  const wchar_t kFontsRegistry[] =
      L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Fonts";
  CHECK(reg_fonts_.empty());
  base::win::RegKey regkey;
  if (regkey.Open(HKEY_LOCAL_MACHINE, kFontsRegistry, KEY_READ) !=
      ERROR_SUCCESS) {
    return false;
  }

  std::wstring name;
  std::wstring value;
  for (DWORD idx = 0; idx < regkey.GetValueCount(); idx++) {
    if (regkey.GetValueNameAt(idx, &name) == ERROR_SUCCESS &&
        regkey.ReadValue(name.c_str(), &value) == ERROR_SUCCESS) {
      base::FilePath path(value.c_str());
      // We need to check if file name is the only component that exists,
      // we will ignore all other registry entries.
      std::vector<base::FilePath::StringType> components;
      path.GetComponents(&components);
      if (components.size() == 1) {
        reg_fonts_.push_back(value.c_str());
      }
    }
  }
  return true;
}

// This list is mainly based on prefs/prefs_tab_helper.cc kFontDefaults.
const wchar_t* kRestrictedFontSet[] = {
  L"times.ttf",     // IDS_STANDARD_FONT_FAMILY
  L"timesbd.ttf",   // IDS_STANDARD_FONT_FAMILY
  L"timesbi.ttf",   // IDS_STANDARD_FONT_FAMILY
  L"timesi.ttf",    // IDS_STANDARD_FONT_FAMILY
  L"cour.ttf",      // IDS_FIXED_FONT_FAMILY
  L"courbd.ttf",    // IDS_FIXED_FONT_FAMILY
  L"courbi.ttf",    // IDS_FIXED_FONT_FAMILY
  L"couri.ttf",     // IDS_FIXED_FONT_FAMILY
  L"consola.ttf",   // IDS_FIXED_FONT_FAMILY_ALT_WIN
  L"consolab.ttf",  // IDS_FIXED_FONT_FAMILY_ALT_WIN
  L"consolai.ttf",  // IDS_FIXED_FONT_FAMILY_ALT_WIN
  L"consolaz.ttf",  // IDS_FIXED_FONT_FAMILY_ALT_WIN
  L"arial.ttf",     // IDS_SANS_SERIF_FONT_FAMILY
  L"arialbd.ttf",   // IDS_SANS_SERIF_FONT_FAMILY
  L"arialbi.ttf",   // IDS_SANS_SERIF_FONT_FAMILY
  L"ariali.ttf",    // IDS_SANS_SERIF_FONT_FAMILY
  L"comic.ttf",     // IDS_CURSIVE_FONT_FAMILY
  L"comicbd.ttf",   // IDS_CURSIVE_FONT_FAMILY
  L"comici.ttf",    // IDS_CURSIVE_FONT_FAMILY
  L"comicz.ttf",    // IDS_CURSIVE_FONT_FAMILY
  L"impact.ttf",    // IDS_FANTASY_FONT_FAMILY
  L"segoeui.ttf",   // IDS_PICTOGRAPH_FONT_FAMILY
  L"segoeuib.ttf",  // IDS_PICTOGRAPH_FONT_FAMILY
  L"segoeuii.ttf",  // IDS_PICTOGRAPH_FONT_FAMILY
  L"msgothic.ttc",  // IDS_STANDARD_FONT_FAMILY_JAPANESE
  L"msmincho.ttc",  // IDS_SERIF_FONT_FAMILY_JAPANESE
  L"gulim.ttc",     // IDS_FIXED_FONT_FAMILY_KOREAN
  L"batang.ttc",    // IDS_SERIF_FONT_FAMILY_KOREAN
  L"simsun.ttc",    // IDS_STANDARD_FONT_FAMILY_SIMPLIFIED_HAN
  L"mingliu.ttc",   // IDS_SERIF_FONT_FAMILY_TRADITIONAL_HAN
};

bool FontCollectionLoader::LoadRestrictedFontList() {
  reg_fonts_.clear();
  reg_fonts_.assign(kRestrictedFontSet,
                    kRestrictedFontSet + _countof(kRestrictedFontSet));
  return true;
}

}  // namespace

namespace content {

mswr::ComPtr<IDWriteFontCollection> g_font_collection;

IDWriteFontCollection* GetCustomFontCollection(IDWriteFactory* factory) {
  if (g_font_collection.Get() != NULL)
    return g_font_collection.Get();

  base::TimeTicks start_tick = base::TimeTicks::Now();

  FontCollectionLoader::Initialize(factory);

  // We try here to put arbitrary limit on max number of fonts that could
  // be loaded, otherwise we fallback to restricted set of fonts.
  const UINT32 kMaxFontThreshold = 1000;
  HRESULT hr = E_FAIL;
  if (g_font_loader->GetFontMapSize() < kMaxFontThreshold) {
    hr = factory->CreateCustomFontCollection(
        g_font_loader.Get(), NULL, 0, g_font_collection.GetAddressOf());
  }

  bool loadingRestricted = false;
  if (FAILED(hr) || !g_font_collection.Get()) {
    // We will try here just one more time with restricted font set.
    g_font_loader->LoadRestrictedFontList();
    hr = factory->CreateCustomFontCollection(
        g_font_loader.Get(), NULL, 0, g_font_collection.GetAddressOf());
  }

  base::TimeDelta time_delta = base::TimeTicks::Now() - start_tick;
  int64 delta = time_delta.ToInternalValue();
  base::debug::Alias(&delta);
  UINT32 size = g_font_loader->GetFontMapSize();
  base::debug::Alias(&size);
  base::debug::Alias(&loadingRestricted);

  CHECK(SUCCEEDED(hr));
  CHECK(g_font_collection.Get() != NULL);

  base::debug::ClearCrashKey(kFontKeyName);

  return g_font_collection.Get();
}

}  // namespace content
<|endoftext|>


<commit_before>#include "GenerateRecomLists.h"
GenerateRecomLists::GenerateRecomLists() {}

GenerateRecomLists::~GenerateRecomLists() {}

void inline copy_table_and_remove_fields(const vector<int>& config, const Table& table_vector, const Table& index_vector,
                                         Table& new_table_vector, Table& new_index_vector) {
    set<int> field_set;
    for (unsigned int i = 0; i < config.size(); i ++) {
        field_set.insert(config[i]);
    }

    for (unsigned int i = 0; i < table_vector.size(); ++i) {
        new_table_vector.push_back(vector<int> ());
        new_index_vector.push_back(vector<int> ());
        for (unsigned int j = 0; j < table_vector[i].size(); ++j) {
            if (field_set.count(index_vector[i][j])) {
                new_table_vector[i].push_back(table_vector[i][j]);
                new_index_vector[i].push_back(table_vector[i][j]);
            }
        }
    }
}

vector<RecPair> GenerateRecomLists::generate_recom_lists(
                              Table& ltoken_vector, Table& rtoken_vector,
                              Table& lindex_vector, Table& rindex_vector,
                              vector<int>& ltoken_sum_vector, vector<int>& rtoken_sum_vector, vector<int>& field_list,
                              CandSet& cand_set, double field_remove_ratio,
                              unsigned int output_size) {

    Table config_lists = generate_config(field_list, ltoken_sum_vector, rtoken_sum_vector, field_remove_ratio,
                           ltoken_vector.size(), rtoken_vector.size());

    int config_num = config_lists.size();
    vector<TopkRankList > rec_lists(config_num);
    for (int i = 0; i < config_num; i ++) {
      rec_lists[i] = generate_topk_with_config(config_lists[i], ltoken_vector, rtoken_vector, lindex_vector,
                                              rindex_vector, cand_set, output_size);
    }
    vector<RecPair> reclist = merge_topk_lists(rec_lists);
    return reclist;
}

/*
 * Generate Topk list for given config.
 */
TopkRankList GenerateRecomLists::generate_topk_with_config(
                              vector<int>& config,
                              Table& ltoken_vector, Table& rtoken_vector,
                              Table& lindex_vector, Table& rindex_vector,
                              CandSet& cand_set, unsigned int output_size) {
    Heap topkheap;
    Table new_ltoken_vector, new_rtoken_vector, new_lindex_vector, new_rindex_vector;
    copy_table_and_remove_fields(config, ltoken_vector, lindex_vector, new_ltoken_vector, new_lindex_vector);
    copy_table_and_remove_fields(config, rtoken_vector, rindex_vector, new_rtoken_vector, new_rindex_vector);
    topkheap = original_topk_sim_join_plain(new_ltoken_vector, new_rtoken_vector, cand_set, output_size);

    TopkRankList topkrank;
    int count = 0;
    while(!topkheap.empty()) {
      //cout << topkheap.top().l_rec << ' ' << topkheap.top().r_rec << ' ' << topkheap.top().sim << ' ' << count << endl;
      topkrank[make_pair(topkheap.top().l_rec, topkheap.top().r_rec)] = ++ count;
      topkheap.pop();
    }
    return topkrank;
}

bool cmp(RecPair& lhs, RecPair& rhs) {
  return lhs.rank < rhs.rank;
}

vector<RecPair> GenerateRecomLists::merge_topk_lists(vector<TopkRankList >& rec_lists) {
  vector<RecPair> rec_list;
  set<pair<int, int> > full_set;

  // Initialize the rankings for each topk recommendation list
  for (unsigned int i = 0; i < rec_lists.size(); i ++) {
    for (TopkRankList::iterator it = rec_lists[i].begin(); it != rec_lists[i].end(); it ++) {
      full_set.insert(make_pair(it->first.first, it->first.second));
    }
  }
  int list_size = rec_lists[0].size();

  // Get the median of each topk recommendation
  for (set<pair<int, int> >::iterator it = full_set.begin(); it != full_set.end(); it ++) {
    vector<int> tmp;

    // for each topk recommendation, if it does not exists in the rec_list of certain config, then its rank
    // under this config would be list_size + 1, otherwise use its original rank
    for (unsigned int i = 0; i < rec_lists.size(); i ++) {
      if (rec_lists[i].find(*it) == rec_lists[i].end()) {
        tmp.push_back(list_size + 1);
      } else {
        tmp.push_back(rec_lists[i][*it]);
      }
    }

    // use the median of ranks in all the configs as the final rank
    sort(tmp.begin(), tmp.end());
    if (tmp.size() & 1) {
      rec_list.push_back(RecPair((*it).first, (*it).second, tmp[tmp.size() / 2]));
    } else {
      rec_list.push_back(RecPair((*it).first, (*it).second, (tmp[tmp.size() / 2 - 1] + tmp[tmp.size() / 2]) / 2));
    }
  }
  sort(rec_list.begin(), rec_list.end(), cmp);
  return rec_list;
}

Table GenerateRecomLists::generate_config(const vector<int>& field_list, const vector<int>& ltoken_sum_vector,
                           const vector<int>& rtoken_sum_vector, const double field_remove_ratio,
                           const unsigned int ltable_size, const unsigned int rtable_size) {
    Table config_lists;
    vector<int> feat_list_copy = field_list;
    config_lists.push_back(feat_list_copy);
    while (feat_list_copy.size() > 1) {
        double max_ratio = 0.0;
        unsigned int ltoken_total_sum = 0, rtoken_total_sum = 0;
        int removed_field_index = -1;

        for (unsigned int i = 0; i < feat_list_copy.size(); ++i) {
            ltoken_total_sum += ltoken_sum_vector[feat_list_copy[i]];
            rtoken_total_sum += rtoken_sum_vector[feat_list_copy[i]];
        }

        double lrec_ave_len = ltoken_total_sum * 1.0 / ltable_size;
        double rrec_ave_len = rtoken_total_sum * 1.0 / rtable_size;
        double ratio = 1 - (feat_list_copy.size() - 1) * field_remove_ratio / (1.0 + field_remove_ratio) *
                 double_max(lrec_ave_len, rrec_ave_len) / (lrec_ave_len + rrec_ave_len);

        for (unsigned int i = 0; i < feat_list_copy.size(); ++i) {
            max_ratio = double_max(max_ratio, double_max(ltoken_sum_vector[feat_list_copy[i]] * 1.0 / ltoken_total_sum,
                                                         rtoken_sum_vector[feat_list_copy[i]] * 1.0 / rtoken_total_sum));
            if (ltoken_sum_vector[feat_list_copy[i]] > ltoken_total_sum * ratio ||
                    rtoken_sum_vector[feat_list_copy[i]] > rtoken_total_sum * ratio) {
                removed_field_index = i;
                break;
            }
        }

        if (removed_field_index < 0) {
            removed_field_index = feat_list_copy.size() - 1;
        }

        for (unsigned int i = 0; i < feat_list_copy.size(); ++i) {
            vector<int> temp = feat_list_copy;
            temp.erase(temp.begin() + i);
            if (temp.size() <= 0) {
                continue;
            }
            config_lists.push_back(temp);
        }
        feat_list_copy.erase(feat_list_copy.begin() + removed_field_index);
    }

    return config_lists;
}

double double_max(const double a, double b) {
    if (a > b) {
        return a;
    }
    return b;
}
<commit_msg>[FIX] Added const to comparison function.<commit_after>#include "GenerateRecomLists.h"
GenerateRecomLists::GenerateRecomLists() {}

GenerateRecomLists::~GenerateRecomLists() {}

void inline copy_table_and_remove_fields(const vector<int>& config, const Table& table_vector, const Table& index_vector,
                                         Table& new_table_vector, Table& new_index_vector) {
    set<int> field_set;
    for (unsigned int i = 0; i < config.size(); i ++) {
        field_set.insert(config[i]);
    }

    for (unsigned int i = 0; i < table_vector.size(); ++i) {
        new_table_vector.push_back(vector<int> ());
        new_index_vector.push_back(vector<int> ());
        for (unsigned int j = 0; j < table_vector[i].size(); ++j) {
            if (field_set.count(index_vector[i][j])) {
                new_table_vector[i].push_back(table_vector[i][j]);
                new_index_vector[i].push_back(table_vector[i][j]);
            }
        }
    }
}

vector<RecPair> GenerateRecomLists::generate_recom_lists(
                              Table& ltoken_vector, Table& rtoken_vector,
                              Table& lindex_vector, Table& rindex_vector,
                              vector<int>& ltoken_sum_vector, vector<int>& rtoken_sum_vector, vector<int>& field_list,
                              CandSet& cand_set, double field_remove_ratio,
                              unsigned int output_size) {

    Table config_lists = generate_config(field_list, ltoken_sum_vector, rtoken_sum_vector, field_remove_ratio,
                           ltoken_vector.size(), rtoken_vector.size());

    int config_num = config_lists.size();
    vector<TopkRankList > rec_lists(config_num);
    for (int i = 0; i < config_num; i ++) {
      rec_lists[i] = generate_topk_with_config(config_lists[i], ltoken_vector, rtoken_vector, lindex_vector,
                                              rindex_vector, cand_set, output_size);
    }
    vector<RecPair> reclist = merge_topk_lists(rec_lists);
    return reclist;
}

/*
 * Generate Topk list for given config.
 */
TopkRankList GenerateRecomLists::generate_topk_with_config(
                              vector<int>& config,
                              Table& ltoken_vector, Table& rtoken_vector,
                              Table& lindex_vector, Table& rindex_vector,
                              CandSet& cand_set, unsigned int output_size) {
    Heap topkheap;
    Table new_ltoken_vector, new_rtoken_vector, new_lindex_vector, new_rindex_vector;
    copy_table_and_remove_fields(config, ltoken_vector, lindex_vector, new_ltoken_vector, new_lindex_vector);
    copy_table_and_remove_fields(config, rtoken_vector, rindex_vector, new_rtoken_vector, new_rindex_vector);
    topkheap = original_topk_sim_join_plain(new_ltoken_vector, new_rtoken_vector, cand_set, output_size);

    TopkRankList topkrank;
    int count = 0;
    while(!topkheap.empty()) {
      //cout << topkheap.top().l_rec << ' ' << topkheap.top().r_rec << ' ' << topkheap.top().sim << ' ' << count << endl;
      topkrank[make_pair(topkheap.top().l_rec, topkheap.top().r_rec)] = ++ count;
      topkheap.pop();
    }
    return topkrank;
}

bool cmp(const RecPair& lhs, const RecPair& rhs) {
  return lhs.rank < rhs.rank;
}

vector<RecPair> GenerateRecomLists::merge_topk_lists(vector<TopkRankList >& rec_lists) {
  vector<RecPair> rec_list;
  set<pair<int, int> > full_set;

  // Initialize the rankings for each topk recommendation list
  for (unsigned int i = 0; i < rec_lists.size(); i ++) {
    for (TopkRankList::iterator it = rec_lists[i].begin(); it != rec_lists[i].end(); it ++) {
      full_set.insert(make_pair(it->first.first, it->first.second));
    }
  }
  int list_size = rec_lists[0].size();

  // Get the median of each topk recommendation
  for (set<pair<int, int> >::iterator it = full_set.begin(); it != full_set.end(); it ++) {
    vector<int> tmp;

    // for each topk recommendation, if it does not exists in the rec_list of certain config, then its rank
    // under this config would be list_size + 1, otherwise use its original rank
    for (unsigned int i = 0; i < rec_lists.size(); i ++) {
      if (rec_lists[i].find(*it) == rec_lists[i].end()) {
        tmp.push_back(list_size + 1);
      } else {
        tmp.push_back(rec_lists[i][*it]);
      }
    }

    // use the median of ranks in all the configs as the final rank
    sort(tmp.begin(), tmp.end());
    if (tmp.size() & 1) {
      rec_list.push_back(RecPair((*it).first, (*it).second, tmp[tmp.size() / 2]));
    } else {
      rec_list.push_back(RecPair((*it).first, (*it).second, (tmp[tmp.size() / 2 - 1] + tmp[tmp.size() / 2]) / 2));
    }
  }
  sort(rec_list.begin(), rec_list.end(), cmp);
  return rec_list;
}

Table GenerateRecomLists::generate_config(const vector<int>& field_list, const vector<int>& ltoken_sum_vector,
                           const vector<int>& rtoken_sum_vector, const double field_remove_ratio,
                           const unsigned int ltable_size, const unsigned int rtable_size) {
    Table config_lists;
    vector<int> feat_list_copy = field_list;
    config_lists.push_back(feat_list_copy);
    while (feat_list_copy.size() > 1) {
        double max_ratio = 0.0;
        unsigned int ltoken_total_sum = 0, rtoken_total_sum = 0;
        int removed_field_index = -1;

        for (unsigned int i = 0; i < feat_list_copy.size(); ++i) {
            ltoken_total_sum += ltoken_sum_vector[feat_list_copy[i]];
            rtoken_total_sum += rtoken_sum_vector[feat_list_copy[i]];
        }

        double lrec_ave_len = ltoken_total_sum * 1.0 / ltable_size;
        double rrec_ave_len = rtoken_total_sum * 1.0 / rtable_size;
        double ratio = 1 - (feat_list_copy.size() - 1) * field_remove_ratio / (1.0 + field_remove_ratio) *
                 double_max(lrec_ave_len, rrec_ave_len) / (lrec_ave_len + rrec_ave_len);

        for (unsigned int i = 0; i < feat_list_copy.size(); ++i) {
            max_ratio = double_max(max_ratio, double_max(ltoken_sum_vector[feat_list_copy[i]] * 1.0 / ltoken_total_sum,
                                                         rtoken_sum_vector[feat_list_copy[i]] * 1.0 / rtoken_total_sum));
            if (ltoken_sum_vector[feat_list_copy[i]] > ltoken_total_sum * ratio ||
                    rtoken_sum_vector[feat_list_copy[i]] > rtoken_total_sum * ratio) {
                removed_field_index = i;
                break;
            }
        }

        if (removed_field_index < 0) {
            removed_field_index = feat_list_copy.size() - 1;
        }

        for (unsigned int i = 0; i < feat_list_copy.size(); ++i) {
            vector<int> temp = feat_list_copy;
            temp.erase(temp.begin() + i);
            if (temp.size() <= 0) {
                continue;
            }
            config_lists.push_back(temp);
        }
        feat_list_copy.erase(feat_list_copy.begin() + removed_field_index);
    }

    return config_lists;
}

double double_max(const double a, double b) {
    if (a > b) {
        return a;
    }
    return b;
}
<|endoftext|>


<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/browser/android/media_player_manager_android.h"

#include "base/bind.h"
#include "content/browser/android/cookie_getter_impl.h"
#include "content/common/media/media_player_messages.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"

using media::MediaPlayerBridge;

// Threshold on the number of media players per renderer before we start
// attempting to release inactive media players.
static const int kMediaPlayerThreshold = 1;

namespace content {

MediaPlayerManagerAndroid::MediaPlayerManagerAndroid(
    RenderViewHost* render_view_host)
    : RenderViewHostObserver(render_view_host),
      ALLOW_THIS_IN_INITIALIZER_LIST(video_view_(this)),
      fullscreen_player_id_(-1) {
}

MediaPlayerManagerAndroid::~MediaPlayerManagerAndroid() {}

bool MediaPlayerManagerAndroid::OnMessageReceived(const IPC::Message& msg) {
  bool handled = true;
  IPC_BEGIN_MESSAGE_MAP(MediaPlayerManagerAndroid, msg)
    IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_EnterFullscreen, OnEnterFullscreen)
    IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_ExitFullscreen, OnExitFullscreen)
    IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_MediaPlayerInitialize, OnInitialize)
    IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_MediaPlayerStart, OnStart)
    IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_MediaPlayerSeek, OnSeek)
    IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_MediaPlayerPause, OnPause)
    IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_MediaPlayerRelease,
                        OnReleaseResources)
    IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_DestroyMediaPlayer, OnDestroyPlayer)
    IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_DestroyAllMediaPlayers,
                        DestroyAllMediaPlayers)
    IPC_MESSAGE_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP()
  return handled;
}

void MediaPlayerManagerAndroid::FullscreenPlayerPlay() {
  MediaPlayerBridge* player = GetFullscreenPlayer();
  if (player) {
    player->Start();
    Send(new MediaPlayerMsg_DidMediaPlayerPlay(
        routing_id(), fullscreen_player_id_));
  }
}

void MediaPlayerManagerAndroid::FullscreenPlayerPause() {
  MediaPlayerBridge* player = GetFullscreenPlayer();
  if (player) {
    player->Pause();
    Send(new MediaPlayerMsg_DidMediaPlayerPause(
        routing_id(), fullscreen_player_id_));
  }
}

void MediaPlayerManagerAndroid::FullscreenPlayerSeek(int msec) {
  MediaPlayerBridge* player = GetFullscreenPlayer();
  if (player)
    player->SeekTo(base::TimeDelta::FromMilliseconds(msec));
}

void MediaPlayerManagerAndroid::ExitFullscreen(bool release_media_player) {
  Send(new MediaPlayerMsg_DidExitFullscreen(
      routing_id(), fullscreen_player_id_));
  MediaPlayerBridge* player = GetFullscreenPlayer();
  fullscreen_player_id_ = -1;
  if (!player)
    return;
  if (release_media_player)
    player->Release();
  else
    player->SetVideoSurface(NULL);
}

void MediaPlayerManagerAndroid::SetVideoSurface(jobject surface) {
  MediaPlayerBridge* player = GetFullscreenPlayer();
  if (player) {
    player->SetVideoSurface(surface);
    Send(new MediaPlayerMsg_DidEnterFullscreen(
        routing_id(), player->player_id()));
  }
}

void MediaPlayerManagerAndroid::OnInitialize(
    int player_id, const std::string& url,
    const std::string& first_party_for_cookies) {
  for (ScopedVector<MediaPlayerBridge>::iterator it = players_.begin();
      it != players_.end(); ++it) {
    if ((*it)->player_id() == player_id) {
      players_.erase(it);
      break;
    }
  }

  RenderProcessHost* host = render_view_host()->GetProcess();
  BrowserContext* context = host->GetBrowserContext();
  players_.push_back(new MediaPlayerBridge(
      player_id, url, first_party_for_cookies,
      new CookieGetterImpl(context, host->GetID(), routing_id()),
      context->IsOffTheRecord(), this,
      base::Bind(&MediaPlayerManagerAndroid::OnError, base::Unretained(this)),
      base::Bind(&MediaPlayerManagerAndroid::OnVideoSizeChanged,
                 base::Unretained(this)),
      base::Bind(&MediaPlayerManagerAndroid::OnBufferingUpdate,
                 base::Unretained(this)),
      base::Bind(&MediaPlayerManagerAndroid::OnPrepared,
                 base::Unretained(this)),
      base::Bind(&MediaPlayerManagerAndroid::OnPlaybackComplete,
                 base::Unretained(this)),
      base::Bind(&MediaPlayerManagerAndroid::OnSeekComplete,
                 base::Unretained(this)),
      base::Bind(&MediaPlayerManagerAndroid::OnTimeUpdate,
                 base::Unretained(this))));

  // Send a MediaPrepared message to webkit so that Load() can finish.
  Send(new MediaPlayerMsg_MediaPrepared(
      routing_id(), player_id, GetPlayer(player_id)->GetDuration()));
}

void MediaPlayerManagerAndroid::OnStart(int player_id) {
  MediaPlayerBridge* player = GetPlayer(player_id);
  if (player)
    player->Start();
}

void MediaPlayerManagerAndroid::OnSeek(int player_id, base::TimeDelta time) {
  MediaPlayerBridge* player = GetPlayer(player_id);
  if (player)
    player->SeekTo(time);
}

void MediaPlayerManagerAndroid::OnPause(int player_id) {
  MediaPlayerBridge* player = GetPlayer(player_id);
  if (player)
    player->Pause();
}

void MediaPlayerManagerAndroid::OnEnterFullscreen(int player_id) {
  DCHECK_EQ(fullscreen_player_id_, -1);

  fullscreen_player_id_ = player_id;
  video_view_.CreateContentVideoView();
}

void MediaPlayerManagerAndroid::OnExitFullscreen(int player_id) {
  if (fullscreen_player_id_ == player_id) {
    MediaPlayerBridge* player = GetPlayer(player_id);
    if (player)
      player->SetVideoSurface(NULL);
    video_view_.DestroyContentVideoView();
    fullscreen_player_id_ = -1;
  }
}

void MediaPlayerManagerAndroid::OnReleaseResources(int player_id) {
  MediaPlayerBridge* player = GetPlayer(player_id);
  if (player)
    player->Release();
}

void MediaPlayerManagerAndroid::OnDestroyPlayer(int player_id) {
  for (ScopedVector<MediaPlayerBridge>::iterator it = players_.begin();
      it != players_.end(); ++it) {
    if ((*it)->player_id() == player_id) {
      players_.erase(it);
      break;
    }
  }
  if (fullscreen_player_id_ == player_id)
    fullscreen_player_id_ = -1;
}

void MediaPlayerManagerAndroid::DestroyAllMediaPlayers() {
  players_.clear();
  if (fullscreen_player_id_ != -1) {
    video_view_.DestroyContentVideoView();
    fullscreen_player_id_ = -1;
  }
}

MediaPlayerBridge* MediaPlayerManagerAndroid::GetPlayer(int player_id) {
  for (ScopedVector<MediaPlayerBridge>::iterator it = players_.begin();
      it != players_.end(); ++it) {
    if ((*it)->player_id() == player_id)
      return *it;
  }
  return NULL;
}

MediaPlayerBridge* MediaPlayerManagerAndroid::GetFullscreenPlayer() {
  return GetPlayer(fullscreen_player_id_);
}

void MediaPlayerManagerAndroid::OnPrepared(int player_id,
                                           base::TimeDelta duration) {
  Send(new MediaPlayerMsg_MediaPrepared(routing_id(), player_id, duration));
  if (fullscreen_player_id_ != -1)
    video_view_.UpdateMediaMetadata();
}

void MediaPlayerManagerAndroid::OnPlaybackComplete(int player_id) {
  Send(new MediaPlayerMsg_MediaPlaybackCompleted(routing_id(), player_id));
  if (fullscreen_player_id_ != -1)
    video_view_.OnPlaybackComplete();
}

void MediaPlayerManagerAndroid::OnBufferingUpdate(
    int player_id, int percentage) {
  Send(new MediaPlayerMsg_MediaBufferingUpdate(
      routing_id(), player_id, percentage));
  if (fullscreen_player_id_ != -1)
    video_view_.OnBufferingUpdate(percentage);
}

void MediaPlayerManagerAndroid::OnSeekComplete(int player_id,
                                               base::TimeDelta current_time) {
  Send(new MediaPlayerMsg_MediaSeekCompleted(
      routing_id(), player_id, current_time));
}

void MediaPlayerManagerAndroid::OnError(int player_id, int error) {
  Send(new MediaPlayerMsg_MediaError(routing_id(), player_id, error));
  if (fullscreen_player_id_ != -1)
    video_view_.OnMediaPlayerError(error);
}

void MediaPlayerManagerAndroid::OnVideoSizeChanged(
    int player_id, int width, int height) {
  Send(new MediaPlayerMsg_MediaVideoSizeChanged(routing_id(), player_id,
      width, height));
  if (fullscreen_player_id_ != -1)
    video_view_.OnVideoSizeChanged(width, height);
}

void MediaPlayerManagerAndroid::OnTimeUpdate(int player_id,
                                             base::TimeDelta current_time) {
  Send(new MediaPlayerMsg_MediaTimeUpdate(
      routing_id(), player_id, current_time));
}

void MediaPlayerManagerAndroid::RequestMediaResources(
    MediaPlayerBridge* player) {
  if (player == NULL)
    return;

  int num_active_player = 0;
  ScopedVector<MediaPlayerBridge>::iterator it;
  for (it = players_.begin(); it != players_.end(); ++it) {
    if (!(*it)->prepared())
      continue;

    // The player is already active, ignore it.
    if ((*it) == player)
      return;
    else
      num_active_player++;
  }

  // Number of active players are less than the threshold, do nothing.
  if (num_active_player < kMediaPlayerThreshold)
    return;

  for (it = players_.begin(); it != players_.end(); ++it) {
    if ((*it)->prepared() && !(*it)->IsPlaying() &&
        fullscreen_player_id_ != (*it)->player_id()) {
      (*it)->Release();
      Send(new MediaPlayerMsg_MediaPlayerReleased(
          routing_id(), (*it)->player_id()));
    }
  }
}

void MediaPlayerManagerAndroid::ReleaseMediaResources(
    MediaPlayerBridge* player) {
  // Nothing needs to be done.
}

}  // namespace content
<commit_msg>Upstream a fix for fulscreen video after resuming from screen lock<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/browser/android/media_player_manager_android.h"

#include "base/bind.h"
#include "content/browser/android/cookie_getter_impl.h"
#include "content/common/media/media_player_messages.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"

using media::MediaPlayerBridge;

// Threshold on the number of media players per renderer before we start
// attempting to release inactive media players.
static const int kMediaPlayerThreshold = 1;

namespace content {

MediaPlayerManagerAndroid::MediaPlayerManagerAndroid(
    RenderViewHost* render_view_host)
    : RenderViewHostObserver(render_view_host),
      ALLOW_THIS_IN_INITIALIZER_LIST(video_view_(this)),
      fullscreen_player_id_(-1) {
}

MediaPlayerManagerAndroid::~MediaPlayerManagerAndroid() {}

bool MediaPlayerManagerAndroid::OnMessageReceived(const IPC::Message& msg) {
  bool handled = true;
  IPC_BEGIN_MESSAGE_MAP(MediaPlayerManagerAndroid, msg)
    IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_EnterFullscreen, OnEnterFullscreen)
    IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_ExitFullscreen, OnExitFullscreen)
    IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_MediaPlayerInitialize, OnInitialize)
    IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_MediaPlayerStart, OnStart)
    IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_MediaPlayerSeek, OnSeek)
    IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_MediaPlayerPause, OnPause)
    IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_MediaPlayerRelease,
                        OnReleaseResources)
    IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_DestroyMediaPlayer, OnDestroyPlayer)
    IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_DestroyAllMediaPlayers,
                        DestroyAllMediaPlayers)
    IPC_MESSAGE_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP()
  return handled;
}

void MediaPlayerManagerAndroid::FullscreenPlayerPlay() {
  MediaPlayerBridge* player = GetFullscreenPlayer();
  if (player) {
    player->Start();
    Send(new MediaPlayerMsg_DidMediaPlayerPlay(
        routing_id(), fullscreen_player_id_));
  }
}

void MediaPlayerManagerAndroid::FullscreenPlayerPause() {
  MediaPlayerBridge* player = GetFullscreenPlayer();
  if (player) {
    player->Pause();
    Send(new MediaPlayerMsg_DidMediaPlayerPause(
        routing_id(), fullscreen_player_id_));
  }
}

void MediaPlayerManagerAndroid::FullscreenPlayerSeek(int msec) {
  MediaPlayerBridge* player = GetFullscreenPlayer();
  if (player)
    player->SeekTo(base::TimeDelta::FromMilliseconds(msec));
}

void MediaPlayerManagerAndroid::ExitFullscreen(bool release_media_player) {
  Send(new MediaPlayerMsg_DidExitFullscreen(
      routing_id(), fullscreen_player_id_));
  MediaPlayerBridge* player = GetFullscreenPlayer();
  fullscreen_player_id_ = -1;
  if (!player)
    return;
  if (release_media_player)
    player->Release();
  else
    player->SetVideoSurface(NULL);
}

void MediaPlayerManagerAndroid::SetVideoSurface(jobject surface) {
  MediaPlayerBridge* player = GetFullscreenPlayer();
  if (player) {
    player->SetVideoSurface(surface);
    Send(new MediaPlayerMsg_DidEnterFullscreen(
        routing_id(), player->player_id()));
  }
}

void MediaPlayerManagerAndroid::OnInitialize(
    int player_id, const std::string& url,
    const std::string& first_party_for_cookies) {
  for (ScopedVector<MediaPlayerBridge>::iterator it = players_.begin();
      it != players_.end(); ++it) {
    if ((*it)->player_id() == player_id) {
      players_.erase(it);
      break;
    }
  }

  RenderProcessHost* host = render_view_host()->GetProcess();
  BrowserContext* context = host->GetBrowserContext();
  players_.push_back(new MediaPlayerBridge(
      player_id, url, first_party_for_cookies,
      new CookieGetterImpl(context, host->GetID(), routing_id()),
      context->IsOffTheRecord(), this,
      base::Bind(&MediaPlayerManagerAndroid::OnError, base::Unretained(this)),
      base::Bind(&MediaPlayerManagerAndroid::OnVideoSizeChanged,
                 base::Unretained(this)),
      base::Bind(&MediaPlayerManagerAndroid::OnBufferingUpdate,
                 base::Unretained(this)),
      base::Bind(&MediaPlayerManagerAndroid::OnPrepared,
                 base::Unretained(this)),
      base::Bind(&MediaPlayerManagerAndroid::OnPlaybackComplete,
                 base::Unretained(this)),
      base::Bind(&MediaPlayerManagerAndroid::OnSeekComplete,
                 base::Unretained(this)),
      base::Bind(&MediaPlayerManagerAndroid::OnTimeUpdate,
                 base::Unretained(this))));

  // Send a MediaPrepared message to webkit so that Load() can finish.
  Send(new MediaPlayerMsg_MediaPrepared(
      routing_id(), player_id, GetPlayer(player_id)->GetDuration()));
}

void MediaPlayerManagerAndroid::OnStart(int player_id) {
  MediaPlayerBridge* player = GetPlayer(player_id);
  if (player)
    player->Start();
}

void MediaPlayerManagerAndroid::OnSeek(int player_id, base::TimeDelta time) {
  MediaPlayerBridge* player = GetPlayer(player_id);
  if (player)
    player->SeekTo(time);
}

void MediaPlayerManagerAndroid::OnPause(int player_id) {
  MediaPlayerBridge* player = GetPlayer(player_id);
  if (player)
    player->Pause();
}

void MediaPlayerManagerAndroid::OnEnterFullscreen(int player_id) {
  DCHECK_EQ(fullscreen_player_id_, -1);

  fullscreen_player_id_ = player_id;
  video_view_.CreateContentVideoView();
}

void MediaPlayerManagerAndroid::OnExitFullscreen(int player_id) {
  if (fullscreen_player_id_ == player_id) {
    MediaPlayerBridge* player = GetPlayer(player_id);
    if (player)
      player->SetVideoSurface(NULL);
    video_view_.DestroyContentVideoView();
    fullscreen_player_id_ = -1;
  }
}

void MediaPlayerManagerAndroid::OnReleaseResources(int player_id) {
  MediaPlayerBridge* player = GetPlayer(player_id);
  // Don't release the fullscreen player when tab visibility changes,
  // it will be released when user hit the back/home button or when
  // OnDestroyPlayer is called.
  if (player && player_id != fullscreen_player_id_)
    player->Release();
}

void MediaPlayerManagerAndroid::OnDestroyPlayer(int player_id) {
  for (ScopedVector<MediaPlayerBridge>::iterator it = players_.begin();
      it != players_.end(); ++it) {
    if ((*it)->player_id() == player_id) {
      players_.erase(it);
      break;
    }
  }
  if (fullscreen_player_id_ == player_id)
    fullscreen_player_id_ = -1;
}

void MediaPlayerManagerAndroid::DestroyAllMediaPlayers() {
  players_.clear();
  if (fullscreen_player_id_ != -1) {
    video_view_.DestroyContentVideoView();
    fullscreen_player_id_ = -1;
  }
}

MediaPlayerBridge* MediaPlayerManagerAndroid::GetPlayer(int player_id) {
  for (ScopedVector<MediaPlayerBridge>::iterator it = players_.begin();
      it != players_.end(); ++it) {
    if ((*it)->player_id() == player_id)
      return *it;
  }
  return NULL;
}

MediaPlayerBridge* MediaPlayerManagerAndroid::GetFullscreenPlayer() {
  return GetPlayer(fullscreen_player_id_);
}

void MediaPlayerManagerAndroid::OnPrepared(int player_id,
                                           base::TimeDelta duration) {
  Send(new MediaPlayerMsg_MediaPrepared(routing_id(), player_id, duration));
  if (fullscreen_player_id_ != -1)
    video_view_.UpdateMediaMetadata();
}

void MediaPlayerManagerAndroid::OnPlaybackComplete(int player_id) {
  Send(new MediaPlayerMsg_MediaPlaybackCompleted(routing_id(), player_id));
  if (fullscreen_player_id_ != -1)
    video_view_.OnPlaybackComplete();
}

void MediaPlayerManagerAndroid::OnBufferingUpdate(
    int player_id, int percentage) {
  Send(new MediaPlayerMsg_MediaBufferingUpdate(
      routing_id(), player_id, percentage));
  if (fullscreen_player_id_ != -1)
    video_view_.OnBufferingUpdate(percentage);
}

void MediaPlayerManagerAndroid::OnSeekComplete(int player_id,
                                               base::TimeDelta current_time) {
  Send(new MediaPlayerMsg_MediaSeekCompleted(
      routing_id(), player_id, current_time));
}

void MediaPlayerManagerAndroid::OnError(int player_id, int error) {
  Send(new MediaPlayerMsg_MediaError(routing_id(), player_id, error));
  if (fullscreen_player_id_ != -1)
    video_view_.OnMediaPlayerError(error);
}

void MediaPlayerManagerAndroid::OnVideoSizeChanged(
    int player_id, int width, int height) {
  Send(new MediaPlayerMsg_MediaVideoSizeChanged(routing_id(), player_id,
      width, height));
  if (fullscreen_player_id_ != -1)
    video_view_.OnVideoSizeChanged(width, height);
}

void MediaPlayerManagerAndroid::OnTimeUpdate(int player_id,
                                             base::TimeDelta current_time) {
  Send(new MediaPlayerMsg_MediaTimeUpdate(
      routing_id(), player_id, current_time));
}

void MediaPlayerManagerAndroid::RequestMediaResources(
    MediaPlayerBridge* player) {
  if (player == NULL)
    return;

  int num_active_player = 0;
  ScopedVector<MediaPlayerBridge>::iterator it;
  for (it = players_.begin(); it != players_.end(); ++it) {
    if (!(*it)->prepared())
      continue;

    // The player is already active, ignore it.
    if ((*it) == player)
      return;
    else
      num_active_player++;
  }

  // Number of active players are less than the threshold, do nothing.
  if (num_active_player < kMediaPlayerThreshold)
    return;

  for (it = players_.begin(); it != players_.end(); ++it) {
    if ((*it)->prepared() && !(*it)->IsPlaying() &&
        fullscreen_player_id_ != (*it)->player_id()) {
      (*it)->Release();
      Send(new MediaPlayerMsg_MediaPlayerReleased(
          routing_id(), (*it)->player_id()));
    }
  }
}

void MediaPlayerManagerAndroid::ReleaseMediaResources(
    MediaPlayerBridge* player) {
  // Nothing needs to be done.
}

}  // namespace content
<|endoftext|>


<commit_before>#include "haar.h"

HaarWavelet::HaarWavelet(int nNumPoints, int nLevel)
{
	m_dRoot2 = 1.0 / 2.0;
	m_pTape = new double[nNumPoints];
	m_nNumPoints = nNumPoints;
	m_nLevel = nLevel;
}

HaarWavelet::~HaarWavelet()
{
	delete [] m_pTape;
}

void HaarWavelet::Transform(double* pBuf)
{
	int nMidPoint = m_nNumPoints / 2;
	int i = 0;
	int j = 0;
	// pass one to get the average vals
	for (i = 0; i < m_nNumPoints; i += 2)
	{
		m_pTape[j] = pBuf[i] + pBuf[i+1];
		m_pTape[j + nMidPoint] = pBuf[i] - pBuf[i+1];
		j++;
	}

	// seperate the multiply into 4 part sections, to speed up fpu usage
	for (i = 0; i < m_nNumPoints; i+=4)
	{
		m_pTape[i] *= m_dRoot2;
		m_pTape[i+1] *= m_dRoot2;
		m_pTape[i+2] *= m_dRoot2;
		m_pTape[i+3] *= m_dRoot2;
	}
	//cout << 1 / m_dRoot2 << endl;
	//Print();
	if (m_nLevel > 1)
	{
		int nStop = 0;
		int nLevel = 1;
		double* dTemp = new double[nMidPoint];
		while (nLevel < m_nLevel)
		{
			nStop = nMidPoint;
			nMidPoint /= 2;
			//cout << "mid: " << nMidPoint << " stop: " << nStop << endl;
			memcpy(dTemp, m_pTape, sizeof(double)*nStop);
			j = 0;
			for (i = 0; i < nStop; i+=2)
			{
				dTemp[j] = m_pTape[i] + m_pTape[i+1];
				dTemp[nMidPoint+j] = m_pTape[i] - m_pTape[i+1];
				j++;
			}
			memcpy(m_pTape, dTemp, sizeof(double)*nStop);

			for (i = 0; i < nStop; i += 2)
			{
				m_pTape[i] *= m_dRoot2;
				m_pTape[i+1] *= m_dRoot2;
			}
			nLevel++;
			//cout << "Level: " << nLevel << endl;
			//Print();
		}
		delete [] dTemp;
	}
}
<commit_msg>Fixed a compile problem on alpha<commit_after>#include <string.h>
#include "haar.h"

HaarWavelet::HaarWavelet(int nNumPoints, int nLevel)
{
	m_dRoot2 = 1.0 / 2.0;
	m_pTape = new double[nNumPoints];
	m_nNumPoints = nNumPoints;
	m_nLevel = nLevel;
}

HaarWavelet::~HaarWavelet()
{
	delete [] m_pTape;
}

void HaarWavelet::Transform(double* pBuf)
{
	int nMidPoint = m_nNumPoints / 2;
	int i = 0;
	int j = 0;
	// pass one to get the average vals
	for (i = 0; i < m_nNumPoints; i += 2)
	{
		m_pTape[j] = pBuf[i] + pBuf[i+1];
		m_pTape[j + nMidPoint] = pBuf[i] - pBuf[i+1];
		j++;
	}

	// seperate the multiply into 4 part sections, to speed up fpu usage
	for (i = 0; i < m_nNumPoints; i+=4)
	{
		m_pTape[i] *= m_dRoot2;
		m_pTape[i+1] *= m_dRoot2;
		m_pTape[i+2] *= m_dRoot2;
		m_pTape[i+3] *= m_dRoot2;
	}
	//cout << 1 / m_dRoot2 << endl;
	//Print();
	if (m_nLevel > 1)
	{
		int nStop = 0;
		int nLevel = 1;
		double* dTemp = new double[nMidPoint];
		while (nLevel < m_nLevel)
		{
			nStop = nMidPoint;
			nMidPoint /= 2;
			//cout << "mid: " << nMidPoint << " stop: " << nStop << endl;
			memcpy(dTemp, m_pTape, sizeof(double)*nStop);
			j = 0;
			for (i = 0; i < nStop; i+=2)
			{
				dTemp[j] = m_pTape[i] + m_pTape[i+1];
				dTemp[nMidPoint+j] = m_pTape[i] - m_pTape[i+1];
				j++;
			}
			memcpy(m_pTape, dTemp, sizeof(double)*nStop);

			for (i = 0; i < nStop; i += 2)
			{
				m_pTape[i] *= m_dRoot2;
				m_pTape[i+1] *= m_dRoot2;
			}
			nLevel++;
			//cout << "Level: " << nLevel << endl;
			//Print();
		}
		delete [] dTemp;
	}
}
<|endoftext|>