<commit_before>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2009 Torus Knot Software Ltd

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-----------------------------------------------------------------------------
*/

#include "OgreNaClGLContext.h"
#include "OgreLog.h"
#include "OgreException.h"
#include "OgreRoot.h"
#include "OgreException.h"
#include "OgreLogManager.h"
#include "OgreStringConverter.h"
#include "OgreWindowEventUtilities.h"

#include "OgreGLES2Prerequisites.h"
#include "OgreGLES2RenderSystem.h"

#include "OgreNaClGLSupport.h"
#include "OgreNaClWindow.h"
#include "OgreNaClGLContext.h"

#include <stdint.h>

namespace Ogre {
    NaClGLContext::NaClGLContext(const NaClWindow * window, const NaClGLSupport *glsupport, pp::Instance* instance, pp::CompletionCallback* swapCallback)
		: pp::Graphics3DClient(instance)
        , mWindow(window)
        , mGLSupport(glsupport)
        , mInstance(instance)
        , mSwapCallback(swapCallback)
        , mWidth(mWindow->getWidth())
        , mHeight(mWindow->getHeight())
    {
    }

    NaClGLContext::~NaClGLContext()
    {
        glSetCurrentContextPPAPI(0);
    }

	void NaClGLContext::setCurrent()
    {
        if (mInstance == NULL) {
            glSetCurrentContextPPAPI(0);
            return;
        }
        // Lazily create the Pepper context.
        if (mContext.is_null())
        {
            LogManager::getSingleton().logMessage("\tcreate context started");

            int32_t attribs[] = {
                PP_GRAPHICS3DATTRIB_ALPHA_SIZE, 0,
                PP_GRAPHICS3DATTRIB_BLUE_SIZE, 8,
                PP_GRAPHICS3DATTRIB_GREEN_SIZE, 8,
                PP_GRAPHICS3DATTRIB_RED_SIZE, 8,
                PP_GRAPHICS3DATTRIB_DEPTH_SIZE, 24,
                PP_GRAPHICS3DATTRIB_STENCIL_SIZE, 8,
                PP_GRAPHICS3DATTRIB_SAMPLES, 0,
                PP_GRAPHICS3DATTRIB_SAMPLE_BUFFERS, 0,
                PP_GRAPHICS3DATTRIB_WIDTH, mWindow->getWidth(),
                PP_GRAPHICS3DATTRIB_HEIGHT, mWindow->getHeight(),
                PP_GRAPHICS3DATTRIB_NONE
            };

            mContext = pp::Graphics3D(mInstance, pp::Graphics3D(), attribs);
            if (mContext.is_null())
            {
                glSetCurrentContextPPAPI(0);
                return;
            }
            mInstance->BindGraphics(mContext);
        }

        glSetCurrentContextPPAPI(mContext.pp_resource());
        return;
    }

    void NaClGLContext::endCurrent()
    {
        glSetCurrentContextPPAPI(0);
    }

    GLES2Context* NaClGLContext::clone() const
    {
        NaClGLContext* res = new NaClGLContext(mWindow, mGLSupport, mInstance, mSwapCallback);
        res->mInstance = this->mInstance;
        return res;
    }

    void NaClGLContext::swapBuffers( bool waitForVSync )
    {
        mContext.SwapBuffers(*mSwapCallback);
    }

    // overrides pp::Graphics3DClient
    void NaClGLContext::Graphics3DContextLost()
    {
        OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
            "Unexpectedly lost graphics context.",
            "NaClGLContext::Graphics3DContextLost" );
    }

    void NaClGLContext::resize()
    {
        if(mWidth != mWindow->getWidth() || mHeight != mWindow->getHeight() )
        {
            LogManager::getSingleton().logMessage("\tresizing");
            mWidth = mWindow->getWidth();
            mHeight = mWindow->getHeight();
            glSetCurrentContextPPAPI(0);
            mContext.ResizeBuffers( mWidth, mHeight );
            glSetCurrentContextPPAPI(mContext.pp_resource());
            LogManager::getSingleton().logMessage("\tdone resizing");
        }

    }

} // namespace
<commit_msg>Backed out changeset: 7631baa16dc0 Seems that there are better solutions for this issue: https://groups.google.com/d/msg/native-client-discuss/DQvA8VyvEKY/rljYZc4qfQgJ<commit_after>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2009 Torus Knot Software Ltd

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-----------------------------------------------------------------------------
*/

#include "OgreNaClGLContext.h"
#include "OgreLog.h"
#include "OgreException.h"
#include "OgreRoot.h"
#include "OgreException.h"
#include "OgreLogManager.h"
#include "OgreStringConverter.h"
#include "OgreWindowEventUtilities.h"

#include "OgreGLES2Prerequisites.h"
#include "OgreGLES2RenderSystem.h"

#include "OgreNaClGLSupport.h"
#include "OgreNaClWindow.h"
#include "OgreNaClGLContext.h"

#include <stdint.h>

namespace Ogre {
    NaClGLContext::NaClGLContext(const NaClWindow * window, const NaClGLSupport *glsupport, pp::Instance* instance, pp::CompletionCallback* swapCallback)
		: pp::Graphics3DClient(instance)
        , mWindow(window)
        , mGLSupport(glsupport)
        , mInstance(instance)
        , mSwapCallback(swapCallback)
        , mWidth(mWindow->getWidth())
        , mHeight(mWindow->getHeight())
    {
    }

    NaClGLContext::~NaClGLContext()
    {
        glSetCurrentContextPPAPI(0);
    }

	void NaClGLContext::setCurrent()
    {
        if (mInstance == NULL) {
            glSetCurrentContextPPAPI(0);
            return;
        }
        // Lazily create the Pepper context.
        if (mContext.is_null())
        {
            LogManager::getSingleton().logMessage("\tcreate context started");

            int32_t attribs[] = {
                PP_GRAPHICS3DATTRIB_ALPHA_SIZE, 8,
                PP_GRAPHICS3DATTRIB_DEPTH_SIZE, 24,
                PP_GRAPHICS3DATTRIB_STENCIL_SIZE, 8,
                PP_GRAPHICS3DATTRIB_SAMPLES, 0,
                PP_GRAPHICS3DATTRIB_SAMPLE_BUFFERS, 0,
                PP_GRAPHICS3DATTRIB_WIDTH, mWindow->getWidth(),
                PP_GRAPHICS3DATTRIB_HEIGHT, mWindow->getHeight(),
                PP_GRAPHICS3DATTRIB_NONE
            };

            mContext = pp::Graphics3D(mInstance, pp::Graphics3D(), attribs);
            if (mContext.is_null())
            {
                glSetCurrentContextPPAPI(0);
                return;
            }
            mInstance->BindGraphics(mContext);
        }

        glSetCurrentContextPPAPI(mContext.pp_resource());
        return;
    }

    void NaClGLContext::endCurrent()
    {
        glSetCurrentContextPPAPI(0);
    }

    GLES2Context* NaClGLContext::clone() const
    {
        NaClGLContext* res = new NaClGLContext(mWindow, mGLSupport, mInstance, mSwapCallback);
        res->mInstance = this->mInstance;
        return res;
    }

    void NaClGLContext::swapBuffers( bool waitForVSync )
    {
        mContext.SwapBuffers(*mSwapCallback);
    }

    // overrides pp::Graphics3DClient
    void NaClGLContext::Graphics3DContextLost()
    {
        OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
            "Unexpectedly lost graphics context.",
            "NaClGLContext::Graphics3DContextLost" );
    }

    void NaClGLContext::resize()
    {
        if(mWidth != mWindow->getWidth() || mHeight != mWindow->getHeight() )
        {
            LogManager::getSingleton().logMessage("\tresizing");
            mWidth = mWindow->getWidth();
            mHeight = mWindow->getHeight();
            glSetCurrentContextPPAPI(0);
            mContext.ResizeBuffers( mWidth, mHeight );
            glSetCurrentContextPPAPI(mContext.pp_resource());
            LogManager::getSingleton().logMessage("\tdone resizing");
        }

    }

} // namespace
<|endoftext|>


<commit_before>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// author:  Baozeng Ding <sploving1@gmail.com>
// author:  Vassil Vassilev <vasil.georgiev.vasilev@cern.ch>
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

#include "NullDerefProtectionTransformer.h"

#include "cling/Utils/AST.h"

#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Sema/Lookup.h"
#include "clang/AST/Expr.h"

#include <bitset>
#include <map>

using namespace clang;

namespace cling {
  NullDerefProtectionTransformer::NullDerefProtectionTransformer(clang::Sema* S)
    : WrapperTransformer(S) {
  }

  NullDerefProtectionTransformer::~NullDerefProtectionTransformer()
  { }

  class PointerCheckInjector : public RecursiveASTVisitor<PointerCheckInjector> {
  private:
    Sema& m_Sema;
    typedef llvm::DenseMap<clang::FunctionDecl*, std::bitset<32> > decl_map_t;
    llvm::DenseMap<clang::FunctionDecl*, std::bitset<32> > m_NonNullArgIndexs;

    ///\brief Needed for the AST transformations, owned by Sema.
    ///
    ASTContext& m_Context;

    ///\brief cling_runtime_internal_throwIfInvalidPointer cache.
    ///
    LookupResult* m_clingthrowIfInvalidPointerCache;

  public:
    PointerCheckInjector(Sema& S) : m_Sema(S), m_Context(S.getASTContext()),
    m_clingthrowIfInvalidPointerCache(0) {}

    bool VisitStmt(Stmt* S) {
      for (auto child: S->children()) {
        if (child)
            VisitStmt(child);
      }
      return true;
    }

    bool VisitUnaryOperator(UnaryOperator* UnOp) {
      VisitStmt(UnOp->getSubExpr());
      if (UnOp->getOpcode() == UO_Deref)
        if (UnOp->getSubExpr()->getType().getTypePtr()->isPointerType())
          UnOp->setSubExpr(SynthesizeCheck(UnOp->getSubExpr()));
      return true;
    }

    bool VisitMemberExpr(MemberExpr* ME) {
      VisitStmt(ME->getBase());
      if (ME->isArrow())
        ME->setBase(SynthesizeCheck(ME->getBase()));
      return true;
    }

    bool VisitCallExpr(CallExpr* CE) {
      VisitStmt(CE->getCallee());
      FunctionDecl* FDecl = CE->getDirectCallee();
      if (FDecl && isDeclCandidate(FDecl)) {
        decl_map_t::const_iterator it = m_NonNullArgIndexs.find(FDecl);
        const std::bitset<32>& ArgIndexs = it->second;
        Sema::ContextRAII pushedDC(m_Sema, FDecl);
        for (int index = 0; index < 32; ++index) {
          if (ArgIndexs.test(index)) {
            // Get the argument with the nonnull attribute.
            Expr* Arg = CE->getArg(index);
            if (Arg->getType().getTypePtr()->isPointerType())
              CE->setArg(index, SynthesizeCheck(Arg));
          }
        }
      }
      return true;
    }

    bool VisitDecl (Decl* D)
    {
      printf("%ld\n", *(long*)D);
      return true;
    }

    bool VisitFunctionDecl(FunctionDecl* FD) {
      if (!FD->isConstexpr()) {
        CompoundStmt* CS = dyn_cast_or_null<CompoundStmt>(FD->getBody());
        if (CS)
          VisitStmt(CS);
      }
      return true;
    }

    bool VisitCXXMethodDecl(CXXMethodDecl* FD) {
      if (!FD->isConstexpr()) {
        CompoundStmt* CS = dyn_cast_or_null<CompoundStmt>(FD->getBody());
        if (CS)
        VisitStmt(CS);
    }
      return true;
    }

    bool TraverseFunctionDecl(FunctionDecl* FD) {
      if (!FD->isConstexpr()) {
        CompoundStmt* CS = dyn_cast_or_null<CompoundStmt>(FD->getBody());
        if (CS)
          TraverseStmt(CS);
      }
      return true;
    }

    bool TraverseCXXMethodDecl(CXXMethodDecl* CMD) {
      if (!CMD->isConstexpr()){
        CompoundStmt* CS = dyn_cast_or_null<CompoundStmt>(CMD->getBody());
        if (CS)
        TraverseStmt(CS);
    }
      return true;
    }

  private:
    Expr* SynthesizeCheck(Expr* Arg) {
      assert(Arg && "Cannot call with Arg=0");

      if(!m_clingthrowIfInvalidPointerCache)
        FindAndCacheRuntimeLookupResult();

      SourceLocation Loc = Arg->getLocStart();
      Expr* VoidSemaArg = utils::Synthesize::CStyleCastPtrExpr(&m_Sema,
                                                            m_Context.VoidPtrTy,
                                                            (uint64_t)&m_Sema);
      Expr* VoidExprArg = utils::Synthesize::CStyleCastPtrExpr(&m_Sema,
                                                          m_Context.VoidPtrTy,
                                                          (uint64_t)Arg);
      Scope* S = m_Sema.getScopeForContext(m_Sema.CurContext);
      CXXScopeSpec CSS;

      Expr* checkCall
        = m_Sema.BuildDeclarationNameExpr(CSS,
                                          *m_clingthrowIfInvalidPointerCache,
                                         /*ADL*/ false).get();
      const clang::FunctionProtoType* checkCallType
        = llvm::dyn_cast<const clang::FunctionProtoType>(
            checkCall->getType().getTypePtr());

      TypeSourceInfo* constVoidPtrTSI = m_Context.getTrivialTypeSourceInfo(
        checkCallType->getParamType(2), Loc);

      Expr* voidPtrArg
        = m_Sema.BuildCStyleCastExpr(Loc, constVoidPtrTSI, Loc,
                                     Arg).get();

      Expr *args[] = {VoidSemaArg, VoidExprArg, voidPtrArg};

      if (Expr* call = m_Sema.ActOnCallExpr(S, checkCall,
                                         Loc, args, Loc).get()) {
        clang::TypeSourceInfo* argTSI = m_Context.getTrivialTypeSourceInfo(
                                        Arg->getType(), Loc);
        Expr* castExpr = m_Sema.BuildCStyleCastExpr(Loc, argTSI, Loc, call).get();
        return castExpr;
      }
      return voidPtrArg;
    }

    bool isDeclCandidate(FunctionDecl * FDecl) {
      if (m_NonNullArgIndexs.count(FDecl))
        return true;

      if (llvm::isa<CXXRecordDecl>(FDecl))
        return true;

      std::bitset<32> ArgIndexs;
      for (specific_attr_iterator<NonNullAttr>
             I = FDecl->specific_attr_begin<NonNullAttr>(),
             E = FDecl->specific_attr_end<NonNullAttr>(); I != E; ++I) {

        NonNullAttr *NonNull = *I;
        for (NonNullAttr::args_iterator i = NonNull->args_begin(),
               e = NonNull->args_end(); i != e; ++i) {
          ArgIndexs.set(*i);
        }
      }

      if (ArgIndexs.any()) {
        m_NonNullArgIndexs.insert(std::make_pair(FDecl, ArgIndexs));
        return true;
      }
      return false;
    }

    void FindAndCacheRuntimeLookupResult() {
      assert(!m_clingthrowIfInvalidPointerCache && "Called multiple times!?");

      DeclarationName Name
        = &m_Context.Idents.get("cling_runtime_internal_throwIfInvalidPointer");
      SourceLocation noLoc;
      m_clingthrowIfInvalidPointerCache = new LookupResult(m_Sema, Name, noLoc,
                                        Sema::LookupOrdinaryName,
                                        Sema::ForRedeclaration);
      m_Sema.LookupQualifiedName(*m_clingthrowIfInvalidPointerCache,
                                 m_Context.getTranslationUnitDecl());
      assert(!m_clingthrowIfInvalidPointerCache->empty() &&
              "Lookup of cling_runtime_internal_throwIfInvalidPointer failed!");
    }
  };

  ASTTransformer::Result
  NullDerefProtectionTransformer::Transform(clang::Decl* D) {

    PointerCheckInjector injector(*m_Sema);
    injector.TraverseDecl(D);
    return Result(D, true);
  }
} // end namespace cling
<commit_msg>Do not check null deref for static data members calls.<commit_after>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// author:  Baozeng Ding <sploving1@gmail.com>
// author:  Vassil Vassilev <vasil.georgiev.vasilev@cern.ch>
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

#include "NullDerefProtectionTransformer.h"

#include "cling/Utils/AST.h"

#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Sema/Lookup.h"
#include "clang/AST/Expr.h"

#include <bitset>
#include <map>

using namespace clang;

namespace cling {
  NullDerefProtectionTransformer::NullDerefProtectionTransformer(clang::Sema* S)
    : WrapperTransformer(S) {
  }

  NullDerefProtectionTransformer::~NullDerefProtectionTransformer()
  { }

  class PointerCheckInjector : public RecursiveASTVisitor<PointerCheckInjector> {
  private:
    Sema& m_Sema;
    typedef llvm::DenseMap<clang::FunctionDecl*, std::bitset<32> > decl_map_t;
    llvm::DenseMap<clang::FunctionDecl*, std::bitset<32> > m_NonNullArgIndexs;

    ///\brief Needed for the AST transformations, owned by Sema.
    ///
    ASTContext& m_Context;

    ///\brief cling_runtime_internal_throwIfInvalidPointer cache.
    ///
    LookupResult* m_clingthrowIfInvalidPointerCache;

  public:
    PointerCheckInjector(Sema& S) : m_Sema(S), m_Context(S.getASTContext()),
    m_clingthrowIfInvalidPointerCache(0) {}

    bool VisitStmt(Stmt* S) {
      for (auto child: S->children()) {
        if (child)
            VisitStmt(child);
      }
      return true;
    }

    bool VisitUnaryOperator(UnaryOperator* UnOp) {
      VisitStmt(UnOp->getSubExpr());
      if (UnOp->getOpcode() == UO_Deref)
        if (UnOp->getSubExpr()->getType().getTypePtr()->isPointerType())
          UnOp->setSubExpr(SynthesizeCheck(UnOp->getSubExpr()));
      return true;
    }

    bool VisitMemberExpr(MemberExpr* ME) {
      if (!((VarDecl*)(ME->getMemberDecl()))->isStaticDataMember()) {
        VisitStmt(ME->getBase());
        if (ME->isArrow())
          ME->setBase(SynthesizeCheck(ME->getBase()));
      }
      return true;
    }

    bool VisitCallExpr(CallExpr* CE) {
      VisitStmt(CE->getCallee());
      FunctionDecl* FDecl = CE->getDirectCallee();
      if (FDecl && isDeclCandidate(FDecl)) {
        decl_map_t::const_iterator it = m_NonNullArgIndexs.find(FDecl);
        const std::bitset<32>& ArgIndexs = it->second;
        Sema::ContextRAII pushedDC(m_Sema, FDecl);
        for (int index = 0; index < 32; ++index) {
          if (ArgIndexs.test(index)) {
            // Get the argument with the nonnull attribute.
            Expr* Arg = CE->getArg(index);
            if (Arg->getType().getTypePtr()->isPointerType())
              CE->setArg(index, SynthesizeCheck(Arg));
          }
        }
      }
      return true;
    }

    bool VisitDecl (Decl* D)
    {
      printf("%ld\n", *(long*)D);
      return true;
    }

    bool VisitFunctionDecl(FunctionDecl* FD) {
      if (!FD->isConstexpr()) {
        CompoundStmt* CS = dyn_cast_or_null<CompoundStmt>(FD->getBody());
        if (CS)
          VisitStmt(CS);
      }
      return true;
    }

    bool VisitCXXMethodDecl(CXXMethodDecl* FD) {
      if (!FD->isConstexpr()) {
        CompoundStmt* CS = dyn_cast_or_null<CompoundStmt>(FD->getBody());
        if (CS)
        VisitStmt(CS);
    }
      return true;
    }

    bool TraverseFunctionDecl(FunctionDecl* FD) {
      if (!FD->isConstexpr()) {
        CompoundStmt* CS = dyn_cast_or_null<CompoundStmt>(FD->getBody());
        if (CS)
          TraverseStmt(CS);
      }
      return true;
    }

    bool TraverseCXXMethodDecl(CXXMethodDecl* CMD) {
      if (!CMD->isConstexpr()){
        CompoundStmt* CS = dyn_cast_or_null<CompoundStmt>(CMD->getBody());
        if (CS)
        TraverseStmt(CS);
    }
      return true;
    }

  private:
    Expr* SynthesizeCheck(Expr* Arg) {
      assert(Arg && "Cannot call with Arg=0");

      if(!m_clingthrowIfInvalidPointerCache)
        FindAndCacheRuntimeLookupResult();

      SourceLocation Loc = Arg->getLocStart();
      Expr* VoidSemaArg = utils::Synthesize::CStyleCastPtrExpr(&m_Sema,
                                                            m_Context.VoidPtrTy,
                                                            (uint64_t)&m_Sema);
      Expr* VoidExprArg = utils::Synthesize::CStyleCastPtrExpr(&m_Sema,
                                                          m_Context.VoidPtrTy,
                                                          (uint64_t)Arg);
      Scope* S = m_Sema.getScopeForContext(m_Sema.CurContext);
      CXXScopeSpec CSS;

      Expr* checkCall
        = m_Sema.BuildDeclarationNameExpr(CSS,
                                          *m_clingthrowIfInvalidPointerCache,
                                         /*ADL*/ false).get();
      const clang::FunctionProtoType* checkCallType
        = llvm::dyn_cast<const clang::FunctionProtoType>(
            checkCall->getType().getTypePtr());

      TypeSourceInfo* constVoidPtrTSI = m_Context.getTrivialTypeSourceInfo(
        checkCallType->getParamType(2), Loc);

      Expr* voidPtrArg
        = m_Sema.BuildCStyleCastExpr(Loc, constVoidPtrTSI, Loc,
                                     Arg).get();

      Expr *args[] = {VoidSemaArg, VoidExprArg, voidPtrArg};

      if (Expr* call = m_Sema.ActOnCallExpr(S, checkCall,
                                         Loc, args, Loc).get()) {
        clang::TypeSourceInfo* argTSI = m_Context.getTrivialTypeSourceInfo(
                                        Arg->getType(), Loc);
        Expr* castExpr = m_Sema.BuildCStyleCastExpr(Loc, argTSI, Loc, call).get();
        return castExpr;
      }
      return voidPtrArg;
    }

    bool isDeclCandidate(FunctionDecl * FDecl) {
      if (m_NonNullArgIndexs.count(FDecl))
        return true;

      if (llvm::isa<CXXRecordDecl>(FDecl))
        return true;

      std::bitset<32> ArgIndexs;
      for (specific_attr_iterator<NonNullAttr>
             I = FDecl->specific_attr_begin<NonNullAttr>(),
             E = FDecl->specific_attr_end<NonNullAttr>(); I != E; ++I) {

        NonNullAttr *NonNull = *I;
        for (NonNullAttr::args_iterator i = NonNull->args_begin(),
               e = NonNull->args_end(); i != e; ++i) {
          ArgIndexs.set(*i);
        }
      }

      if (ArgIndexs.any()) {
        m_NonNullArgIndexs.insert(std::make_pair(FDecl, ArgIndexs));
        return true;
      }
      return false;
    }

    void FindAndCacheRuntimeLookupResult() {
      assert(!m_clingthrowIfInvalidPointerCache && "Called multiple times!?");

      DeclarationName Name
        = &m_Context.Idents.get("cling_runtime_internal_throwIfInvalidPointer");
      SourceLocation noLoc;
      m_clingthrowIfInvalidPointerCache = new LookupResult(m_Sema, Name, noLoc,
                                        Sema::LookupOrdinaryName,
                                        Sema::ForRedeclaration);
      m_Sema.LookupQualifiedName(*m_clingthrowIfInvalidPointerCache,
                                 m_Context.getTranslationUnitDecl());
      assert(!m_clingthrowIfInvalidPointerCache->empty() &&
              "Lookup of cling_runtime_internal_throwIfInvalidPointer failed!");
    }
  };

  ASTTransformer::Result
  NullDerefProtectionTransformer::Transform(clang::Decl* D) {

    PointerCheckInjector injector(*m_Sema);
    injector.TraverseDecl(D);
    return Result(D, true);
  }
} // end namespace cling
<|endoftext|>


<commit_before>#include <random>

#include "poly.h"
#include "bit_utils.h"
#include "utils.h"

/*****************************************************************************\
|*                                Constructors                               *|
\*****************************************************************************/

Poly::Poly() {
    for (unsigned i = 0; i < NUM_INLINE_BLOCKS; i++) {
        this->inlineBlocks[i] = 0;
    }
    this->deg = -1;
}

Poly::Poly(unsigned numBlocks) {
    //do nothing with numBlocks for now
    (void) numBlocks;

    for (unsigned i = 0; i < NUM_INLINE_BLOCKS; i++) {
        this->inlineBlocks[i] = 0;
    }
    this->deg = -1;
}

Poly Poly::fromInt(Block value) {
    Poly res;
    res.setBlock(0, value);
    res.computeDegree();
    return res;
}

Poly Poly::random(unsigned len) {
    std::default_random_engine generator;
    generator.seed(getNanoseconds());

    return Poly::random(len, generator);
}

//TODO: check bounds
Poly Poly::fromBlocks(Poly origin, unsigned start, unsigned end) {
    Poly res(end - start);

    for(unsigned i = start; i < end; i++) {
        res.setBlock(i - start, origin.block(i));
    }

    return res;
}

/*****************************************************************************\
|*                                  Accessors                                *|
\*****************************************************************************/

Poly::Bit Poly::bit(unsigned i) const {
    return ((this->block(i / BLOCK_SIZE)) >> (i % BLOCK_SIZE)) & 1;
}

Poly::Block Poly::block(unsigned i) const {
    return this->inlineBlocks[i];
}

int Poly::degree() const {
    return deg;
}

unsigned Poly::size() const {
    return this->degree() + 1;
}

unsigned Poly::numBlocks() const {
    return NUM_INLINE_BLOCKS;
}

unsigned Poly::numUsedBlocks() const {
    return (this->size() + (BLOCK_SIZE - 1)) / BLOCK_SIZE;
}

/*****************************************************************************\
|*                                 Operators                                 *|
\*****************************************************************************/

Poly Poly::operator+(const Poly& other) const {
    unsigned nBlocks = std::max(this->numUsedBlocks(), other.numUsedBlocks());
    Poly p(nBlocks);

    for (unsigned i = 0; i < nBlocks; i++) {
        p.setBlock(i, this->block(i) ^ other.block(i));
    }

    p.computeDegree();

    return p;
}

Poly Poly::operator-(const Poly& other) const {
    return *this + other;
}

Poly Poly::operator*(const Poly& other) const {
    return this->multiplyKaratsuba32(other);
}

Poly Poly::operator&(const Poly& other) const {
    unsigned nBlocks = (std::max(this->size(), other.size()) + (BLOCK_SIZE - 1)) / BLOCK_SIZE;
    Poly p(nBlocks);

    for (unsigned i = 0; i < nBlocks; i++) {
        p.setBlock(i, this->block(i) & other.block(i));
    }

    return p;
}

Poly Poly::operator|(const Poly& other) const {
    unsigned nBlocks = (std::max(this->size(), other.size()) + (BLOCK_SIZE - 1)) / BLOCK_SIZE;
    Poly p(nBlocks);

    for (unsigned i = 0; i < nBlocks; i++) {
        p.setBlock(i, this->block(i) | other.block(i));
    }

    return p;
}

Poly Poly::operator^(const Poly& other) const {
    unsigned nBlocks = (std::max(this->size(), other.size()) + (BLOCK_SIZE - 1)) / BLOCK_SIZE;
    Poly p(nBlocks);

    for (unsigned i = 0; i < nBlocks; i++) {
        p.setBlock(i, this->block(i) ^ other.block(i));
    }

    return p;
}

/*****************************************************************************\
|*                                   Misc                                    *|
\*****************************************************************************/

int Poly::computeDegree() {
    for (unsigned i = this->numBlocks(); i-->0;) {
        Block b = this->block(i);
        if (b != 0) {
            //TODO remove the assumption on the block size
            deg = i * BLOCK_SIZE + log2_u64(b);
            return deg;
        }
    }

    //We have the 0 polynomial.
    deg = -1;
    return deg;
}

Poly Poly::leftBlockShifted(unsigned i) const {
    unsigned nBlocks = this->numUsedBlocks();
    Poly res(nBlocks + i);

    for (unsigned j = 0; j < nBlocks; j++) {
        res.setBlock(i + j, this->block(j));
    }

    return res;
}

Poly Poly::rightBlockShifted(unsigned i) const {
    int nBlocks = this->numUsedBlocks();
    Poly res(nBlocks - i);

    for (int j = i; j < nBlocks; j++) {
        res.setBlock(j - i, this->block(j));
    }

    return res;
}

Poly Poly::multiplyNaively(const Poly& other) const {
    Poly res;
    for (unsigned i = 0; i < this->size(); i++) {
        for (unsigned j = 0; j < other.size(); j++) {
            res.xorBit(i + j, this->bit(i) & other.bit(j));
        }
    }

    res.computeDegree();

    return res;
}

Poly Poly::multiplyKaratsuba8(const Poly& other) const {
    return this->doMultiplyKaratsuba(other, 8);
}

Poly Poly::multiplyKaratsuba16(const Poly& other) const {
    return this->doMultiplyKaratsuba(other, 16);
}

Poly Poly::multiplyKaratsuba32(const Poly& other) const {
    return this->doMultiplyKaratsuba(other, 32);
}

/*****************************************************************************\
|*                         Private Basic Operations                          *|
\*****************************************************************************/

void Poly::setBlock(unsigned i, Block value) {
    this->inlineBlocks[i] = value;
}

void Poly::setBit(unsigned i, Bit value) {
    //Casting to blocks, else the shifting operations are done on 32 bits (size of the bits)
    //and the ~ puts ones in the upper bits of the block
    //Note that it is free, simply changing the shll to shlq mnemonics.
    Block valueBlock = value;

    this->inlineBlocks[i / BLOCK_SIZE] &= ~(((uint64_t)1) << i);
    this->inlineBlocks[i / BLOCK_SIZE] |= (valueBlock << i);
}

void Poly::xorBit(unsigned i, Bit value) {
    Block valueBlock = value;
    this->inlineBlocks[i / BLOCK_SIZE] ^= (valueBlock << i);
}

/*****************************************************************************\
|*                         Karatsuba implementation                          *|
\*****************************************************************************/

Poly Poly::doMultiplyKaratsuba(const Poly& other, unsigned splitLimit) const {
    if (this->size() == 0 or other.size() == 0) {
        return Poly::fromInt(0);
    }

    unsigned nBlocks = std::max(this->numUsedBlocks(), other.numUsedBlocks());
    static const bool debug = false;
    //TODO compute the degree before returning

    if (nBlocks > 1) {
        if (debug) {
            std::cout << "Doing karatsuba big" << std::endl;
        }

        return this->doMultiplyKaratsubaBig(other, splitLimit);
    }

    unsigned size = std::max(this->size(), other.size());

   /* if (size <= 8) {
    }
    */

    if (size <= 16) {
        if (debug) {
            std::cout << "Doing karatsuba 16" << std::endl;
        }
        return this->doMultiplyKaratsuba16(other, splitLimit);
    }

    if (size <= 32) {
        if (debug) {
            std::cout << "Doing karatsuba 32" << std::endl;
        }
        return this->doMultiplyKaratsuba32(other, splitLimit);
    }

    if (debug) {
        std::cout << "Doing karatsuba 64" << std::endl;
    }

    Poly res = this->doMultiplyKaratsuba64(other, splitLimit);
    res.computeDegree();
    return res;
}

Poly Poly::doMultiplyKaratsuba16(const Poly& other, unsigned splitLimit) const {
    return Poly::fromInt(convolution_16_32(this->block(0), other.block(0)));
}

Poly Poly::doMultiplyKaratsuba32(const Poly& other, unsigned splitLimit) const {
    return Poly::fromInt(convolution_32_64(this->block(0), other.block(0)));
}

Poly Poly::doMultiplyKaratsuba64(const Poly& other, unsigned splitLimit) const {
    static const bool debug = false;
    Poly a1 = Poly::fromInt(other.block(0) >> 32);
    Poly a0 = Poly::fromInt(other.block(0) & 0xFFFFFFFF);

    Poly b1 = Poly::fromInt(this->block(0) >> 32);
    Poly b0 = Poly::fromInt(this->block(0) & 0xFFFFFFFF);

    Poly c2 = a1.doMultiplyKaratsuba32(b1, splitLimit);
    Poly c0 = a0.doMultiplyKaratsuba32(b0, splitLimit);
    Poly c1 = (a1 + a0).doMultiplyKaratsuba32(b1 + b0, splitLimit) - c2 - c0;

    if (debug) {
        std::cout << " a: " << other << std::endl;
        std::cout << "a1: " << a1 << std::endl;
        std::cout << "a0: " << a0 << std::endl;

        std::cout << std::endl;

        std::cout << " b: " << *this << std::endl;
        std::cout << "b1: " << b1 << std::endl;
        std::cout << "b0: " << b0 << std::endl;

        std::cout << std::endl;

        std::cout << "c2: " << c2 << std::endl;
        std::cout << "c1: " << c1 << std::endl;
        std::cout << "c0: " << c0 << std::endl;

        std::cout << std::endl;
    }

    Poly res;

    Block res1 = c2.block(0) ^ (c1.block(0) >> 32);
    Block res0 = c0.block(0) ^ ((c1.block(0) & 0xFFFFFFFF) << 32);

    res.setBlock(1, res1);
    res.setBlock(0, res0);

    if (debug) {
        if ((this->multiplyNaively(other) + res).size() != 0) {
            std::cout << "Error in Karatsuba64" << std::endl;
        }
    }

    return res;
}

Poly Poly::doMultiplyKaratsubaBig(const Poly& other, unsigned splitLimit) const {
    unsigned nBlocks = std::max(this->numUsedBlocks(), other.numUsedBlocks());
    static const bool debug = false;
    unsigned cut = (nBlocks + 1) / 2;

    Poly a1 = other.rightBlockShifted(cut);
    Poly a0 = Poly::fromBlocks(other, 0, cut);

    Poly b1 = this->rightBlockShifted(cut);
    Poly b0 = Poly::fromBlocks(*this, 0, cut);

    a1.computeDegree();
    a0.computeDegree();
    b1.computeDegree();
    b0.computeDegree();

    Poly c2 = a1.doMultiplyKaratsuba(b1, splitLimit);
    Poly c0 = a0.doMultiplyKaratsuba(b0, splitLimit);

    Poly c1 = (a1 + a0).doMultiplyKaratsuba(b1 + b0, splitLimit) - c2 - c0;

    if (debug) {
        std::cout << " a: " << other << std::endl;
        std::cout << "a1: " << a1 << std::endl;
        std::cout << "a0: " << a0 << std::endl;

        std::cout << std::endl;

        std::cout << " b: " << *this << std::endl;
        std::cout << "b1: " << b1 << std::endl;
        std::cout << "b0: " << b0 << std::endl;

        std::cout << std::endl;

        std::cout << "c2: " << c2 << std::endl;
        std::cout << "c1: " << c1 << std::endl;
        std::cout << "c0: " << c0 << std::endl;

        std::cout << std::endl;
    }

    Poly c2Shifted = c2.leftBlockShifted(cut * 2);
    Poly c1Shifted = c1.leftBlockShifted(cut);

    c2Shifted.computeDegree();
    c1Shifted.computeDegree();

    Poly res = c2Shifted + c1Shifted + c0;

    if (debug) {
        if ((this->multiplyNaively(other) + res).size() != 0) {
            std::cout << "#################################################""Error in KaratsubaBig" << std::endl;
        }else {
            std::cout << "Ok" << std::endl;
        }
    }

    return res;
}

/*****************************************************************************\
|*                                      IO                                   *|
\*****************************************************************************/

std::ostream& operator<<(std::ostream& os, const Poly& p) {
    os << "(";
    for (int i = p.size(); i-->0;) {
        os << p.bit(i);
    }
    os << "] - " << p.degree();

    return os;
}
<commit_msg>Show blocks when printing polynomials<commit_after>#include <random>

#include "poly.h"
#include "bit_utils.h"
#include "utils.h"

/*****************************************************************************\
|*                                Constructors                               *|
\*****************************************************************************/

Poly::Poly() {
    for (unsigned i = 0; i < NUM_INLINE_BLOCKS; i++) {
        this->inlineBlocks[i] = 0;
    }
    this->deg = -1;
}

Poly::Poly(unsigned numBlocks) {
    //do nothing with numBlocks for now
    (void) numBlocks;

    for (unsigned i = 0; i < NUM_INLINE_BLOCKS; i++) {
        this->inlineBlocks[i] = 0;
    }
    this->deg = -1;
}

Poly Poly::fromInt(Block value) {
    Poly res;
    res.setBlock(0, value);
    res.computeDegree();
    return res;
}

Poly Poly::random(unsigned len) {
    std::default_random_engine generator;
    generator.seed(getNanoseconds());

    return Poly::random(len, generator);
}

//TODO: check bounds
Poly Poly::fromBlocks(Poly origin, unsigned start, unsigned end) {
    Poly res(end - start);

    for(unsigned i = start; i < end; i++) {
        res.setBlock(i - start, origin.block(i));
    }

    return res;
}

/*****************************************************************************\
|*                                  Accessors                                *|
\*****************************************************************************/

Poly::Bit Poly::bit(unsigned i) const {
    return ((this->block(i / BLOCK_SIZE)) >> (i % BLOCK_SIZE)) & 1;
}

Poly::Block Poly::block(unsigned i) const {
    return this->inlineBlocks[i];
}

int Poly::degree() const {
    return deg;
}

unsigned Poly::size() const {
    return this->degree() + 1;
}

unsigned Poly::numBlocks() const {
    return NUM_INLINE_BLOCKS;
}

unsigned Poly::numUsedBlocks() const {
    return (this->size() + (BLOCK_SIZE - 1)) / BLOCK_SIZE;
}

/*****************************************************************************\
|*                                 Operators                                 *|
\*****************************************************************************/

Poly Poly::operator+(const Poly& other) const {
    unsigned nBlocks = std::max(this->numUsedBlocks(), other.numUsedBlocks());
    Poly p(nBlocks);

    for (unsigned i = 0; i < nBlocks; i++) {
        p.setBlock(i, this->block(i) ^ other.block(i));
    }

    p.computeDegree();

    return p;
}

Poly Poly::operator-(const Poly& other) const {
    return *this + other;
}

Poly Poly::operator*(const Poly& other) const {
    return this->multiplyKaratsuba32(other);
}

Poly Poly::operator&(const Poly& other) const {
    unsigned nBlocks = (std::max(this->size(), other.size()) + (BLOCK_SIZE - 1)) / BLOCK_SIZE;
    Poly p(nBlocks);

    for (unsigned i = 0; i < nBlocks; i++) {
        p.setBlock(i, this->block(i) & other.block(i));
    }

    return p;
}

Poly Poly::operator|(const Poly& other) const {
    unsigned nBlocks = (std::max(this->size(), other.size()) + (BLOCK_SIZE - 1)) / BLOCK_SIZE;
    Poly p(nBlocks);

    for (unsigned i = 0; i < nBlocks; i++) {
        p.setBlock(i, this->block(i) | other.block(i));
    }

    return p;
}

Poly Poly::operator^(const Poly& other) const {
    unsigned nBlocks = (std::max(this->size(), other.size()) + (BLOCK_SIZE - 1)) / BLOCK_SIZE;
    Poly p(nBlocks);

    for (unsigned i = 0; i < nBlocks; i++) {
        p.setBlock(i, this->block(i) ^ other.block(i));
    }

    return p;
}

/*****************************************************************************\
|*                                   Misc                                    *|
\*****************************************************************************/

int Poly::computeDegree() {
    for (unsigned i = this->numBlocks(); i-->0;) {
        Block b = this->block(i);
        if (b != 0) {
            //TODO remove the assumption on the block size
            deg = i * BLOCK_SIZE + log2_u64(b);
            return deg;
        }
    }

    //We have the 0 polynomial.
    deg = -1;
    return deg;
}

Poly Poly::leftBlockShifted(unsigned i) const {
    unsigned nBlocks = this->numUsedBlocks();
    Poly res(nBlocks + i);

    for (unsigned j = 0; j < nBlocks; j++) {
        res.setBlock(i + j, this->block(j));
    }

    return res;
}

Poly Poly::rightBlockShifted(unsigned i) const {
    int nBlocks = this->numUsedBlocks();
    Poly res(nBlocks - i);

    for (int j = i; j < nBlocks; j++) {
        res.setBlock(j - i, this->block(j));
    }

    return res;
}

Poly Poly::multiplyNaively(const Poly& other) const {
    Poly res;
    for (unsigned i = 0; i < this->size(); i++) {
        for (unsigned j = 0; j < other.size(); j++) {
            res.xorBit(i + j, this->bit(i) & other.bit(j));
        }
    }

    res.computeDegree();

    return res;
}

Poly Poly::multiplyKaratsuba8(const Poly& other) const {
    return this->doMultiplyKaratsuba(other, 8);
}

Poly Poly::multiplyKaratsuba16(const Poly& other) const {
    return this->doMultiplyKaratsuba(other, 16);
}

Poly Poly::multiplyKaratsuba32(const Poly& other) const {
    return this->doMultiplyKaratsuba(other, 32);
}

/*****************************************************************************\
|*                         Private Basic Operations                          *|
\*****************************************************************************/

void Poly::setBlock(unsigned i, Block value) {
    this->inlineBlocks[i] = value;
}

void Poly::setBit(unsigned i, Bit value) {
    //Casting to blocks, else the shifting operations are done on 32 bits (size of the bits)
    //and the ~ puts ones in the upper bits of the block
    //Note that it is free, simply changing the shll to shlq mnemonics.
    Block valueBlock = value;

    this->inlineBlocks[i / BLOCK_SIZE] &= ~(((uint64_t)1) << i);
    this->inlineBlocks[i / BLOCK_SIZE] |= (valueBlock << i);
}

void Poly::xorBit(unsigned i, Bit value) {
    Block valueBlock = value;
    this->inlineBlocks[i / BLOCK_SIZE] ^= (valueBlock << i);
}

/*****************************************************************************\
|*                         Karatsuba implementation                          *|
\*****************************************************************************/

Poly Poly::doMultiplyKaratsuba(const Poly& other, unsigned splitLimit) const {
    if (this->size() == 0 or other.size() == 0) {
        return Poly::fromInt(0);
    }

    unsigned nBlocks = std::max(this->numUsedBlocks(), other.numUsedBlocks());
    static const bool debug = false;
    //TODO compute the degree before returning

    if (nBlocks > 1) {
        if (debug) {
            std::cout << "Doing karatsuba big" << std::endl;
        }

        return this->doMultiplyKaratsubaBig(other, splitLimit);
    }

    unsigned size = std::max(this->size(), other.size());

   /* if (size <= 8) {
    }
    */

    if (size <= 16) {
        if (debug) {
            std::cout << "Doing karatsuba 16" << std::endl;
        }
        return this->doMultiplyKaratsuba16(other, splitLimit);
    }

    if (size <= 32) {
        if (debug) {
            std::cout << "Doing karatsuba 32" << std::endl;
        }
        return this->doMultiplyKaratsuba32(other, splitLimit);
    }

    if (debug) {
        std::cout << "Doing karatsuba 64" << std::endl;
    }

    Poly res = this->doMultiplyKaratsuba64(other, splitLimit);
    res.computeDegree();
    return res;
}

Poly Poly::doMultiplyKaratsuba16(const Poly& other, unsigned splitLimit) const {
    return Poly::fromInt(convolution_16_32(this->block(0), other.block(0)));
}

Poly Poly::doMultiplyKaratsuba32(const Poly& other, unsigned splitLimit) const {
    return Poly::fromInt(convolution_32_64(this->block(0), other.block(0)));
}

Poly Poly::doMultiplyKaratsuba64(const Poly& other, unsigned splitLimit) const {
    static const bool debug = false;
    Poly a1 = Poly::fromInt(other.block(0) >> 32);
    Poly a0 = Poly::fromInt(other.block(0) & 0xFFFFFFFF);

    Poly b1 = Poly::fromInt(this->block(0) >> 32);
    Poly b0 = Poly::fromInt(this->block(0) & 0xFFFFFFFF);

    Poly c2 = a1.doMultiplyKaratsuba32(b1, splitLimit);
    Poly c0 = a0.doMultiplyKaratsuba32(b0, splitLimit);
    Poly c1 = (a1 + a0).doMultiplyKaratsuba32(b1 + b0, splitLimit) - c2 - c0;

    if (debug) {
        std::cout << " a: " << other << std::endl;
        std::cout << "a1: " << a1 << std::endl;
        std::cout << "a0: " << a0 << std::endl;

        std::cout << std::endl;

        std::cout << " b: " << *this << std::endl;
        std::cout << "b1: " << b1 << std::endl;
        std::cout << "b0: " << b0 << std::endl;

        std::cout << std::endl;

        std::cout << "c2: " << c2 << std::endl;
        std::cout << "c1: " << c1 << std::endl;
        std::cout << "c0: " << c0 << std::endl;

        std::cout << std::endl;
    }

    Poly res;

    Block res1 = c2.block(0) ^ (c1.block(0) >> 32);
    Block res0 = c0.block(0) ^ ((c1.block(0) & 0xFFFFFFFF) << 32);

    res.setBlock(1, res1);
    res.setBlock(0, res0);

    if (debug) {
        if ((this->multiplyNaively(other) + res).size() != 0) {
            std::cout << "Error in Karatsuba64" << std::endl;
        }
    }

    return res;
}

Poly Poly::doMultiplyKaratsubaBig(const Poly& other, unsigned splitLimit) const {
    unsigned nBlocks = std::max(this->numUsedBlocks(), other.numUsedBlocks());
    static const bool debug = false;
    unsigned cut = (nBlocks + 1) / 2;

    Poly a1 = other.rightBlockShifted(cut);
    Poly a0 = Poly::fromBlocks(other, 0, cut);

    Poly b1 = this->rightBlockShifted(cut);
    Poly b0 = Poly::fromBlocks(*this, 0, cut);

    a1.computeDegree();
    a0.computeDegree();
    b1.computeDegree();
    b0.computeDegree();

    Poly c2 = a1.doMultiplyKaratsuba(b1, splitLimit);
    Poly c0 = a0.doMultiplyKaratsuba(b0, splitLimit);

    Poly c1 = (a1 + a0).doMultiplyKaratsuba(b1 + b0, splitLimit) - c2 - c0;

    if (debug) {
        std::cout << " a: " << other << std::endl;
        std::cout << "a1: " << a1 << std::endl;
        std::cout << "a0: " << a0 << std::endl;

        std::cout << std::endl;

        std::cout << " b: " << *this << std::endl;
        std::cout << "b1: " << b1 << std::endl;
        std::cout << "b0: " << b0 << std::endl;

        std::cout << std::endl;

        std::cout << "c2: " << c2 << std::endl;
        std::cout << "c1: " << c1 << std::endl;
        std::cout << "c0: " << c0 << std::endl;

        std::cout << std::endl;
    }

    Poly c2Shifted = c2.leftBlockShifted(cut * 2);
    Poly c1Shifted = c1.leftBlockShifted(cut);

    c2Shifted.computeDegree();
    c1Shifted.computeDegree();

    Poly res = c2Shifted + c1Shifted + c0;

    if (debug) {
        if ((this->multiplyNaively(other) + res).size() != 0) {
            std::cout << "#################################################""Error in KaratsubaBig" << std::endl;
        }else {
            std::cout << "Ok" << std::endl;
        }
    }

    return res;
}

/*****************************************************************************\
|*                                      IO                                   *|
\*****************************************************************************/

std::ostream& operator<<(std::ostream& os, const Poly& p) {
    os << "(";
    for (int i = p.size(); i-->0;) {
        os << p.bit(i);
        if (i != 0 and i % Poly::BLOCK_SIZE == 0) {
            os << ' ';
        }
    }
    os << "] - " << p.degree();

    return os;
}
<|endoftext|>


<commit_before>/*

Copyright (c) 2015, Project OSRM contributors
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.

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 HOLDER 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 MATCH_HPP
#define MATCH_HPP

#include "plugin_base.hpp"

#include "../algorithms/bayes_classifier.hpp"
#include "../algorithms/object_encoder.hpp"
#include "../data_structures/search_engine.hpp"
#include "../descriptors/descriptor_base.hpp"
#include "../descriptors/json_descriptor.hpp"
#include "../routing_algorithms/map_matching.hpp"
#include "../util/compute_angle.hpp"
#include "../util/integer_range.hpp"
#include "../util/json_logger.hpp"
#include "../util/json_util.hpp"
#include "../util/string_util.hpp"

#include <cstdlib>

#include <algorithm>
#include <memory>
#include <string>
#include <vector>

template <class DataFacadeT> class MapMatchingPlugin : public BasePlugin
{
    constexpr static const unsigned max_number_of_candidates = 10;

    std::shared_ptr<SearchEngine<DataFacadeT>> search_engine_ptr;

    using ClassifierT = BayesClassifier<LaplaceDistribution, LaplaceDistribution, double>;
    using TraceClassification = ClassifierT::ClassificationT;

  public:
    MapMatchingPlugin(DataFacadeT *facade, const int max_locations_map_matching)
        : descriptor_string("match"), facade(facade),
          max_locations_map_matching(max_locations_map_matching)
          // the values where derived from fitting a laplace distribution
          // to the values of manually classified traces
          ,
          classifier(LaplaceDistribution(0.0057154021891018675, 0.020294704891166186),
                     LaplaceDistribution(0.11467696742821254, 0.49918444000368756),
                     0.7977883096366508) // valid apriori probability
    {
        search_engine_ptr = std::make_shared<SearchEngine<DataFacadeT>>(facade);
    }

    virtual ~MapMatchingPlugin() {}

    const std::string GetDescriptor() const final { return descriptor_string; }

    TraceClassification
    classify(const float trace_length, const float matched_length, const int removed_points) const
    {
        const double distance_feature = -std::log(trace_length) + std::log(matched_length);

        // matched to the same point
        if (!std::isfinite(distance_feature))
        {
            return std::make_pair(ClassifierT::ClassLabel::NEGATIVE, 1.0);
        }

        const auto label_with_confidence = classifier.classify(distance_feature);

        // "second stage classifier": if we need to remove points there is something fishy
        if (removed_points > 0)
        {
            return std::make_pair(ClassifierT::ClassLabel::NEGATIVE, 1.0);
        }

        return label_with_confidence;
    }

    bool getCandiates(const std::vector<FixedPointCoordinate> &input_coords,
                      std::vector<double> &sub_trace_lengths,
                      osrm::matching::CandidateLists &candidates_lists)
    {
        double last_distance =
            coordinate_calculation::great_circle_distance(input_coords[0], input_coords[1]);
        sub_trace_lengths.resize(input_coords.size());
        sub_trace_lengths[0] = 0;
        for (const auto current_coordinate : osrm::irange<std::size_t>(0, input_coords.size()))
        {
            bool allow_uturn = false;
            if (0 < current_coordinate)
            {
                last_distance = coordinate_calculation::great_circle_distance(
                    input_coords[current_coordinate - 1], input_coords[current_coordinate]);
                sub_trace_lengths[current_coordinate] +=
                    sub_trace_lengths[current_coordinate - 1] + last_distance;
            }

            if (input_coords.size() - 1 > current_coordinate && 0 < current_coordinate)
            {
                double turn_angle = ComputeAngle::OfThreeFixedPointCoordinates(
                    input_coords[current_coordinate - 1], input_coords[current_coordinate],
                    input_coords[current_coordinate + 1]);

                // sharp turns indicate a possible uturn
                if (turn_angle <= 90.0 || turn_angle >= 270.0)
                {
                    allow_uturn = true;
                }
            }

            std::vector<std::pair<PhantomNode, double>> candidates;
            if (!facade->IncrementalFindPhantomNodeForCoordinateWithMaxDistance(
                    input_coords[current_coordinate], candidates, last_distance / 2.0, 5,
                    max_number_of_candidates))
            {
                return false;
            }

            if (allow_uturn)
            {
                candidates_lists.push_back(candidates);
            }
            else
            {
                const auto compact_size = candidates.size();
                for (const auto i : osrm::irange<std::size_t>(0, compact_size))
                {
                    // Split edge if it is bidirectional and append reverse direction to end of list
                    if (candidates[i].first.forward_node_id != SPECIAL_NODEID &&
                        candidates[i].first.reverse_node_id != SPECIAL_NODEID)
                    {
                        PhantomNode reverse_node(candidates[i].first);
                        reverse_node.forward_node_id = SPECIAL_NODEID;
                        candidates.push_back(std::make_pair(reverse_node, candidates[i].second));

                        candidates[i].first.reverse_node_id = SPECIAL_NODEID;
                    }
                }
                candidates_lists.push_back(candidates);
            }
        }

        return true;
    }

    osrm::json::Object submatchingToJSON(const osrm::matching::SubMatching &sub,
                                         const RouteParameters &route_parameters,
                                         const InternalRouteResult &raw_route)
    {
        osrm::json::Object subtrace;

        if (route_parameters.classify)
        {
            subtrace.values["confidence"] = sub.confidence;
        }

        if (route_parameters.geometry)
        {
            DescriptionFactory factory;
            FixedPointCoordinate current_coordinate;
            factory.SetStartSegment(raw_route.segment_end_coordinates.front().source_phantom,
                                    raw_route.source_traversed_in_reverse.front());
            for (const auto i :
                 osrm::irange<std::size_t>(0, raw_route.unpacked_path_segments.size()))
            {
                for (const PathData &path_data : raw_route.unpacked_path_segments[i])
                {
                    current_coordinate = facade->GetCoordinateOfNode(path_data.node);
                    factory.AppendSegment(current_coordinate, path_data);
                }
                factory.SetEndSegment(raw_route.segment_end_coordinates[i].target_phantom,
                                      raw_route.target_traversed_in_reverse[i],
                                      raw_route.is_via_leg(i));
            }
            // we need this because we don't run DP
            for (auto &segment : factory.path_description)
            {
                segment.necessary = true;
            }
            subtrace.values["geometry"] =
                factory.AppendGeometryString(route_parameters.compression);
        }

        subtrace.values["indices"] = osrm::json::make_array(sub.indices);

        osrm::json::Array points;
        for (const auto &node : sub.nodes)
        {
            points.values.emplace_back(
                osrm::json::make_array(node.location.lat / COORDINATE_PRECISION,
                                       node.location.lon / COORDINATE_PRECISION));
        }
        subtrace.values["matched_points"] = points;

        return subtrace;
    }

    int HandleRequest(const RouteParameters &route_parameters,
                      osrm::json::Object &json_result) final
    {
        // check number of parameters
        if (!check_all_coordinates(route_parameters.coordinates))
        {
            return 400;
        }

        std::vector<double> sub_trace_lengths;
        osrm::matching::CandidateLists candidates_lists;
        const auto &input_coords = route_parameters.coordinates;
        const auto &input_timestamps = route_parameters.timestamps;
        if (input_timestamps.size() > 0 && input_coords.size() != input_timestamps.size())
        {
            return 400;
        }

        // enforce maximum number of locations for performance reasons
        if (max_locations_map_matching > 0 &&
            static_cast<int>(input_coords.size()) < max_locations_map_matching)
        {
            return 400;
        }

        const bool found_candidates =
            getCandiates(input_coords, sub_trace_lengths, candidates_lists);
        if (!found_candidates)
        {
            return 400;
        }

        // setup logging if enabled
        if (osrm::json::Logger::get())
            osrm::json::Logger::get()->initialize("matching");

        // call the actual map matching
        osrm::matching::SubMatchingList sub_matchings;
        search_engine_ptr->map_matching(candidates_lists, input_coords, input_timestamps,
                                        route_parameters.matching_beta,
                                        route_parameters.gps_precision, sub_matchings);

        if (sub_matchings.empty())
        {
            return 400;
        }

        osrm::json::Array matchings;
        for (auto &sub : sub_matchings)
        {
            // classify result
            if (route_parameters.classify)
            {
                double trace_length =
                    sub_trace_lengths[sub.indices.back()] - sub_trace_lengths[sub.indices.front()];
                TraceClassification classification =
                    classify(trace_length, sub.length,
                             (sub.indices.back() - sub.indices.front() + 1) - sub.nodes.size());
                if (classification.first == ClassifierT::ClassLabel::POSITIVE)
                {
                    sub.confidence = classification.second;
                }
                else
                {
                    sub.confidence = 1 - classification.second;
                }
            }

            BOOST_ASSERT(sub.nodes.size() > 1);

            // FIXME we only run this to obtain the geometry
            // The clean way would be to get this directly from the map matching plugin
            InternalRouteResult raw_route;
            PhantomNodes current_phantom_node_pair;
            for (unsigned i = 0; i < sub.nodes.size() - 1; ++i)
            {
                current_phantom_node_pair.source_phantom = sub.nodes[i];
                current_phantom_node_pair.target_phantom = sub.nodes[i + 1];
                raw_route.segment_end_coordinates.emplace_back(current_phantom_node_pair);
            }
            search_engine_ptr->shortest_path(
                raw_route.segment_end_coordinates,
                std::vector<bool>(raw_route.segment_end_coordinates.size(), true), raw_route);

            matchings.values.emplace_back(submatchingToJSON(sub, route_parameters, raw_route));
        }

        if (osrm::json::Logger::get())
            osrm::json::Logger::get()->render("matching", json_result);
        json_result.values["matchings"] = matchings;

        return 200;
    }

  private:
    std::string descriptor_string;
    DataFacadeT *facade;
    int max_locations_map_matching;
    ClassifierT classifier;
};

#endif // MATCH_HPP
<commit_msg>Remove second stage classifier: obsolete with trace splitting<commit_after>/*

Copyright (c) 2015, Project OSRM contributors
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.

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 HOLDER 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 MATCH_HPP
#define MATCH_HPP

#include "plugin_base.hpp"

#include "../algorithms/bayes_classifier.hpp"
#include "../algorithms/object_encoder.hpp"
#include "../data_structures/search_engine.hpp"
#include "../descriptors/descriptor_base.hpp"
#include "../descriptors/json_descriptor.hpp"
#include "../routing_algorithms/map_matching.hpp"
#include "../util/compute_angle.hpp"
#include "../util/integer_range.hpp"
#include "../util/json_logger.hpp"
#include "../util/json_util.hpp"
#include "../util/string_util.hpp"

#include <cstdlib>

#include <algorithm>
#include <memory>
#include <string>
#include <vector>

template <class DataFacadeT> class MapMatchingPlugin : public BasePlugin
{
    constexpr static const unsigned max_number_of_candidates = 10;

    std::shared_ptr<SearchEngine<DataFacadeT>> search_engine_ptr;

    using ClassifierT = BayesClassifier<LaplaceDistribution, LaplaceDistribution, double>;
    using TraceClassification = ClassifierT::ClassificationT;

  public:
    MapMatchingPlugin(DataFacadeT *facade, const int max_locations_map_matching)
        : descriptor_string("match"), facade(facade),
          max_locations_map_matching(max_locations_map_matching)
          // the values where derived from fitting a laplace distribution
          // to the values of manually classified traces
          ,
          classifier(LaplaceDistribution(0.0057154021891018675, 0.020294704891166186),
                     LaplaceDistribution(0.11467696742821254, 0.49918444000368756),
                     0.7977883096366508) // valid apriori probability
    {
        search_engine_ptr = std::make_shared<SearchEngine<DataFacadeT>>(facade);
    }

    virtual ~MapMatchingPlugin() {}

    const std::string GetDescriptor() const final { return descriptor_string; }

    TraceClassification
    classify(const float trace_length, const float matched_length, const int removed_points) const
    {
        const double distance_feature = -std::log(trace_length) + std::log(matched_length);

        // matched to the same point
        if (!std::isfinite(distance_feature))
        {
            return std::make_pair(ClassifierT::ClassLabel::NEGATIVE, 1.0);
        }

        const auto label_with_confidence = classifier.classify(distance_feature);

        return label_with_confidence;
    }

    bool getCandiates(const std::vector<FixedPointCoordinate> &input_coords,
                      std::vector<double> &sub_trace_lengths,
                      osrm::matching::CandidateLists &candidates_lists)
    {
        double last_distance =
            coordinate_calculation::great_circle_distance(input_coords[0], input_coords[1]);
        sub_trace_lengths.resize(input_coords.size());
        sub_trace_lengths[0] = 0;
        for (const auto current_coordinate : osrm::irange<std::size_t>(0, input_coords.size()))
        {
            bool allow_uturn = false;
            if (0 < current_coordinate)
            {
                last_distance = coordinate_calculation::great_circle_distance(
                    input_coords[current_coordinate - 1], input_coords[current_coordinate]);
                sub_trace_lengths[current_coordinate] +=
                    sub_trace_lengths[current_coordinate - 1] + last_distance;
            }

            if (input_coords.size() - 1 > current_coordinate && 0 < current_coordinate)
            {
                double turn_angle = ComputeAngle::OfThreeFixedPointCoordinates(
                    input_coords[current_coordinate - 1], input_coords[current_coordinate],
                    input_coords[current_coordinate + 1]);

                // sharp turns indicate a possible uturn
                if (turn_angle <= 90.0 || turn_angle >= 270.0)
                {
                    allow_uturn = true;
                }
            }

            std::vector<std::pair<PhantomNode, double>> candidates;
            if (!facade->IncrementalFindPhantomNodeForCoordinateWithMaxDistance(
                    input_coords[current_coordinate], candidates, last_distance / 2.0, 5,
                    max_number_of_candidates))
            {
                return false;
            }

            if (allow_uturn)
            {
                candidates_lists.push_back(candidates);
            }
            else
            {
                const auto compact_size = candidates.size();
                for (const auto i : osrm::irange<std::size_t>(0, compact_size))
                {
                    // Split edge if it is bidirectional and append reverse direction to end of list
                    if (candidates[i].first.forward_node_id != SPECIAL_NODEID &&
                        candidates[i].first.reverse_node_id != SPECIAL_NODEID)
                    {
                        PhantomNode reverse_node(candidates[i].first);
                        reverse_node.forward_node_id = SPECIAL_NODEID;
                        candidates.push_back(std::make_pair(reverse_node, candidates[i].second));

                        candidates[i].first.reverse_node_id = SPECIAL_NODEID;
                    }
                }
                candidates_lists.push_back(candidates);
            }
        }

        return true;
    }

    osrm::json::Object submatchingToJSON(const osrm::matching::SubMatching &sub,
                                         const RouteParameters &route_parameters,
                                         const InternalRouteResult &raw_route)
    {
        osrm::json::Object subtrace;

        if (route_parameters.classify)
        {
            subtrace.values["confidence"] = sub.confidence;
        }

        if (route_parameters.geometry)
        {
            DescriptionFactory factory;
            FixedPointCoordinate current_coordinate;
            factory.SetStartSegment(raw_route.segment_end_coordinates.front().source_phantom,
                                    raw_route.source_traversed_in_reverse.front());
            for (const auto i :
                 osrm::irange<std::size_t>(0, raw_route.unpacked_path_segments.size()))
            {
                for (const PathData &path_data : raw_route.unpacked_path_segments[i])
                {
                    current_coordinate = facade->GetCoordinateOfNode(path_data.node);
                    factory.AppendSegment(current_coordinate, path_data);
                }
                factory.SetEndSegment(raw_route.segment_end_coordinates[i].target_phantom,
                                      raw_route.target_traversed_in_reverse[i],
                                      raw_route.is_via_leg(i));
            }
            // we need this because we don't run DP
            for (auto &segment : factory.path_description)
            {
                segment.necessary = true;
            }
            subtrace.values["geometry"] =
                factory.AppendGeometryString(route_parameters.compression);
        }

        subtrace.values["indices"] = osrm::json::make_array(sub.indices);

        osrm::json::Array points;
        for (const auto &node : sub.nodes)
        {
            points.values.emplace_back(
                osrm::json::make_array(node.location.lat / COORDINATE_PRECISION,
                                       node.location.lon / COORDINATE_PRECISION));
        }
        subtrace.values["matched_points"] = points;

        return subtrace;
    }

    int HandleRequest(const RouteParameters &route_parameters,
                      osrm::json::Object &json_result) final
    {
        // check number of parameters
        if (!check_all_coordinates(route_parameters.coordinates))
        {
            return 400;
        }

        std::vector<double> sub_trace_lengths;
        osrm::matching::CandidateLists candidates_lists;
        const auto &input_coords = route_parameters.coordinates;
        const auto &input_timestamps = route_parameters.timestamps;
        if (input_timestamps.size() > 0 && input_coords.size() != input_timestamps.size())
        {
            return 400;
        }

        // enforce maximum number of locations for performance reasons
        if (max_locations_map_matching > 0 &&
            static_cast<int>(input_coords.size()) < max_locations_map_matching)
        {
            return 400;
        }

        const bool found_candidates =
            getCandiates(input_coords, sub_trace_lengths, candidates_lists);
        if (!found_candidates)
        {
            return 400;
        }

        // setup logging if enabled
        if (osrm::json::Logger::get())
            osrm::json::Logger::get()->initialize("matching");

        // call the actual map matching
        osrm::matching::SubMatchingList sub_matchings;
        search_engine_ptr->map_matching(candidates_lists, input_coords, input_timestamps,
                                        route_parameters.matching_beta,
                                        route_parameters.gps_precision, sub_matchings);

        if (sub_matchings.empty())
        {
            return 400;
        }

        osrm::json::Array matchings;
        for (auto &sub : sub_matchings)
        {
            // classify result
            if (route_parameters.classify)
            {
                double trace_length =
                    sub_trace_lengths[sub.indices.back()] - sub_trace_lengths[sub.indices.front()];
                TraceClassification classification =
                    classify(trace_length, sub.length,
                             (sub.indices.back() - sub.indices.front() + 1) - sub.nodes.size());
                if (classification.first == ClassifierT::ClassLabel::POSITIVE)
                {
                    sub.confidence = classification.second;
                }
                else
                {
                    sub.confidence = 1 - classification.second;
                }
            }

            BOOST_ASSERT(sub.nodes.size() > 1);

            // FIXME we only run this to obtain the geometry
            // The clean way would be to get this directly from the map matching plugin
            InternalRouteResult raw_route;
            PhantomNodes current_phantom_node_pair;
            for (unsigned i = 0; i < sub.nodes.size() - 1; ++i)
            {
                current_phantom_node_pair.source_phantom = sub.nodes[i];
                current_phantom_node_pair.target_phantom = sub.nodes[i + 1];
                raw_route.segment_end_coordinates.emplace_back(current_phantom_node_pair);
            }
            search_engine_ptr->shortest_path(
                raw_route.segment_end_coordinates,
                std::vector<bool>(raw_route.segment_end_coordinates.size(), true), raw_route);

            matchings.values.emplace_back(submatchingToJSON(sub, route_parameters, raw_route));
        }

        if (osrm::json::Logger::get())
            osrm::json::Logger::get()->render("matching", json_result);
        json_result.values["matchings"] = matchings;

        return 200;
    }

  private:
    std::string descriptor_string;
    DataFacadeT *facade;
    int max_locations_map_matching;
    ClassifierT classifier;
};

#endif // MATCH_HPP
<|endoftext|>


<commit_before><commit_msg>Fixing a null reference exception when deserializing layers with qtree extents enabled<commit_after><|endoftext|>


<commit_before><commit_msg>remove superfluous double computation of layer heights<commit_after><|endoftext|>


<commit_before>// refactor of online2-wav-nnet3-latgen-faster.cc

#include "online2/online-nnet3-decoding.h"
#include "online2/online-nnet2-feature-pipeline.h"
#include "online2/onlinebin-util.h"
#include "online2/online-timing.h"
#include "online2/online-endpoint.h"
#include "fstext/fstext-lib.h"
#include "lat/lattice-functions.h"
#include "lat/word-align-lattice.h"

const int arate = 8000;

void ConfigFeatureInfo(kaldi::OnlineNnet2FeaturePipelineInfo& info,
                       std::string ivector_model_dir) {
    // Configure inline to avoid absolute paths in ".conf" files

    info.feature_type = "mfcc";
    info.use_ivectors = true;

    // ivector_extractor.conf
    ReadKaldiObject(ivector_model_dir + "/final.mat",
                    &info.ivector_extractor_info.lda_mat);
    ReadKaldiObject(ivector_model_dir + "/global_cmvn.stats",
                    &info.ivector_extractor_info.global_cmvn_stats);
    ReadKaldiObject(ivector_model_dir + "/final.dubm",
                    &info.ivector_extractor_info.diag_ubm);
    ReadKaldiObject(ivector_model_dir + "/final.ie",
                    &info.ivector_extractor_info.extractor);

    info.ivector_extractor_info.num_gselect = 5;
    info.ivector_extractor_info.min_post = 0.025;
    info.ivector_extractor_info.posterior_scale = 0.1;
    info.ivector_extractor_info.max_remembered_frames = 1000;
    info.ivector_extractor_info.max_count = 100; // changed from 0.0 (?)

    // XXX: Where do these come from?
    info.ivector_extractor_info.greedy_ivector_extractor = true;
    info.ivector_extractor_info.ivector_period = 10;
    info.ivector_extractor_info.num_cg_iters = 15;
    info.ivector_extractor_info.use_most_recent_ivector = true;

    // splice.conf
    info.ivector_extractor_info.splice_opts.left_context = 3;
    info.ivector_extractor_info.splice_opts.right_context = 3;

    // mfcc.conf
    info.mfcc_opts.frame_opts.samp_freq = arate;
    info.mfcc_opts.use_energy = false;
    info.mfcc_opts.num_ceps = 40;
    info.mfcc_opts.mel_opts.num_bins = 40;
    info.mfcc_opts.mel_opts.low_freq = 40;
    info.mfcc_opts.mel_opts.high_freq = -200;

    info.ivector_extractor_info.Check();
}

void ConfigDecoding(kaldi::OnlineNnet3DecodingConfig& config) {
  config.decodable_opts.acoustic_scale = 1.0; // changed from 0.1?
  config.decoder_opts.lattice_beam = 6.0;
  config.decoder_opts.beam = 15.0;
  config.decoder_opts.max_active = 7000;
}

void ConfigEndpoint(kaldi::OnlineEndpointConfig& config) {
  config.silence_phones = "1:2:3:4:5:6:7:8:9:10:11:12:13:14:15:16:17:18:19:20";
}
void usage() {
  fprintf(stderr, "usage: k3 [nnet_dir hclg_path]\n");
}

int main(int argc, char *argv[]) {
    using namespace kaldi;
    using namespace fst;

    setbuf(stdout, NULL);

    std::string nnet_dir = "exp/tdnn_7b_chain_online";
    std::string graph_dir = nnet_dir + "/graph_pp";
    std::string fst_rxfilename = graph_dir + "/HCLG.fst";

    if(argc == 3) {
      nnet_dir = argv[1];
      fst_rxfilename = argv[2];
    }
    else if(argc != 1) {
      usage();
      return EXIT_FAILURE;
    }

    const std::string ivector_model_dir = nnet_dir + "/ivector_extractor";
    const std::string nnet3_rxfilename = nnet_dir + "/final.mdl";

    const std::string word_syms_rxfilename = graph_dir + "/words.txt";
    const string word_boundary_filename = graph_dir + "/phones/word_boundary.int";
    const string phone_syms_rxfilename = graph_dir + "/phones.txt";

    WordBoundaryInfoNewOpts opts; // use default opts
    WordBoundaryInfo word_boundary_info(opts, word_boundary_filename);

    OnlineNnet2FeaturePipelineInfo feature_info;
    ConfigFeatureInfo(feature_info, ivector_model_dir);
    OnlineNnet3DecodingConfig nnet3_decoding_config;
    ConfigDecoding(nnet3_decoding_config);
    OnlineEndpointConfig endpoint_config;
    ConfigEndpoint(endpoint_config);

    BaseFloat frame_shift = feature_info.FrameShiftInSeconds();

    TransitionModel trans_model;
    nnet3::AmNnetSimple am_nnet;
    {
      bool binary;
      Input ki(nnet3_rxfilename, &binary);
      trans_model.Read(ki.Stream(), binary);
      am_nnet.Read(ki.Stream(), binary);
    }

    fst::Fst<fst::StdArc> *decode_fst = ReadFstKaldi(fst_rxfilename);

    fst::SymbolTable *word_syms =
      fst::SymbolTable::ReadText(word_syms_rxfilename);

    fst::SymbolTable* phone_syms =
      fst::SymbolTable::ReadText(phone_syms_rxfilename);

    OnlineIvectorExtractorAdaptationState adaptation_state(feature_info.ivector_extractor_info);

    OnlineNnet2FeaturePipeline feature_pipeline(feature_info);
    feature_pipeline.SetAdaptationState(adaptation_state);

    OnlineSilenceWeighting silence_weighting(
                                             trans_model,
                                             feature_info.silence_weighting_config);

    SingleUtteranceNnet3Decoder decoder(nnet3_decoding_config,
                                        trans_model,
                                        am_nnet,
                                        *decode_fst,
                                        &feature_pipeline);

  char cmd[1024];

  while(true) {
    // Let the client decide what we should do...
    fgets(cmd, sizeof(cmd), stdin);

    if(strcmp(cmd,"stop\n") == 0) {
      break;
    }
    else if(strcmp(cmd,"reset\n") == 0) {
      feature_pipeline.~OnlineNnet2FeaturePipeline();
      new (&feature_pipeline) OnlineNnet2FeaturePipeline(feature_info);

      decoder.~SingleUtteranceNnet3Decoder();
      new (&decoder) SingleUtteranceNnet3Decoder(nnet3_decoding_config,
                                                 trans_model,
                                                 am_nnet,
                                                 *decode_fst,
                                                 &feature_pipeline);
    }
    else if(strcmp(cmd,"push-chunk\n") == 0) {

      // Get chunk length from python
      int chunk_len;
      fgets(cmd, sizeof(cmd), stdin);
      sscanf(cmd, "%d\n", &chunk_len);

      int16_t audio_chunk[chunk_len];
      Vector<BaseFloat> wave_part = Vector<BaseFloat>(chunk_len);

      fread(&audio_chunk, 2, chunk_len, stdin);

      // We need to copy this into the `wave_part' Vector<BaseFloat> thing.
      // From `gst-audio-source.cc' in gst-kaldi-nnet2
      for (int i = 0; i < chunk_len ; ++i) {
        (wave_part)(i) = static_cast<BaseFloat>(audio_chunk[i]);
      }

      feature_pipeline.AcceptWaveform(arate, wave_part);

      std::vector<std::pair<int32, BaseFloat> > delta_weights;
      if (silence_weighting.Active()) {
        silence_weighting.ComputeCurrentTraceback(decoder.Decoder());
        silence_weighting.GetDeltaWeights(feature_pipeline.NumFramesReady(),
                                          &delta_weights);
        feature_pipeline.UpdateFrameWeights(delta_weights);
      }

      decoder.AdvanceDecoding();

      fprintf(stdout, "ok\n");
    }
    else if(strcmp(cmd, "get-final\n") == 0) {
      feature_pipeline.InputFinished(); // XXX: this is new: what does it do?

      decoder.FinalizeDecoding();

      Lattice final_lat;
      decoder.GetBestPath(true, &final_lat);
      CompactLattice clat;
      ConvertLattice(final_lat, &clat);

      // Compute prons alignment (see: kaldi/latbin/nbest-to-prons.cc)
      CompactLattice aligned_clat;

      std::vector<int32> words, times, lengths;
      std::vector<std::vector<int32> > prons;
      std::vector<std::vector<int32> > phone_lengths;

      WordAlignLattice(clat, trans_model, word_boundary_info,
                       0, &aligned_clat);

      CompactLatticeToWordProns(trans_model, aligned_clat, &words, &times,
                                &lengths, &prons, &phone_lengths);

      for (int i = 0; i < words.size(); i++) {
        if(words[i] == 0) {
          // <eps> links - silence
          continue;
        }
        fprintf(stdout, "word: %s / start: %f / duration: %f\n",
                word_syms->Find(words[i]).c_str(),
                times[i] * frame_shift,
                lengths[i] * frame_shift);
        // Print out the phonemes for this word
        for(size_t j=0; j<phone_lengths[i].size(); j++) {
          fprintf(stdout, "phone: %s / duration: %f\n",
                  phone_syms->Find(prons[i][j]).c_str(),
                  phone_lengths[i][j] * frame_shift);
        }
      }

      fprintf(stdout, "done with words\n");

    }
    else {

      fprintf(stderr, "unknown command %s\n", cmd);

    }
  }
}
<commit_msg>update graph_dir<commit_after>// refactor of online2-wav-nnet3-latgen-faster.cc

#include "online2/online-nnet3-decoding.h"
#include "online2/online-nnet2-feature-pipeline.h"
#include "online2/onlinebin-util.h"
#include "online2/online-timing.h"
#include "online2/online-endpoint.h"
#include "fstext/fstext-lib.h"
#include "lat/lattice-functions.h"
#include "lat/word-align-lattice.h"

const int arate = 8000;

void ConfigFeatureInfo(kaldi::OnlineNnet2FeaturePipelineInfo& info,
                       std::string ivector_model_dir) {
    // Configure inline to avoid absolute paths in ".conf" files

    info.feature_type = "mfcc";
    info.use_ivectors = true;

    // ivector_extractor.conf
    ReadKaldiObject(ivector_model_dir + "/final.mat",
                    &info.ivector_extractor_info.lda_mat);
    ReadKaldiObject(ivector_model_dir + "/global_cmvn.stats",
                    &info.ivector_extractor_info.global_cmvn_stats);
    ReadKaldiObject(ivector_model_dir + "/final.dubm",
                    &info.ivector_extractor_info.diag_ubm);
    ReadKaldiObject(ivector_model_dir + "/final.ie",
                    &info.ivector_extractor_info.extractor);

    info.ivector_extractor_info.num_gselect = 5;
    info.ivector_extractor_info.min_post = 0.025;
    info.ivector_extractor_info.posterior_scale = 0.1;
    info.ivector_extractor_info.max_remembered_frames = 1000;
    info.ivector_extractor_info.max_count = 100; // changed from 0.0 (?)

    // XXX: Where do these come from?
    info.ivector_extractor_info.greedy_ivector_extractor = true;
    info.ivector_extractor_info.ivector_period = 10;
    info.ivector_extractor_info.num_cg_iters = 15;
    info.ivector_extractor_info.use_most_recent_ivector = true;

    // splice.conf
    info.ivector_extractor_info.splice_opts.left_context = 3;
    info.ivector_extractor_info.splice_opts.right_context = 3;

    // mfcc.conf
    info.mfcc_opts.frame_opts.samp_freq = arate;
    info.mfcc_opts.use_energy = false;
    info.mfcc_opts.num_ceps = 40;
    info.mfcc_opts.mel_opts.num_bins = 40;
    info.mfcc_opts.mel_opts.low_freq = 40;
    info.mfcc_opts.mel_opts.high_freq = -200;

    info.ivector_extractor_info.Check();
}

void ConfigDecoding(kaldi::OnlineNnet3DecodingConfig& config) {
  config.decodable_opts.acoustic_scale = 1.0; // changed from 0.1?
  config.decoder_opts.lattice_beam = 6.0;
  config.decoder_opts.beam = 15.0;
  config.decoder_opts.max_active = 7000;
}

void ConfigEndpoint(kaldi::OnlineEndpointConfig& config) {
  config.silence_phones = "1:2:3:4:5:6:7:8:9:10:11:12:13:14:15:16:17:18:19:20";
}
void usage() {
  fprintf(stderr, "usage: k3 [nnet_dir hclg_path]\n");
}

int main(int argc, char *argv[]) {
    using namespace kaldi;
    using namespace fst;

    setbuf(stdout, NULL);

    std::string nnet_dir = "exp/tdnn_7b_chain_online";
    std::string graph_dir = nnet_dir + "/graph_pp";
    std::string fst_rxfilename = graph_dir + "/HCLG.fst";

    if(argc == 3) {
      nnet_dir = argv[1];
      graph_dir = nnet_dir + "/graph_pp";
      fst_rxfilename = argv[2];
    }
    else if(argc != 1) {
      usage();
      return EXIT_FAILURE;
    }

    const std::string ivector_model_dir = nnet_dir + "/ivector_extractor";
    const std::string nnet3_rxfilename = nnet_dir + "/final.mdl";

    const std::string word_syms_rxfilename = graph_dir + "/words.txt";
    const string word_boundary_filename = graph_dir + "/phones/word_boundary.int";
    const string phone_syms_rxfilename = graph_dir + "/phones.txt";

    WordBoundaryInfoNewOpts opts; // use default opts
    WordBoundaryInfo word_boundary_info(opts, word_boundary_filename);

    OnlineNnet2FeaturePipelineInfo feature_info;
    ConfigFeatureInfo(feature_info, ivector_model_dir);
    OnlineNnet3DecodingConfig nnet3_decoding_config;
    ConfigDecoding(nnet3_decoding_config);
    OnlineEndpointConfig endpoint_config;
    ConfigEndpoint(endpoint_config);

    BaseFloat frame_shift = feature_info.FrameShiftInSeconds();

    TransitionModel trans_model;
    nnet3::AmNnetSimple am_nnet;
    {
      bool binary;
      Input ki(nnet3_rxfilename, &binary);
      trans_model.Read(ki.Stream(), binary);
      am_nnet.Read(ki.Stream(), binary);
    }

    fst::Fst<fst::StdArc> *decode_fst = ReadFstKaldi(fst_rxfilename);

    fst::SymbolTable *word_syms =
      fst::SymbolTable::ReadText(word_syms_rxfilename);

    fst::SymbolTable* phone_syms =
      fst::SymbolTable::ReadText(phone_syms_rxfilename);

    OnlineIvectorExtractorAdaptationState adaptation_state(feature_info.ivector_extractor_info);

    OnlineNnet2FeaturePipeline feature_pipeline(feature_info);
    feature_pipeline.SetAdaptationState(adaptation_state);

    OnlineSilenceWeighting silence_weighting(
                                             trans_model,
                                             feature_info.silence_weighting_config);

    SingleUtteranceNnet3Decoder decoder(nnet3_decoding_config,
                                        trans_model,
                                        am_nnet,
                                        *decode_fst,
                                        &feature_pipeline);

  char cmd[1024];

  while(true) {
    // Let the client decide what we should do...
    fgets(cmd, sizeof(cmd), stdin);

    if(strcmp(cmd,"stop\n") == 0) {
      break;
    }
    else if(strcmp(cmd,"reset\n") == 0) {
      feature_pipeline.~OnlineNnet2FeaturePipeline();
      new (&feature_pipeline) OnlineNnet2FeaturePipeline(feature_info);

      decoder.~SingleUtteranceNnet3Decoder();
      new (&decoder) SingleUtteranceNnet3Decoder(nnet3_decoding_config,
                                                 trans_model,
                                                 am_nnet,
                                                 *decode_fst,
                                                 &feature_pipeline);
    }
    else if(strcmp(cmd,"push-chunk\n") == 0) {

      // Get chunk length from python
      int chunk_len;
      fgets(cmd, sizeof(cmd), stdin);
      sscanf(cmd, "%d\n", &chunk_len);

      int16_t audio_chunk[chunk_len];
      Vector<BaseFloat> wave_part = Vector<BaseFloat>(chunk_len);

      fread(&audio_chunk, 2, chunk_len, stdin);

      // We need to copy this into the `wave_part' Vector<BaseFloat> thing.
      // From `gst-audio-source.cc' in gst-kaldi-nnet2
      for (int i = 0; i < chunk_len ; ++i) {
        (wave_part)(i) = static_cast<BaseFloat>(audio_chunk[i]);
      }

      feature_pipeline.AcceptWaveform(arate, wave_part);

      std::vector<std::pair<int32, BaseFloat> > delta_weights;
      if (silence_weighting.Active()) {
        silence_weighting.ComputeCurrentTraceback(decoder.Decoder());
        silence_weighting.GetDeltaWeights(feature_pipeline.NumFramesReady(),
                                          &delta_weights);
        feature_pipeline.UpdateFrameWeights(delta_weights);
      }

      decoder.AdvanceDecoding();

      fprintf(stdout, "ok\n");
    }
    else if(strcmp(cmd, "get-final\n") == 0) {
      feature_pipeline.InputFinished(); // XXX: this is new: what does it do?

      decoder.FinalizeDecoding();

      Lattice final_lat;
      decoder.GetBestPath(true, &final_lat);
      CompactLattice clat;
      ConvertLattice(final_lat, &clat);

      // Compute prons alignment (see: kaldi/latbin/nbest-to-prons.cc)
      CompactLattice aligned_clat;

      std::vector<int32> words, times, lengths;
      std::vector<std::vector<int32> > prons;
      std::vector<std::vector<int32> > phone_lengths;

      WordAlignLattice(clat, trans_model, word_boundary_info,
                       0, &aligned_clat);

      CompactLatticeToWordProns(trans_model, aligned_clat, &words, &times,
                                &lengths, &prons, &phone_lengths);

      for (int i = 0; i < words.size(); i++) {
        if(words[i] == 0) {
          // <eps> links - silence
          continue;
        }
        fprintf(stdout, "word: %s / start: %f / duration: %f\n",
                word_syms->Find(words[i]).c_str(),
                times[i] * frame_shift,
                lengths[i] * frame_shift);
        // Print out the phonemes for this word
        for(size_t j=0; j<phone_lengths[i].size(); j++) {
          fprintf(stdout, "phone: %s / duration: %f\n",
                  phone_syms->Find(prons[i][j]).c_str(),
                  phone_lengths[i][j] * frame_shift);
        }
      }

      fprintf(stdout, "done with words\n");

    }
    else {

      fprintf(stderr, "unknown command %s\n", cmd);

    }
  }
}
<|endoftext|>


<commit_before><commit_msg>matriz<commit_after>#include <iostream>

using std::cin;
using std::cout;
using std::endl;

void crear_llenar(char** matriz);

int main(int argc, char*argv[]){
	int size = 7;
	char** matriz = new char*[size];

	crear_llenar(matriz);

	for (int i = 0; i < size; i++){
		for (int j = 0; j < size; j++){
			cout << matriz[i][j] << "  ";
		}
		cout << endl;
	}

	return 0;
}

void crear_llenar(char** matriz){
	int size = 7;

	//creacion de matriz
	for (int i = 0; i < size; i++){
		matriz[i] = new char[size];
	}

	//llenado prueba
	for (int i = 0; i < size; i++){
		for (int j = 0; j < size; j++){
			if(i == 0 && j == 3){
				matriz[i][j] = '#';
			}else if (i == 3 && j == 0){
				matriz[i][j] = '+';
			}else if (i == 3 && j == 6){
				matriz[i][j] = '+';
			}else if (i == 6 && j == 3){
				matriz[i][j] = '#';
			}else{
				matriz[i][j] = '.';
			}
		}
	}
}
<|endoftext|>


<commit_before><commit_msg>Typo.<commit_after><|endoftext|>