<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: iosys.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: hr $ $Date: 2005-09-29 16:31:38 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _SBIOSYS_HXX
#define _SBIOSYS_HXX

#ifndef _STREAM_HXX //autogen
#include <tools/stream.hxx>
#endif
#ifndef _SBERRORS_HXX
#include "sberrors.hxx"
#endif

class SvStream;

// Zur Zeit sind globale Dateien (Kanalnummern 256 bis 511)
// nicht implementiert.

#define CHANNELS 256
#define CONSOLE  0

#define SBSTRM_INPUT    0x0001      // Input
#define SBSTRM_OUTPUT   0x0002      // Output
#define SBSTRM_RANDOM   0x0004      // Random
#define SBSTRM_APPEND   0x0008      // Append
#define SBSTRM_BINARY   0x0010      // Binary

class SbiStream {
    SvStream* pStrm;                // der Stream
    ULONG  nExpandOnWriteTo;        // bei Schreibzugriff, den Stream
                                    // bis zu dieser Groesse aufblasen
    ByteString aLine;               // aktuelle Zeile
    ULONG  nLine;                   // aktuelle Zeilennummer
    short  nLen;                    // Pufferlaenge
    short  nMode;                   // Bits:
    short  nChan;                   // aktueller Kanal
    SbError nError;                 // letzter Fehlercode
    void   MapError();              // Fehlercode mappen

public:
    SbiStream();
   ~SbiStream();
    SbError Open( short, const ByteString&, short, short, short );
    SbError Close();
    SbError Read( ByteString&, USHORT = 0, bool bForceReadingPerByte=false );
    SbError Read( char& );
    SbError Write( const ByteString&, USHORT = 0 );

    BOOL IsText() const     { return !(nMode & SBSTRM_BINARY);  }
    BOOL IsRandom() const   { return  (nMode & SBSTRM_RANDOM);  }
    BOOL IsBinary() const   { return  (nMode & SBSTRM_BINARY);  }
    BOOL IsSeq() const      { return !(nMode & SBSTRM_RANDOM);  }
    BOOL IsAppend() const   { return  (nMode & SBSTRM_APPEND);  }
    short GetBlockLen() const          { return nLen;           }
    short GetMode() const              { return nMode;          }
    ULONG GetLine() const              { return nLine;          }
    void SetExpandOnWriteTo( ULONG n ) { nExpandOnWriteTo = n;  }
    void ExpandFile();
    SvStream* GetStrm()                { return pStrm;          }
};

class SbiIoSystem {
    SbiStream* pChan[ CHANNELS ];
    ByteString  aPrompt;            // Input-Prompt
    ByteString  aIn, aOut;          // Console-Buffer
    short     nChan;                // aktueller Kanal
    SbError   nError;               // letzter Fehlercode
    void      ReadCon( ByteString& );
    void      WriteCon( const ByteString& );
public:
    SbiIoSystem();
   ~SbiIoSystem();
    SbError GetError();
    void  Shutdown();
    void  SetPrompt( const ByteString& r ) { aPrompt = r; }
    void  SetChannel( short n  )       { nChan = n;   }
    short GetChannel() const           { return nChan;}
    void  ResetChannel()               { nChan = 0;   }
    void  Open( short, const ByteString&, short, short, short );
    void  Close();
    void  Read( ByteString&, short = 0 );
    char  Read();
    void  Write( const ByteString&, short = 0 );
    short NextChannel();
    // 0 == bad channel or no SvStream (nChannel=0..CHANNELS-1)
    SbiStream* GetStream( short nChannel ) const;
    void  CloseAll(); // JSM
};

#endif

<commit_msg>INTEGRATION: CWS sb59 (1.5.114); FILE MERGED 2006/08/11 15:04:28 sb 1.5.114.1: #i67487# Made code warning-free (wntmsci10).<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: iosys.hxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: obo $ $Date: 2006-10-12 14:28:26 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _SBIOSYS_HXX
#define _SBIOSYS_HXX

#ifndef _STREAM_HXX //autogen
#include <tools/stream.hxx>
#endif
#ifndef _SBERRORS_HXX
#include "sberrors.hxx"
#endif

class SvStream;

// Zur Zeit sind globale Dateien (Kanalnummern 256 bis 511)
// nicht implementiert.

#define CHANNELS 256
#define CONSOLE  0

#define SBSTRM_INPUT    0x0001      // Input
#define SBSTRM_OUTPUT   0x0002      // Output
#define SBSTRM_RANDOM   0x0004      // Random
#define SBSTRM_APPEND   0x0008      // Append
#define SBSTRM_BINARY   0x0010      // Binary

class SbiStream {
    SvStream* pStrm;                // der Stream
    ULONG  nExpandOnWriteTo;        // bei Schreibzugriff, den Stream
                                    // bis zu dieser Groesse aufblasen
    ByteString aLine;               // aktuelle Zeile
    ULONG  nLine;                   // aktuelle Zeilennummer
    short  nLen;                    // Pufferlaenge
    short  nMode;                   // Bits:
    short  nChan;                   // aktueller Kanal
    SbError nError;                 // letzter Fehlercode
    void   MapError();              // Fehlercode mappen

public:
    SbiStream();
   ~SbiStream();
    SbError Open( short, const ByteString&, short, short, short );
    SbError Close();
    SbError Read( ByteString&, USHORT = 0, bool bForceReadingPerByte=false );
    SbError Read( char& );
    SbError Write( const ByteString&, USHORT = 0 );

    bool IsText() const     { return (nMode & SBSTRM_BINARY) == 0; }
    bool IsRandom() const   { return (nMode & SBSTRM_RANDOM) != 0; }
    bool IsBinary() const   { return (nMode & SBSTRM_BINARY) != 0; }
    bool IsSeq() const      { return (nMode & SBSTRM_RANDOM) == 0; }
    bool IsAppend() const   { return (nMode & SBSTRM_APPEND) != 0; }
    short GetBlockLen() const          { return nLen;           }
    short GetMode() const              { return nMode;          }
    ULONG GetLine() const              { return nLine;          }
    void SetExpandOnWriteTo( ULONG n ) { nExpandOnWriteTo = n;  }
    void ExpandFile();
    SvStream* GetStrm()                { return pStrm;          }
};

class SbiIoSystem {
    SbiStream* pChan[ CHANNELS ];
    ByteString  aPrompt;            // Input-Prompt
    ByteString  aIn, aOut;          // Console-Buffer
    short     nChan;                // aktueller Kanal
    SbError   nError;               // letzter Fehlercode
    void      ReadCon( ByteString& );
    void      WriteCon( const ByteString& );
public:
    SbiIoSystem();
   ~SbiIoSystem();
    SbError GetError();
    void  Shutdown();
    void  SetPrompt( const ByteString& r ) { aPrompt = r; }
    void  SetChannel( short n  )       { nChan = n;   }
    short GetChannel() const           { return nChan;}
    void  ResetChannel()               { nChan = 0;   }
    void  Open( short, const ByteString&, short, short, short );
    void  Close();
    void  Read( ByteString&, short = 0 );
    char  Read();
    void  Write( const ByteString&, short = 0 );
    short NextChannel();
    // 0 == bad channel or no SvStream (nChannel=0..CHANNELS-1)
    SbiStream* GetStream( short nChannel ) const;
    void  CloseAll(); // JSM
};

#endif

<|endoftext|>


<commit_before>//
// Copyright (C) 2013
// Alessio Sclocco <a.sclocco@vu.nl>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//

#include <iostream>
#include <string>
#include <vector>
#include <exception>
#include <fstream>
#include <iomanip>
#include <limits>
#include <cmath>
using std::cout;
using std::cerr;
using std::endl;
using std::string;
using std::vector;
using std::exception;
using std::ofstream;
using std::fixed;
using std::setprecision;
using std::numeric_limits;

#include <ArgumentList.hpp>
using isa::utils::ArgumentList;
#include <Observation.hpp>
using AstroData::Observation;
#include <InitializeOpenCL.hpp>
using isa::OpenCL::initializeOpenCL;
#include <CLData.hpp>
using isa::OpenCL::CLData;
#include <utils.hpp>
using isa::utils::toStringValue;
using isa::utils::pad;
#include <Timer.hpp>
using isa::utils::Timer;
#include <Transpose.hpp>
using isa::OpenCL::Transpose;

typedef float dataType;
const string typeName("float");
const unsigned int maxThreadsPerBlock = 1024;
const unsigned int padding = 32;

int main(int argc, char * argv[]) {
	unsigned int lowerNrThreads = 0;
	unsigned int nrIterations = 0;
	unsigned int clPlatformID = 0;
	unsigned int clDeviceID = 0;
	unsigned int M = 0;
	unsigned int N = 0;
	CLData< dataType > * inputData = new CLData< dataType >("InputData", true);
	CLData< dataType > * transposedData = new CLData<dataType >("TranposedData", true);

	try {
		ArgumentList args(argc, argv);

		clPlatformID = args.getSwitchArgument< unsigned int >("-opencl_platform");
		clDeviceID = args.getSwitchArgument< unsigned int >("-opencl_device");
		nrIterations = args.getSwitchArgument< unsigned int >("-iterations");
		lowerNrThreads = args.getSwitchArgument< unsigned int >("-lnt");
		M = args.getSwitchArgument< unsigned int >("-M");
		N = args.getSwitchArgument< unsigned int >("-N");
	} catch ( exception & err ) {
		cerr << err.what() << endl;
		return 1;
	}

	cl::Context * clContext = new cl::Context();
	vector< cl::Platform > * clPlatforms = new vector< cl::Platform >();
	vector< cl::Device > * clDevices = new vector< cl::Device >();
	vector< vector< cl::CommandQueue > > * clQueues = new vector< vector < cl::CommandQueue > >();

	initializeOpenCL(clPlatformID, 1, clPlatforms, clContext, clDevices, clQueues);

	cout << fixed << endl;
	cout << "# M N nrThreadPerBlock GB/s err time err" << endl << endl;

	// Allocate memory
	inputData->allocateHostData(M * pad(N, padding));
	inputData->blankHostData()
	transposedData->allocateHostData(N * pad(M, padding));
	transposedData->blankHostData();

	inputData->setCLContext(clContext);
	inputData->setCLQueue(&((clQueues->at(clDeviceID)).at(0)));
	transposedData->setCLContext(clContext);
	transposedData->setCLQueue(&((clQueues->at(clDeviceID)).at(0)));

	try {
		inputData->setDeviceReadOnly();
		inputData->allocateDeviceData();
		inputData->copyHostToDevice();
		transposedData->setDeviceWriteOnly();
		transposedData->allocateDeviceData();
		transposedData->copyHostToDevice();
	} catch ( OpenCLError err ) {
		cerr << err.what() << endl;
	}

	// Find the parameters
	vector< unsigned int > configurations;
	for ( unsigned int threadsPerBlock = lowerNrThreads; threadsPerBlock <= maxThreadsPerBlock; threadsPerBlock++ ) {
		if ( M % threadsPerBlock == 0 ) {
			configurations.push_back(threadsPerBlock);
		}
	}

	for ( vector< unsigned int >::const_iterator configuration = configurations.begin(); configuration != configurations.end(); configuration++ ) {
		double Acur = 0.0;
		double Aold = 0.0;
		double Vcur = 0.0;
		double Vold = 0.0;

		try {
			// Generate kernel
			Transpose< dataType > clTranspose("clTranspose", typeName);
			clTranspose.bindOpenCL(clContext, &(clDevices->at(clDeviceID)), &((clQueues->at(clDeviceID)).at(0)));
			clTranspose.setDimensions(M, N);
			clTranspose.setPaddingFactor(padding);
			clTranspose.setNrThreadsPerBlock(*configuration);
			clTranspose.generateCode();

			clTranspose(inputData, transposedData);
			(clTranspose.getTimer()).reset();

			for ( unsigned int iteration = 0; iteration < nrIterations; iteration++ ) {
				clTranspose(inputData, transposedData);

				if ( iteration == 0 ) {
					Acur = clTranspose.getGB() / clTranspose.getTimer().getLastRunTime();
				} else {
					Aold = Acur;
					Vold = Vcur;

					Acur = Aold + (((clTranspose.getGB() / clTranspose.getTimer().getLastRunTime()) - Aold) / (iteration + 1));
					Vcur = Vold + (((clTranspose.getGB() / clTranspose.getTimer().getLastRunTime()) - Aold) * ((clTranspose.getGB() / clTranspose.getTimer().getLastRunTime()) - Acur));
				}
			}
			Vcur = sqrt(Vcur / nrIterations);

			cout << M << " " << N << " " << *configuration << " " << setprecision(3) << Acur << " " << Vcur << " " << setprecision(6) << clTranspose.getTimer().getAverageTime() << " " << clTranspose.getTimer().getStdDev() << endl;
		} catch ( OpenCLError err ) {
			cerr << err.what() << endl;
			continue;
		}
	}

	cout << endl;

	return 0;
}
<commit_msg>Fixing some typos also in tuning. It seems to work fine also on CPUs, but with 4 threads. Probably related to vectorization by the OpenCL compiler.<commit_after>//
// Copyright (C) 2013
// Alessio Sclocco <a.sclocco@vu.nl>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//

#include <iostream>
#include <string>
#include <vector>
#include <exception>
#include <fstream>
#include <iomanip>
#include <limits>
#include <cmath>
using std::cout;
using std::cerr;
using std::endl;
using std::string;
using std::vector;
using std::exception;
using std::ofstream;
using std::fixed;
using std::setprecision;
using std::numeric_limits;

#include <ArgumentList.hpp>
using isa::utils::ArgumentList;
#include <InitializeOpenCL.hpp>
using isa::OpenCL::initializeOpenCL;
#include <CLData.hpp>
using isa::OpenCL::CLData;
#include <utils.hpp>
using isa::utils::toStringValue;
using isa::utils::pad;
#include <Timer.hpp>
using isa::utils::Timer;
#include <Transpose.hpp>
using isa::OpenCL::Transpose;

typedef float dataType;
const string typeName("float");
const unsigned int maxThreadsPerBlock = 1024;
const unsigned int padding = 32;

int main(int argc, char * argv[]) {
	unsigned int lowerNrThreads = 0;
	unsigned int nrIterations = 0;
	unsigned int clPlatformID = 0;
	unsigned int clDeviceID = 0;
	unsigned int M = 0;
	unsigned int N = 0;
	CLData< dataType > * inputData = new CLData< dataType >("InputData", true);
	CLData< dataType > * transposedData = new CLData<dataType >("TranposedData", true);

	try {
		ArgumentList args(argc, argv);

		clPlatformID = args.getSwitchArgument< unsigned int >("-opencl_platform");
		clDeviceID = args.getSwitchArgument< unsigned int >("-opencl_device");
		nrIterations = args.getSwitchArgument< unsigned int >("-iterations");
		lowerNrThreads = args.getSwitchArgument< unsigned int >("-lnt");
		M = args.getSwitchArgument< unsigned int >("-M");
		N = args.getSwitchArgument< unsigned int >("-N");
	} catch ( exception & err ) {
		cerr << err.what() << endl;
		return 1;
	}

	cl::Context * clContext = new cl::Context();
	vector< cl::Platform > * clPlatforms = new vector< cl::Platform >();
	vector< cl::Device > * clDevices = new vector< cl::Device >();
	vector< vector< cl::CommandQueue > > * clQueues = new vector< vector < cl::CommandQueue > >();

	initializeOpenCL(clPlatformID, 1, clPlatforms, clContext, clDevices, clQueues);

	cout << fixed << endl;
	cout << "# M N nrThreadPerBlock GB/s err time err" << endl << endl;

	// Allocate memory
	inputData->allocateHostData(M * pad(N, padding));
	inputData->blankHostData();
	transposedData->allocateHostData(N * pad(M, padding));
	transposedData->blankHostData();

	inputData->setCLContext(clContext);
	inputData->setCLQueue(&((clQueues->at(clDeviceID)).at(0)));
	transposedData->setCLContext(clContext);
	transposedData->setCLQueue(&((clQueues->at(clDeviceID)).at(0)));

	try {
		inputData->setDeviceReadOnly();
		inputData->allocateDeviceData();
		inputData->copyHostToDevice();
		transposedData->setDeviceWriteOnly();
		transposedData->allocateDeviceData();
		transposedData->copyHostToDevice();
	} catch ( OpenCLError err ) {
		cerr << err.what() << endl;
	}

	// Find the parameters
	vector< unsigned int > configurations;
	for ( unsigned int threadsPerBlock = lowerNrThreads; threadsPerBlock <= maxThreadsPerBlock; threadsPerBlock++ ) {
		if ( M % threadsPerBlock == 0 ) {
			configurations.push_back(threadsPerBlock);
		}
	}

	for ( vector< unsigned int >::const_iterator configuration = configurations.begin(); configuration != configurations.end(); configuration++ ) {
		double Acur = 0.0;
		double Aold = 0.0;
		double Vcur = 0.0;
		double Vold = 0.0;

		try {
			// Generate kernel
			Transpose< dataType > clTranspose("clTranspose", typeName);
			clTranspose.bindOpenCL(clContext, &(clDevices->at(clDeviceID)), &((clQueues->at(clDeviceID)).at(0)));
			clTranspose.setDimensions(M, N);
			clTranspose.setPaddingFactor(padding);
			clTranspose.setNrThreadsPerBlock(*configuration);
			clTranspose.generateCode();

			clTranspose(inputData, transposedData);
			(clTranspose.getTimer()).reset();

			for ( unsigned int iteration = 0; iteration < nrIterations; iteration++ ) {
				clTranspose(inputData, transposedData);

				if ( iteration == 0 ) {
					Acur = clTranspose.getGB() / clTranspose.getTimer().getLastRunTime();
				} else {
					Aold = Acur;
					Vold = Vcur;

					Acur = Aold + (((clTranspose.getGB() / clTranspose.getTimer().getLastRunTime()) - Aold) / (iteration + 1));
					Vcur = Vold + (((clTranspose.getGB() / clTranspose.getTimer().getLastRunTime()) - Aold) * ((clTranspose.getGB() / clTranspose.getTimer().getLastRunTime()) - Acur));
				}
			}
			Vcur = sqrt(Vcur / nrIterations);

			cout << M << " " << N << " " << *configuration << " " << setprecision(3) << Acur << " " << Vcur << " " << setprecision(6) << clTranspose.getTimer().getAverageTime() << " " << clTranspose.getTimer().getStdDev() << endl;
		} catch ( OpenCLError err ) {
			cerr << err.what() << endl;
			continue;
		}
	}

	cout << endl;

	return 0;
}
<|endoftext|>


<commit_before>// cpsm - fuzzy path matcher
// Copyright (C) 2015 Jamie Liu
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "matcher.h"

#include <algorithm>
#include <cstdint>
#include <limits>
#include <utility>

#include <boost/range/adaptor/reversed.hpp>

#include "path_util.h"
#include "str_util.h"

namespace cpsm {

Matcher::Matcher(boost::string_ref const query, MatcherOpts opts,
                 StringHandler strings)
    : opts_(std::move(opts)), strings_(std::move(strings)) {
  strings_.decompose(query, query_);
  if (opts_.is_path) {
    // Store the index of the first character after the rightmost path
    // separator in the query. (Store an index rather than an iterator to keep
    // Matcher copyable/moveable.)
    query_key_begin_index_ =
        std::find(query_.crbegin(), query_.crend(), path_separator()).base() -
        query_.cbegin();
    switch (opts_.query_path_mode) {
      case MatcherOpts::QueryPathMode::NORMAL:
        require_full_part_ = false;
        break;
      case MatcherOpts::QueryPathMode::STRICT:
        require_full_part_ = true;
        break;
      case MatcherOpts::QueryPathMode::AUTO:
        require_full_part_ =
            (query.find_first_of(path_separator()) != std::string::npos);
        break;
    }
  } else {
    query_key_begin_index_ = 0;
    require_full_part_ = false;
  }

  // Queries are smartcased (case-sensitive only if any uppercase appears in the
  // query).
  is_case_sensitive_ =
      std::any_of(query_.begin(), query_.end(),
                  [&](char32_t const c) { return strings_.is_uppercase(c); });

  cur_file_parts_ = path_components_of(opts_.cur_file);
}

bool Matcher::match_base(boost::string_ref const item, MatchBase& m,
                         std::vector<char32_t>* const buf,
                         std::vector<char32_t>* const buf2) const {
  m = MatchBase();

  std::vector<char32_t> key_chars_local;
  std::vector<char32_t>& key_chars = buf ? *buf : key_chars_local;
  std::vector<char32_t> temp_chars_local;
  std::vector<char32_t>& temp_chars = buf2 ? *buf2 : temp_chars_local;

  std::vector<boost::string_ref> item_parts;
  if (opts_.is_path) {
    item_parts = path_components_of(item);
  } else {
    item_parts.push_back(item);
  }
  if (!item_parts.empty()) {
    m.unmatched_len = item_parts.back().size();
  }

  if (query_.empty()) {
    match_path(item_parts, m);
    return true;
  }

  // Since for paths (the common case) we prefer rightmost path components, we
  // scan path components right-to-left.
  auto query_it = query_.crbegin();
  auto const query_end = query_.crend();
  auto query_key_begin = query_.cend();
  // Index into item_parts, counting from the right.
  CharCount part_index = 0;
  for (boost::string_ref const item_part :
       boost::adaptors::reverse(item_parts)) {
    if (query_it == query_end) {
      break;
    }

    std::vector<char32_t>& item_part_chars =
        part_index ? temp_chars : key_chars;
    item_part_chars.clear();
    strings_.decompose(item_part, item_part_chars);

    // Since path components are matched right-to-left, query characters must be
    // consumed greedily right-to-left.
    auto query_prev = query_it;
    for (char32_t const c : boost::adaptors::reverse(item_part_chars)) {
      if (match_char(c, *query_it)) {
        ++query_it;
        if (query_it == query_end) {
          break;
        }
      }
    }

    // If strict query path mode is on, the match must have run to a path
    // separator. If not, discard the match.
    if (require_full_part_ &&
        !((query_it == query_end) || (*query_it == path_separator()))) {
      query_it = query_prev;
      continue;
    }

    m.part_index_sum += part_index;
    if (part_index == 0) {
      query_key_begin = query_it.base();
    }
    part_index++;
  }

  // Did all characters match?
  if (query_it != query_end) {
    return false;
  }

  // Fill path match data.
  match_path(item_parts, m);

  // Now do more refined matching on the key (the rightmost path component of
  // the item for a path match, and just the full item otherwise).
  match_key(key_chars, query_key_begin, m);
  return true;
}

void Matcher::match_path(std::vector<boost::string_ref> const& item_parts,
                         MatchBase& m) const {
  if (!opts_.is_path) {
    return;
  }
  m.path_distance = path_distance_between(cur_file_parts_, item_parts);
  if (!cur_file_parts_.empty() && !item_parts.empty()) {
    m.cur_file_prefix_len =
        common_prefix(cur_file_parts_.back(), item_parts.back());
  }
}

void Matcher::match_key(std::vector<char32_t> const& key,
                        std::vector<char32_t>::const_iterator query_key,
                        MatchBase& m) const {
  auto const query_key_end = query_.cend();
  if (query_key == query_key_end) {
    return;
  }
  bool const query_key_at_begin =
      (query_key == (query_.cbegin() + query_key_begin_index_));
  // key can't be empty since [query_key, query_.end()) is non-empty.
  const auto is_word_prefix = [&](std::size_t const i) -> bool {
    if (i == 0) {
      return true;
    }
    if (strings_.is_alphanumeric(key[i]) &&
        !strings_.is_alphanumeric(key[i - 1])) {
      return true;
    }
    if (strings_.is_uppercase(key[i]) && !strings_.is_uppercase(key[i - 1])) {
      return true;
    }
    return false;
  };

  // Attempt two matches. In the first pass, only match word prefixes and
  // non-alphanumeric characters to try and get a word prefix-only match. In
  // the second pass, match greedily.
  for (int pass = 0; pass < 2; pass++) {
    CharCount word_index = 0;
    bool at_word_start = true;
    bool word_matched = false;
    bool is_full_prefix = query_key_at_begin;
    m.prefix_score = std::numeric_limits<CharCount2>::max();
    switch (pass) {
      case 0:
        if (query_key_at_begin) {
          m.prefix_score = 0;
        }
        break;
      case 1:
        if (query_key_at_begin) {
          m.prefix_score = std::numeric_limits<CharCount2>::max() - 1;
        }
        // Need to reset word_prefix_len after failed first pass.
        m.word_prefix_len = 0;
        break;
    }
    for (std::size_t i = 0; i < key.size(); i++) {
      if (is_word_prefix(i)) {
        word_index++;
        at_word_start = true;
        word_matched = false;
      }
      if (pass == 0 && strings_.is_alphanumeric(*query_key) && !at_word_start) {
        is_full_prefix = false;
        continue;
      }
      if (match_char(key[i], *query_key)) {
        if (at_word_start) {
          m.word_prefix_len++;
        }
        if (pass == 0 && query_key_at_begin && !word_matched) {
          m.prefix_score += word_index;
          word_matched = true;
        }
        if (pass == 1 && query_key_at_begin && i == 0) {
          m.prefix_score = std::numeric_limits<CharCount2>::max() - 2;
        }
        ++query_key;
        if (query_key == query_key_end) {
          m.unmatched_len = key.size() - (i + 1);
          if (is_full_prefix) {
            m.prefix_score = 0;
          }
          return;
        }
      } else {
        at_word_start = false;
        is_full_prefix = false;
      }
    }
  }
}

bool Matcher::match_char(char32_t item, char32_t const query) const {
  if (!is_case_sensitive_) {
    // The query must not contain any uppercase letters since otherwise the
    // query would be case-sensitive, so just force all uppercase characters to
    // lowercase.
    if (strings_.is_uppercase(item)) {
      item = strings_.to_lowercase(item);
    }
  }
  return item == query;
}

}  // namespace cpsm
<commit_msg>Fix empty queries preferring current file<commit_after>// cpsm - fuzzy path matcher
// Copyright (C) 2015 Jamie Liu
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "matcher.h"

#include <algorithm>
#include <cstdint>
#include <limits>
#include <utility>

#include <boost/range/adaptor/reversed.hpp>

#include "path_util.h"
#include "str_util.h"

namespace cpsm {

Matcher::Matcher(boost::string_ref const query, MatcherOpts opts,
                 StringHandler strings)
    : opts_(std::move(opts)), strings_(std::move(strings)) {
  strings_.decompose(query, query_);
  if (opts_.is_path) {
    // Store the index of the first character after the rightmost path
    // separator in the query. (Store an index rather than an iterator to keep
    // Matcher copyable/moveable.)
    query_key_begin_index_ =
        std::find(query_.crbegin(), query_.crend(), path_separator()).base() -
        query_.cbegin();
    switch (opts_.query_path_mode) {
      case MatcherOpts::QueryPathMode::NORMAL:
        require_full_part_ = false;
        break;
      case MatcherOpts::QueryPathMode::STRICT:
        require_full_part_ = true;
        break;
      case MatcherOpts::QueryPathMode::AUTO:
        require_full_part_ =
            (query.find_first_of(path_separator()) != std::string::npos);
        break;
    }
  } else {
    query_key_begin_index_ = 0;
    require_full_part_ = false;
  }

  // Queries are smartcased (case-sensitive only if any uppercase appears in the
  // query).
  is_case_sensitive_ =
      std::any_of(query_.begin(), query_.end(),
                  [&](char32_t const c) { return strings_.is_uppercase(c); });

  cur_file_parts_ = path_components_of(opts_.cur_file);
}

bool Matcher::match_base(boost::string_ref const item, MatchBase& m,
                         std::vector<char32_t>* const buf,
                         std::vector<char32_t>* const buf2) const {
  m = MatchBase();

  std::vector<char32_t> key_chars_local;
  std::vector<char32_t>& key_chars = buf ? *buf : key_chars_local;
  std::vector<char32_t> temp_chars_local;
  std::vector<char32_t>& temp_chars = buf2 ? *buf2 : temp_chars_local;

  std::vector<boost::string_ref> item_parts;
  if (opts_.is_path) {
    item_parts = path_components_of(item);
  } else {
    item_parts.push_back(item);
  }
  if (!item_parts.empty()) {
    m.unmatched_len = item_parts.back().size();
  }

  if (query_.empty()) {
    match_path(item_parts, m);
    return true;
  }

  // Since for paths (the common case) we prefer rightmost path components, we
  // scan path components right-to-left.
  auto query_it = query_.crbegin();
  auto const query_end = query_.crend();
  auto query_key_begin = query_.cend();
  // Index into item_parts, counting from the right.
  CharCount part_index = 0;
  for (boost::string_ref const item_part :
       boost::adaptors::reverse(item_parts)) {
    if (query_it == query_end) {
      break;
    }

    std::vector<char32_t>& item_part_chars =
        part_index ? temp_chars : key_chars;
    item_part_chars.clear();
    strings_.decompose(item_part, item_part_chars);

    // Since path components are matched right-to-left, query characters must be
    // consumed greedily right-to-left.
    auto query_prev = query_it;
    for (char32_t const c : boost::adaptors::reverse(item_part_chars)) {
      if (match_char(c, *query_it)) {
        ++query_it;
        if (query_it == query_end) {
          break;
        }
      }
    }

    // If strict query path mode is on, the match must have run to a path
    // separator. If not, discard the match.
    if (require_full_part_ &&
        !((query_it == query_end) || (*query_it == path_separator()))) {
      query_it = query_prev;
      continue;
    }

    m.part_index_sum += part_index;
    if (part_index == 0) {
      query_key_begin = query_it.base();
    }
    part_index++;
  }

  // Did all characters match?
  if (query_it != query_end) {
    return false;
  }

  // Fill path match data.
  match_path(item_parts, m);

  // Now do more refined matching on the key (the rightmost path component of
  // the item for a path match, and just the full item otherwise).
  match_key(key_chars, query_key_begin, m);
  return true;
}

void Matcher::match_path(std::vector<boost::string_ref> const& item_parts,
                         MatchBase& m) const {
  if (!opts_.is_path) {
    return;
  }
  m.path_distance = path_distance_between(cur_file_parts_, item_parts);
  // We don't want to exclude cur_file as a match, but we also don't want it
  // to be the top match, so force cur_file_prefix_len to 0 for cur_file (i.e.
  // if path_distance is 0).
  if (m.path_distance != 0 && !cur_file_parts_.empty() && !item_parts.empty()) {
    m.cur_file_prefix_len =
        common_prefix(cur_file_parts_.back(), item_parts.back());
  }
}

void Matcher::match_key(std::vector<char32_t> const& key,
                        std::vector<char32_t>::const_iterator query_key,
                        MatchBase& m) const {
  auto const query_key_end = query_.cend();
  if (query_key == query_key_end) {
    return;
  }
  bool const query_key_at_begin =
      (query_key == (query_.cbegin() + query_key_begin_index_));
  // key can't be empty since [query_key, query_.end()) is non-empty.
  const auto is_word_prefix = [&](std::size_t const i) -> bool {
    if (i == 0) {
      return true;
    }
    if (strings_.is_alphanumeric(key[i]) &&
        !strings_.is_alphanumeric(key[i - 1])) {
      return true;
    }
    if (strings_.is_uppercase(key[i]) && !strings_.is_uppercase(key[i - 1])) {
      return true;
    }
    return false;
  };

  // Attempt two matches. In the first pass, only match word prefixes and
  // non-alphanumeric characters to try and get a word prefix-only match. In
  // the second pass, match greedily.
  for (int pass = 0; pass < 2; pass++) {
    CharCount word_index = 0;
    bool at_word_start = true;
    bool word_matched = false;
    bool is_full_prefix = query_key_at_begin;
    m.prefix_score = std::numeric_limits<CharCount2>::max();
    switch (pass) {
      case 0:
        if (query_key_at_begin) {
          m.prefix_score = 0;
        }
        break;
      case 1:
        if (query_key_at_begin) {
          m.prefix_score = std::numeric_limits<CharCount2>::max() - 1;
        }
        // Need to reset word_prefix_len after failed first pass.
        m.word_prefix_len = 0;
        break;
    }
    for (std::size_t i = 0; i < key.size(); i++) {
      if (is_word_prefix(i)) {
        word_index++;
        at_word_start = true;
        word_matched = false;
      }
      if (pass == 0 && strings_.is_alphanumeric(*query_key) && !at_word_start) {
        is_full_prefix = false;
        continue;
      }
      if (match_char(key[i], *query_key)) {
        if (at_word_start) {
          m.word_prefix_len++;
        }
        if (pass == 0 && query_key_at_begin && !word_matched) {
          m.prefix_score += word_index;
          word_matched = true;
        }
        if (pass == 1 && query_key_at_begin && i == 0) {
          m.prefix_score = std::numeric_limits<CharCount2>::max() - 2;
        }
        ++query_key;
        if (query_key == query_key_end) {
          m.unmatched_len = key.size() - (i + 1);
          if (is_full_prefix) {
            m.prefix_score = 0;
          }
          return;
        }
      } else {
        at_word_start = false;
        is_full_prefix = false;
      }
    }
  }
}

bool Matcher::match_char(char32_t item, char32_t const query) const {
  if (!is_case_sensitive_) {
    // The query must not contain any uppercase letters since otherwise the
    // query would be case-sensitive, so just force all uppercase characters to
    // lowercase.
    if (strings_.is_uppercase(item)) {
      item = strings_.to_lowercase(item);
    }
  }
  return item == query;
}

}  // namespace cpsm
<|endoftext|>


<commit_before>#include <cstdio>
#include <cstdlib>
#include <cstring>

#include <iomanip>
#include <iostream>
#include <limits>
#include <vector>
#include <sys/resource.h>

#include "hashpack.h"
#include "hashmap.h"

using namespace std;
using namespace rigtorp;

inline uint64_t RDTSC_START() {
    unsigned cyc_high, cyc_low;
    __asm volatile("cpuid\n\t"
                   "rdtsc\n\t"
                   "mov %%edx, %0\n\t"
                   "mov %%eax, %1\n\t"
                   : "=r"(cyc_high), "=r"(cyc_low)::"%rax", "%rbx", "%rcx",
                   "%rdx");
    return ((uint64_t)cyc_high << 32) | cyc_low;
}

inline uint64_t RDTSC_FINAL() {
    unsigned cyc_high, cyc_low;
    __asm volatile("rdtscp\n\t"
                   "mov %%edx, %0\n\t"
                   "mov %%eax, %1\n\t"
                   "cpuid\n\t"
                   : "=r"(cyc_high), "=r"(cyc_low)::"%rax", "%rbx", "%rcx",
                   "%rdx");
    return ((uint64_t)cyc_high << 32) | cyc_low;
}

template <typename ht>
void populate(ht & h, vector<uint64_t> & keys) {
    for(size_t i = 0; i < keys.size(); ++i) {
        h.emplace(keys[i], i);
    }
}

template <typename ht>
size_t  query(ht & h, vector<uint64_t> & keys) {
    size_t sum = 0;
    for(size_t i = 0; i < keys.size(); ++i) {
        auto it = h.find(keys[i]);
        if(it != h.end()) sum+= it->second;
    }
    return sum;
}

template <typename ht>
double query_avg_probed_keys(ht & h, vector<uint64_t> & keys) {
    size_t sum = 0;
    for(size_t i = 0; i < keys.size(); ++i) {
        sum += h.probed_keys(keys[i]);
    }
    return sum * 1.0 / keys.size();
}

const uint64_t EMPTY = 0xFFFFFFFFFFFFFFFF;

template <typename Pack>
void basic(std::vector<uint64_t> & keys,  const float loadfactor, const int repeat) {
    double querycycles = 0;
    double probespercycle = 0;
    size_t howmany = keys.size();
    std::cout << "testing "  << setw(20) << string(Pack::NAME) << " ";
    std::cout.flush();
    for(int r = 0 ; r < repeat; ++r) {

        HashMap<uint64_t, uint32_t, Pack> hm(16, EMPTY, loadfactor);
        uint64_t  cycles_start, cycles_end;
        cycles_start = RDTSC_START();
        populate(hm,keys);
        cycles_end = RDTSC_FINAL();
        cycles_start = RDTSC_START();
        query(hm,keys);
        cycles_end = RDTSC_FINAL();
        querycycles += (cycles_end - cycles_start) * 1.0 / howmany;

        double pk = query_avg_probed_keys(hm,keys);
        probespercycle += pk;
    }
    std::cout << "     " << setw(10) << querycycles / repeat << " cycles per query on average " ;
    std::cout << "     " << setw(10) << probespercycle / repeat << " probes per query on average " ;
    std::cout << std::endl;

}

void demorandom(const uint64_t howmany) {
    srand(0);
    const float loadfactor = 0.9;
    const float repeat = 1000;
    std::vector<uint64_t>  keys;
    for(uint64_t i = 1; i <= howmany; ++i) {
        keys.push_back(get64rand());// formally, we should make sure that the key differs from EMPTY
    }
    std::cout << "populating a hash table with " << howmany << " random 64-bit keys and then retrieving them. " << std::endl;
    std::cout << "load factor = " << loadfactor << std::endl;
    std::cout << "We repeat with " << repeat << " different hash functions, using the same keys." << std::endl;

    basic<Zobrist64Pack>(keys, loadfactor, repeat);

    basic<MultiplyShift64Pack>(keys, loadfactor, repeat);
    basic<ClLinear64Pack>(keys, loadfactor, repeat);
    basic<ThorupZhangCWCubic64Pack>(keys, loadfactor, repeat);

    std::cout << std::endl;

}

void demofixed(const uint64_t howmany) {
    srand(0);
    const float loadfactor = 0.9;
    const float repeat = 1000;
    std::vector<uint64_t>  keys;
    for(uint64_t i = 1; i <= howmany; ++i) {
        keys.push_back(i + UINT64_C(0xFFFFFFFFF));
    }
    std::cout << "populating a hash table with " << howmany << " sequential 64-bit keys and then retrieving them. " << std::endl;
    std::cout << "load factor = " << loadfactor << std::endl;
    std::cout << "We repeat with " << repeat << " different hash functions, using the same keys." << std::endl;

    basic<Zobrist64Pack>(keys, loadfactor, repeat);

    basic<MultiplyShift64Pack>(keys, loadfactor, repeat);
    basic<ClLinear64Pack>(keys, loadfactor, repeat);

    basic<ThorupZhangCWCubic64Pack>(keys, loadfactor, repeat);

    std::cout << std::endl;

}

int main() {
    demorandom(2000);
    demorandom(64000);

    demofixed(2000);
    demofixed(64000);

}
<commit_msg>Extending the benchmark somewhat.<commit_after>#include <cstdio>
#include <cstdlib>
#include <cstring>

#include <iomanip>
#include <iostream>
#include <limits>
#include <vector>
#include <sys/resource.h>

#include "hashpack.h"
#include "hashmap.h"

using namespace std;
using namespace rigtorp;

inline uint64_t RDTSC_START() {
    unsigned cyc_high, cyc_low;
    __asm volatile("cpuid\n\t"
                   "rdtsc\n\t"
                   "mov %%edx, %0\n\t"
                   "mov %%eax, %1\n\t"
                   : "=r"(cyc_high), "=r"(cyc_low)::"%rax", "%rbx", "%rcx",
                   "%rdx");
    return ((uint64_t)cyc_high << 32) | cyc_low;
}

inline uint64_t RDTSC_FINAL() {
    unsigned cyc_high, cyc_low;
    __asm volatile("rdtscp\n\t"
                   "mov %%edx, %0\n\t"
                   "mov %%eax, %1\n\t"
                   "cpuid\n\t"
                   : "=r"(cyc_high), "=r"(cyc_low)::"%rax", "%rbx", "%rcx",
                   "%rdx");
    return ((uint64_t)cyc_high << 32) | cyc_low;
}

template <typename ht>
void populate(ht & h, vector<uint64_t> & keys) {
    for(size_t i = 0; i < keys.size(); ++i) {
        h.emplace(keys[i], i);
    }
}

template <typename ht>
size_t  query(ht & h, vector<uint64_t> & keys) {
    size_t sum = 0;
    for(size_t i = 0; i < keys.size(); ++i) {
        auto it = h.find(keys[i]);
        if(it != h.end()) sum+= it->second;
    }
    return sum;
}

template <typename ht>
double query_avg_probed_keys(ht & h, vector<uint64_t> & keys) {
    size_t sum = 0;
    for(size_t i = 0; i < keys.size(); ++i) {
        sum += h.probed_keys(keys[i]);
    }
    return sum * 1.0 / keys.size();
}

const uint64_t EMPTY = 0xFFFFFFFFFFFFFFFF;

template <typename Pack>
void basic(std::vector<uint64_t> & keys,  const float loadfactor, const int repeat) {
    double querycycles = 0;
    double probespercycle = 0;
    size_t howmany = keys.size();
    std::cout << "testing "  << setw(20) << string(Pack::NAME) << " ";
    std::cout.flush();
    uint64_t sum = 0;
    vector <HashMap<uint64_t, uint32_t, Pack> > collection;
    uint64_t  cycles_start, cycles_end;
    for(int r = 0 ; r < repeat; ++r) {
        HashMap<uint64_t, uint32_t, Pack> hm(16, EMPTY, loadfactor);
        cycles_start = RDTSC_START();
        populate(hm,keys);
        cycles_end = RDTSC_FINAL();
        collection.push_back(hm);
    }
    for(int r = 0 ; r < repeat; ++r) {
        HashMap<uint64_t, uint32_t, Pack> & hm = collection[r];
        cycles_start = RDTSC_START();
        sum += query(hm,keys);
        cycles_end = RDTSC_FINAL();
        querycycles += (cycles_end - cycles_start) * 1.0 / howmany;

        double pk = query_avg_probed_keys(hm,keys);
        probespercycle += pk;
     }
     std::cout << "     " << setw(10) << querycycles / repeat << " cycles per query on average " ;
    std::cout << "     " << setw(10) << probespercycle / repeat << " probes per query on average " ;
    std::cout << " ignore me: " << sum ;
    std::cout << std::endl;

}

void demorandom(const uint64_t howmany) {
    srand(0);
    const float loadfactor = 0.9;
    const float repeat = 1000;
    std::vector<uint64_t>  keys;
    for(uint64_t i = 1; i <= howmany; ++i) {
        keys.push_back(get64rand());// formally, we should make sure that the key differs from EMPTY
    }
    std::cout << "populating a hash table with " << howmany << " random 64-bit keys and then retrieving them. " << std::endl;
    std::cout << "load factor = " << loadfactor << std::endl;
    std::cout << "We repeat with " << repeat << " different hash functions, using the same keys." << std::endl;

    basic<Zobrist64Pack>(keys, loadfactor, repeat);

    basic<MultiplyShift64Pack>(keys, loadfactor, repeat);
    basic<ClLinear64Pack>(keys, loadfactor, repeat);
    basic<ThorupZhangCWCubic64Pack>(keys, loadfactor, repeat);

    std::cout << std::endl;

}

void demofixed(const uint64_t howmany) {
    srand(0);
    const float loadfactor = 0.9;
    const float repeat = 1000;
    std::vector<uint64_t>  keys;
    for(uint64_t i = 1; i <= howmany; ++i) {
        keys.push_back(i + UINT64_C(0xFFFFFFFFF));
    }
    std::cout << "populating a hash table with " << howmany << " sequential 64-bit keys and then retrieving them. " << std::endl;
    std::cout << "load factor = " << loadfactor << std::endl;
    std::cout << "We repeat with " << repeat << " different hash functions, using the same keys." << std::endl;

    basic<Zobrist64Pack>(keys, loadfactor, repeat);

    basic<MultiplyShift64Pack>(keys, loadfactor, repeat);
    basic<ClLinear64Pack>(keys, loadfactor, repeat);

    basic<ThorupZhangCWCubic64Pack>(keys, loadfactor, repeat);

    std::cout << std::endl;

}

int main() {
    demorandom(1000);
    demorandom(2000);
    demorandom(64000);

    demofixed(1000);
    demofixed(2000);
    demofixed(64000);
}
<|endoftext|>


<commit_before>/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
//                           License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistribution's of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistribution's 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.
//
//   * The name of the copyright holders may not 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 Intel Corporation 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.
//
//M*/

#if !defined CUDA_DISABLER

#include "TestHaarCascadeLoader.h"
#include "NCVHaarObjectDetection.hpp"

TestHaarCascadeLoader::TestHaarCascadeLoader(std::string testName_, std::string cascadeName_)
    :
    NCVTestProvider(testName_),
    cascadeName(cascadeName_)
{
}

bool TestHaarCascadeLoader::toString(std::ofstream &strOut)
{
    strOut << "cascadeName=" << cascadeName << std::endl;
    return true;
}

bool TestHaarCascadeLoader::init()
{
    return true;
}

bool TestHaarCascadeLoader::process()
{
    NCVStatus ncvStat;
    bool rcode = false;

    Ncv32u numStages, numNodes, numFeatures;
    Ncv32u numStages_2 = 0, numNodes_2 = 0, numFeatures_2 = 0;

    ncvStat = ncvHaarGetClassifierSize(this->cascadeName, numStages, numNodes, numFeatures);
    ncvAssertReturn(ncvStat == NCV_SUCCESS, false);

    NCVVectorAlloc<HaarStage64> h_HaarStages(*this->allocatorCPU.get(), numStages);
    ncvAssertReturn(h_HaarStages.isMemAllocated(), false);
    NCVVectorAlloc<HaarClassifierNode128> h_HaarNodes(*this->allocatorCPU.get(), numNodes);
    ncvAssertReturn(h_HaarNodes.isMemAllocated(), false);
    NCVVectorAlloc<HaarFeature64> h_HaarFeatures(*this->allocatorCPU.get(), numFeatures);
    ncvAssertReturn(h_HaarFeatures.isMemAllocated(), false);

    NCVVectorAlloc<HaarStage64> h_HaarStages_2(*this->allocatorCPU.get(), numStages);
    ncvAssertReturn(h_HaarStages_2.isMemAllocated(), false);
    NCVVectorAlloc<HaarClassifierNode128> h_HaarNodes_2(*this->allocatorCPU.get(), numNodes);
    ncvAssertReturn(h_HaarNodes_2.isMemAllocated(), false);
    NCVVectorAlloc<HaarFeature64> h_HaarFeatures_2(*this->allocatorCPU.get(), numFeatures);
    ncvAssertReturn(h_HaarFeatures_2.isMemAllocated(), false);

    HaarClassifierCascadeDescriptor haar;
    HaarClassifierCascadeDescriptor haar_2;

    NCV_SET_SKIP_COND(this->allocatorGPU.get()->isCounting());
    NCV_SKIP_COND_BEGIN

    const std::string testNvbinName = "test.nvbin";
    ncvStat = ncvHaarLoadFromFile_host(this->cascadeName, haar, h_HaarStages, h_HaarNodes, h_HaarFeatures);
    ncvAssertReturn(ncvStat == NCV_SUCCESS, false);

    ncvStat = ncvHaarStoreNVBIN_host(testNvbinName, haar, h_HaarStages, h_HaarNodes, h_HaarFeatures);
    ncvAssertReturn(ncvStat == NCV_SUCCESS, false);

    ncvStat = ncvHaarGetClassifierSize(testNvbinName, numStages_2, numNodes_2, numFeatures_2);
    ncvAssertReturn(ncvStat == NCV_SUCCESS, false);

    ncvStat = ncvHaarLoadFromFile_host(testNvbinName, haar_2, h_HaarStages_2, h_HaarNodes_2, h_HaarFeatures_2);
    ncvAssertReturn(ncvStat == NCV_SUCCESS, false);

    NCV_SKIP_COND_END

    //bit-to-bit check
    bool bLoopVirgin = true;

    NCV_SKIP_COND_BEGIN

    if (
    numStages_2 != numStages                                       ||
    numNodes_2 != numNodes                                         ||
    numFeatures_2 != numFeatures                                   ||
    haar.NumStages               != haar_2.NumStages               ||
    haar.NumClassifierRootNodes  != haar_2.NumClassifierRootNodes  ||
    haar.NumClassifierTotalNodes != haar_2.NumClassifierTotalNodes ||
    haar.NumFeatures             != haar_2.NumFeatures             ||
    haar.ClassifierSize.width    != haar_2.ClassifierSize.width    ||
    haar.ClassifierSize.height   != haar_2.ClassifierSize.height   ||
    haar.bNeedsTiltedII          != haar_2.bNeedsTiltedII          ||
    haar.bHasStumpsOnly          != haar_2.bHasStumpsOnly          )
    {
        bLoopVirgin = false;
    }
    if (memcmp(h_HaarStages.ptr(), h_HaarStages_2.ptr(), haar.NumStages * sizeof(HaarStage64)) ||
        memcmp(h_HaarNodes.ptr(), h_HaarNodes_2.ptr(), haar.NumClassifierTotalNodes * sizeof(HaarClassifierNode128)) ||
        memcmp(h_HaarFeatures.ptr(), h_HaarFeatures_2.ptr(), haar.NumFeatures * sizeof(HaarFeature64)) )
    {
        bLoopVirgin = false;
    }
    NCV_SKIP_COND_END

    if (bLoopVirgin)
    {
        rcode = true;
    }

    return rcode;
}

bool TestHaarCascadeLoader::deinit()
{
    return true;
}

#endif /* CUDA_DISABLER */
<commit_msg>gpu test output files moved from cwd to temp folder(cherry picked from commit 49731ad5303a714302ff053aaeb32900845304bf)<commit_after>/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
//                           License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistribution's of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistribution's 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.
//
//   * The name of the copyright holders may not 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 Intel Corporation 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.
//
//M*/

#if !defined CUDA_DISABLER

#include "TestHaarCascadeLoader.h"
#include "NCVHaarObjectDetection.hpp"

TestHaarCascadeLoader::TestHaarCascadeLoader(std::string testName_, std::string cascadeName_)
    :
    NCVTestProvider(testName_),
    cascadeName(cascadeName_)
{
}

bool TestHaarCascadeLoader::toString(std::ofstream &strOut)
{
    strOut << "cascadeName=" << cascadeName << std::endl;
    return true;
}

bool TestHaarCascadeLoader::init()
{
    return true;
}

bool TestHaarCascadeLoader::process()
{
    NCVStatus ncvStat;
    bool rcode = false;

    Ncv32u numStages, numNodes, numFeatures;
    Ncv32u numStages_2 = 0, numNodes_2 = 0, numFeatures_2 = 0;

    ncvStat = ncvHaarGetClassifierSize(this->cascadeName, numStages, numNodes, numFeatures);
    ncvAssertReturn(ncvStat == NCV_SUCCESS, false);

    NCVVectorAlloc<HaarStage64> h_HaarStages(*this->allocatorCPU.get(), numStages);
    ncvAssertReturn(h_HaarStages.isMemAllocated(), false);
    NCVVectorAlloc<HaarClassifierNode128> h_HaarNodes(*this->allocatorCPU.get(), numNodes);
    ncvAssertReturn(h_HaarNodes.isMemAllocated(), false);
    NCVVectorAlloc<HaarFeature64> h_HaarFeatures(*this->allocatorCPU.get(), numFeatures);
    ncvAssertReturn(h_HaarFeatures.isMemAllocated(), false);

    NCVVectorAlloc<HaarStage64> h_HaarStages_2(*this->allocatorCPU.get(), numStages);
    ncvAssertReturn(h_HaarStages_2.isMemAllocated(), false);
    NCVVectorAlloc<HaarClassifierNode128> h_HaarNodes_2(*this->allocatorCPU.get(), numNodes);
    ncvAssertReturn(h_HaarNodes_2.isMemAllocated(), false);
    NCVVectorAlloc<HaarFeature64> h_HaarFeatures_2(*this->allocatorCPU.get(), numFeatures);
    ncvAssertReturn(h_HaarFeatures_2.isMemAllocated(), false);

    HaarClassifierCascadeDescriptor haar;
    HaarClassifierCascadeDescriptor haar_2;

    NCV_SET_SKIP_COND(this->allocatorGPU.get()->isCounting());
    NCV_SKIP_COND_BEGIN

    const std::string testNvbinName = cv::tempfile("test.nvbin");
    ncvStat = ncvHaarLoadFromFile_host(this->cascadeName, haar, h_HaarStages, h_HaarNodes, h_HaarFeatures);
    ncvAssertReturn(ncvStat == NCV_SUCCESS, false);

    ncvStat = ncvHaarStoreNVBIN_host(testNvbinName, haar, h_HaarStages, h_HaarNodes, h_HaarFeatures);
    ncvAssertReturn(ncvStat == NCV_SUCCESS, false);

    ncvStat = ncvHaarGetClassifierSize(testNvbinName, numStages_2, numNodes_2, numFeatures_2);
    ncvAssertReturn(ncvStat == NCV_SUCCESS, false);

    ncvStat = ncvHaarLoadFromFile_host(testNvbinName, haar_2, h_HaarStages_2, h_HaarNodes_2, h_HaarFeatures_2);
    ncvAssertReturn(ncvStat == NCV_SUCCESS, false);

    NCV_SKIP_COND_END

    //bit-to-bit check
    bool bLoopVirgin = true;

    NCV_SKIP_COND_BEGIN

    if (
    numStages_2 != numStages                                       ||
    numNodes_2 != numNodes                                         ||
    numFeatures_2 != numFeatures                                   ||
    haar.NumStages               != haar_2.NumStages               ||
    haar.NumClassifierRootNodes  != haar_2.NumClassifierRootNodes  ||
    haar.NumClassifierTotalNodes != haar_2.NumClassifierTotalNodes ||
    haar.NumFeatures             != haar_2.NumFeatures             ||
    haar.ClassifierSize.width    != haar_2.ClassifierSize.width    ||
    haar.ClassifierSize.height   != haar_2.ClassifierSize.height   ||
    haar.bNeedsTiltedII          != haar_2.bNeedsTiltedII          ||
    haar.bHasStumpsOnly          != haar_2.bHasStumpsOnly          )
    {
        bLoopVirgin = false;
    }
    if (memcmp(h_HaarStages.ptr(), h_HaarStages_2.ptr(), haar.NumStages * sizeof(HaarStage64)) ||
        memcmp(h_HaarNodes.ptr(), h_HaarNodes_2.ptr(), haar.NumClassifierTotalNodes * sizeof(HaarClassifierNode128)) ||
        memcmp(h_HaarFeatures.ptr(), h_HaarFeatures_2.ptr(), haar.NumFeatures * sizeof(HaarFeature64)) )
    {
        bLoopVirgin = false;
    }
    NCV_SKIP_COND_END

    if (bLoopVirgin)
    {
        rcode = true;
    }

    return rcode;
}

bool TestHaarCascadeLoader::deinit()
{
    return true;
}

#endif /* CUDA_DISABLER */
<|endoftext|>


<commit_before>/******************************************************************************
 * Copyright 2017 The Apollo Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/

/**
 * @file reference_line.cc
 **/

#include "modules/planning/reference_line/reference_line.h"

#include <algorithm>
#include <sstream>
#include <string>
#include <utility>
#include <vector>

#include "boost/math/tools/minima.hpp"

#include "modules/common/log.h"
#include "modules/common/math/angle.h"
#include "modules/common/math/linear_interpolation.h"
#include "modules/planning/common/planning_gflags.h"
#include "modules/planning/math/double.h"

namespace apollo {
namespace planning {

using ReferenceMapLine = hdmap::Path;

ReferenceLine::ReferenceLine(
    const std::vector<ReferencePoint>& reference_points)
    : reference_points_(reference_points),
      reference_map_line_(ReferenceMapLine(std::vector<hdmap::MapPathPoint>(
          reference_points.begin(), reference_points.end()))) {}

ReferenceLine::ReferenceLine(
    const std::vector<ReferencePoint>& reference_points,
    const std::vector<hdmap::LaneSegment>& lane_segments,
    const double max_approximation_error)
    : reference_points_(reference_points),
      reference_map_line_(ReferenceMapLine(
          std::vector<hdmap::MapPathPoint>(reference_points.begin(),
                                           reference_points.end()),
          lane_segments, max_approximation_error)) {}

ReferencePoint ReferenceLine::get_reference_point(const double s) const {
  const auto& accumulated_s = reference_map_line_.accumulated_s();
  if (s < accumulated_s.front()) {
    AWARN << "The requested s is nearer than the start point of the reference "
             "line; reference line starts at "
          << accumulated_s.back() << ", requested " << s << ".";
    ReferencePoint ref_point(reference_map_line_.get_smooth_point(s),
                             0.0, 0.0, 0.0, 0.0);
    return ref_point;
  }
  if (s > accumulated_s.back()) {
    AWARN << "The requested s exceeds the reference line; reference line "
             "ends at "
          << accumulated_s.back() << "requested " << s << " .";
    ReferencePoint ref_point(reference_map_line_.get_smooth_point(s),
                             0.0, 0.0, 0.0, 0.0);
    return ref_point;
  }

  auto it_lower =
      std::lower_bound(accumulated_s.begin(), accumulated_s.end(), s);
  if (it_lower == accumulated_s.begin()) {
    return reference_points_.front();
  } else {
    std::uint32_t index =
        static_cast<std::uint32_t>(it_lower - accumulated_s.begin());
    auto p0 = reference_points_[index - 1];
    auto p1 = reference_points_[index];

    auto s0 = accumulated_s[index - 1];
    auto s1 = accumulated_s[index];

    return ReferenceLine::interpolate(p0, s0, p1, s1, s);
  }
}

double ReferenceLine::find_min_distance_point(const ReferencePoint& p0,
                                              const double s0,
                                              const ReferencePoint& p1,
                                              const double s1, const double x,
                                              const double y) {
  auto func_dist_square = [&p0, &p1, &s0, &s1, &x, &y](const double s) {
    auto p = ReferenceLine::interpolate(p0, s0, p1, s1, s);
    double dx = p.x() - x;
    double dy = p.y() - y;
    return dx * dx + dy * dy;
  };

  return ::boost::math::tools::brent_find_minima(func_dist_square, s0, s1, 8)
      .first;
}

ReferencePoint ReferenceLine::get_reference_point(const double x,
                                                  const double y) const {
  CHECK_GE(reference_points_.size(), 0);

  auto func_distance_square = [](const ReferencePoint& point, const double x,
                                 const double y) {
    double dx = point.x() - x;
    double dy = point.y() - y;
    return dx * dx + dy * dy;
  };

  double d_min = func_distance_square(reference_points_.front(), x, y);
  double index_min = 0;

  for (uint32_t i = 1; i < reference_points_.size(); ++i) {
    double d_temp = func_distance_square(reference_points_[i], x, y);
    if (d_temp < d_min) {
      d_min = d_temp;
      index_min = i;
    }
  }

  uint32_t index_start = (index_min == 0 ? index_min : index_min - 1);
  uint32_t index_end =
      (index_min + 1 == reference_points_.size() ? index_min : index_min + 1);

  if (index_start == index_end) {
    return reference_points_[index_start];
  }

  double s0 = reference_map_line_.accumulated_s()[index_start];
  double s1 = reference_map_line_.accumulated_s()[index_end];

  double s = ReferenceLine::find_min_distance_point(
      reference_points_[index_start], s0, reference_points_[index_end], s1, x,
      y);

  return ReferenceLine::interpolate(reference_points_[index_start], s0,
                                    reference_points_[index_end], s1, s);
}

bool ReferenceLine::get_point_in_Cartesian_frame(
    const common::SLPoint& sl_point,
    common::math::Vec2d* const xy_point) const {
  CHECK_NOTNULL(xy_point);
  if (reference_map_line_.num_points() < 2) {
    AERROR << "The reference line has too few points.";
    return false;
  }

  const auto matched_point = get_reference_point(sl_point.s());
  const auto angle = common::math::Angle16::from_rad(matched_point.heading());
  xy_point->set_x(matched_point.x() - common::math::sin(angle) * sl_point.l());
  xy_point->set_y(matched_point.y() + common::math::cos(angle) * sl_point.l());
  return true;
}

bool ReferenceLine::get_point_in_frenet_frame(
    const common::math::Vec2d& xy_point,
    common::SLPoint* const sl_point) const {
  DCHECK_NOTNULL(sl_point);
  double s = 0;
  double l = 0;
  if (!reference_map_line_.get_projection(xy_point, &s, &l)) {
    AERROR << "Can't get nearest point from path.";
    return false;
  }

  if (s > reference_map_line_.accumulated_s().back()) {
    AERROR << "The s of point is bigger than the length of current path. s: "
           << s << ", curr path length: "
           << reference_map_line_.accumulated_s().back() << ".";
    return false;
  }
  sl_point->set_s(s);
  sl_point->set_l(l);
  return true;
}

ReferencePoint ReferenceLine::interpolate(const ReferencePoint& p0,
                                          const double s0,
                                          const ReferencePoint& p1,
                                          const double s1, const double s) {
  ReferencePoint p = p1;
  p.set_x(common::math::lerp(p0.x(), s0, p1.x(), s1, s));
  p.set_y(common::math::lerp(p0.y(), s0, p1.y(), s1, s));
  p.set_heading(common::math::slerp(p0.heading(), s0, p1.heading(), s1, s));
  p.set_kappa(common::math::lerp(p0.kappa(), s0, p1.kappa(), s1, s));
  p.set_dkappa(common::math::lerp(p0.dkappa(), s0, p1.dkappa(), s1, s));

  // lane boundary info, lane info will be the same as the p1.
  return p;
}

const std::vector<ReferencePoint>& ReferenceLine::reference_points() const {
  return reference_points_;
}

const ReferenceMapLine& ReferenceLine::reference_map_line() const {
  return reference_map_line_;
}

double ReferenceLine::get_lane_width(const double s) const {
  // TODO(startcode) : need implement;
  return 4.0;
}

bool ReferenceLine::get_lane_width(const double s, double* const left_width,
                                   double* const right_width) const {
  return reference_map_line_.get_width(s, left_width, right_width);
}

bool ReferenceLine::is_on_road(const common::SLPoint& sl_point) const {
  if (sl_point.s() <= 0 || sl_point.s() > reference_map_line_.length()) {
    return false;
  }
  double left_width = 0.0;
  double right_width = 0.0;

  if (!get_lane_width(sl_point.s(), &left_width, &right_width)) {
    return false;
  }

  if (sl_point.l() <= -right_width || sl_point.l() >= left_width) {
    return false;
  }

  return true;
}

std::string ReferenceLine::DebugString() const {
  std::ostringstream ss;
  ss << "point num:" << reference_points_.size();
  for (int32_t i = 0; i < static_cast<int32_t>(reference_points_.size()) &&
                      i < FLAGS_trajectory_point_num_for_debug;
       ++i) {
    ss << reference_points_[i].DebugString();
  }
  return ss.str();
}

}  // namespace planning
}  // namespace apollo
<commit_msg>added lane_waypoints when empty in planning.<commit_after>/******************************************************************************
 * Copyright 2017 The Apollo Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/

/**
 * @file reference_line.cc
 **/

#include "modules/planning/reference_line/reference_line.h"

#include <algorithm>
#include <sstream>
#include <string>
#include <utility>
#include <vector>

#include "boost/math/tools/minima.hpp"

#include "modules/common/log.h"
#include "modules/common/math/angle.h"
#include "modules/common/math/linear_interpolation.h"
#include "modules/planning/common/planning_gflags.h"
#include "modules/planning/math/double.h"

namespace apollo {
namespace planning {

using ReferenceMapLine = hdmap::Path;

ReferenceLine::ReferenceLine(
    const std::vector<ReferencePoint>& reference_points)
    : reference_points_(reference_points),
      reference_map_line_(ReferenceMapLine(std::vector<hdmap::MapPathPoint>(
          reference_points.begin(), reference_points.end()))) {}

ReferenceLine::ReferenceLine(
    const std::vector<ReferencePoint>& reference_points,
    const std::vector<hdmap::LaneSegment>& lane_segments,
    const double max_approximation_error)
    : reference_points_(reference_points),
      reference_map_line_(ReferenceMapLine(
          std::vector<hdmap::MapPathPoint>(reference_points.begin(),
                                           reference_points.end()),
          lane_segments, max_approximation_error)) {}

ReferencePoint ReferenceLine::get_reference_point(const double s) const {
  const auto& accumulated_s = reference_map_line_.accumulated_s();
  if (s < accumulated_s.front()) {
    AWARN << "The requested s is nearer than the start point of the reference "
             "line; reference line starts at "
          << accumulated_s.back() << ", requested " << s << ".";
    ReferencePoint ref_point(reference_map_line_.get_smooth_point(s), 0.0, 0.0,
                             0.0, 0.0);
    if (ref_point.lane_waypoints().empty()) {
      ref_point.add_lane_waypoints(reference_points_.front().lane_waypoints());
    }
    return ref_point;
  }
  if (s > accumulated_s.back()) {
    AWARN << "The requested s exceeds the reference line; reference line "
             "ends at "
          << accumulated_s.back() << "requested " << s << " .";
    ReferencePoint ref_point(reference_map_line_.get_smooth_point(s), 0.0, 0.0,
                             0.0, 0.0);
    if (ref_point.lane_waypoints().empty()) {
      ref_point.add_lane_waypoints(reference_points_.back().lane_waypoints());
    }
    return ref_point;
  }

  auto it_lower =
      std::lower_bound(accumulated_s.begin(), accumulated_s.end(), s);
  if (it_lower == accumulated_s.begin()) {
    return reference_points_.front();
  } else {
    std::uint32_t index =
        static_cast<std::uint32_t>(it_lower - accumulated_s.begin());
    auto p0 = reference_points_[index - 1];
    auto p1 = reference_points_[index];

    auto s0 = accumulated_s[index - 1];
    auto s1 = accumulated_s[index];

    return ReferenceLine::interpolate(p0, s0, p1, s1, s);
  }
}

double ReferenceLine::find_min_distance_point(const ReferencePoint& p0,
                                              const double s0,
                                              const ReferencePoint& p1,
                                              const double s1, const double x,
                                              const double y) {
  auto func_dist_square = [&p0, &p1, &s0, &s1, &x, &y](const double s) {
    auto p = ReferenceLine::interpolate(p0, s0, p1, s1, s);
    double dx = p.x() - x;
    double dy = p.y() - y;
    return dx * dx + dy * dy;
  };

  return ::boost::math::tools::brent_find_minima(func_dist_square, s0, s1, 8)
      .first;
}

ReferencePoint ReferenceLine::get_reference_point(const double x,
                                                  const double y) const {
  CHECK_GE(reference_points_.size(), 0);

  auto func_distance_square = [](const ReferencePoint& point, const double x,
                                 const double y) {
    double dx = point.x() - x;
    double dy = point.y() - y;
    return dx * dx + dy * dy;
  };

  double d_min = func_distance_square(reference_points_.front(), x, y);
  double index_min = 0;

  for (uint32_t i = 1; i < reference_points_.size(); ++i) {
    double d_temp = func_distance_square(reference_points_[i], x, y);
    if (d_temp < d_min) {
      d_min = d_temp;
      index_min = i;
    }
  }

  uint32_t index_start = (index_min == 0 ? index_min : index_min - 1);
  uint32_t index_end =
      (index_min + 1 == reference_points_.size() ? index_min : index_min + 1);

  if (index_start == index_end) {
    return reference_points_[index_start];
  }

  double s0 = reference_map_line_.accumulated_s()[index_start];
  double s1 = reference_map_line_.accumulated_s()[index_end];

  double s = ReferenceLine::find_min_distance_point(
      reference_points_[index_start], s0, reference_points_[index_end], s1, x,
      y);

  return ReferenceLine::interpolate(reference_points_[index_start], s0,
                                    reference_points_[index_end], s1, s);
}

bool ReferenceLine::get_point_in_Cartesian_frame(
    const common::SLPoint& sl_point,
    common::math::Vec2d* const xy_point) const {
  CHECK_NOTNULL(xy_point);
  if (reference_map_line_.num_points() < 2) {
    AERROR << "The reference line has too few points.";
    return false;
  }

  const auto matched_point = get_reference_point(sl_point.s());
  const auto angle = common::math::Angle16::from_rad(matched_point.heading());
  xy_point->set_x(matched_point.x() - common::math::sin(angle) * sl_point.l());
  xy_point->set_y(matched_point.y() + common::math::cos(angle) * sl_point.l());
  return true;
}

bool ReferenceLine::get_point_in_frenet_frame(
    const common::math::Vec2d& xy_point,
    common::SLPoint* const sl_point) const {
  DCHECK_NOTNULL(sl_point);
  double s = 0;
  double l = 0;
  if (!reference_map_line_.get_projection(xy_point, &s, &l)) {
    AERROR << "Can't get nearest point from path.";
    return false;
  }

  if (s > reference_map_line_.accumulated_s().back()) {
    AERROR << "The s of point is bigger than the length of current path. s: "
           << s << ", curr path length: "
           << reference_map_line_.accumulated_s().back() << ".";
    return false;
  }
  sl_point->set_s(s);
  sl_point->set_l(l);
  return true;
}

ReferencePoint ReferenceLine::interpolate(const ReferencePoint& p0,
                                          const double s0,
                                          const ReferencePoint& p1,
                                          const double s1, const double s) {
  ReferencePoint p = p1;
  p.set_x(common::math::lerp(p0.x(), s0, p1.x(), s1, s));
  p.set_y(common::math::lerp(p0.y(), s0, p1.y(), s1, s));
  p.set_heading(common::math::slerp(p0.heading(), s0, p1.heading(), s1, s));
  p.set_kappa(common::math::lerp(p0.kappa(), s0, p1.kappa(), s1, s));
  p.set_dkappa(common::math::lerp(p0.dkappa(), s0, p1.dkappa(), s1, s));

  // lane boundary info, lane info will be the same as the p1.
  return p;
}

const std::vector<ReferencePoint>& ReferenceLine::reference_points() const {
  return reference_points_;
}

const ReferenceMapLine& ReferenceLine::reference_map_line() const {
  return reference_map_line_;
}

double ReferenceLine::get_lane_width(const double s) const {
  // TODO(startcode) : need implement;
  return 4.0;
}

bool ReferenceLine::get_lane_width(const double s, double* const left_width,
                                   double* const right_width) const {
  return reference_map_line_.get_width(s, left_width, right_width);
}

bool ReferenceLine::is_on_road(const common::SLPoint& sl_point) const {
  if (sl_point.s() <= 0 || sl_point.s() > reference_map_line_.length()) {
    return false;
  }
  double left_width = 0.0;
  double right_width = 0.0;

  if (!get_lane_width(sl_point.s(), &left_width, &right_width)) {
    return false;
  }

  if (sl_point.l() <= -right_width || sl_point.l() >= left_width) {
    return false;
  }

  return true;
}

std::string ReferenceLine::DebugString() const {
  std::ostringstream ss;
  ss << "point num:" << reference_points_.size();
  for (int32_t i = 0; i < static_cast<int32_t>(reference_points_.size()) &&
                      i < FLAGS_trajectory_point_num_for_debug;
       ++i) {
    ss << reference_points_[i].DebugString();
  }
  return ss.str();
}

}  // namespace planning
}  // namespace apollo
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

#include "webrtc/common_types.h"
#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h"
#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h"

namespace webrtc {
namespace {

class RtcpRttStatsTestImpl : public RtcpRttStats {
 public:
  RtcpRttStatsTestImpl() : rtt_ms_(0) {}
  virtual ~RtcpRttStatsTestImpl() {}

  virtual void OnRttUpdate(uint32_t rtt_ms) {
    rtt_ms_ = rtt_ms;
  }
  virtual uint32_t LastProcessedRtt() const {
    return rtt_ms_;
  }
  uint32_t rtt_ms_;
};

class SendTransport : public Transport,
                      public NullRtpData {
 public:
  SendTransport() : rtp_rtcp_impl_(NULL), clock_(NULL), delay_ms_(0) {}

  void SetRtpRtcpModule(ModuleRtpRtcpImpl* rtp_rtcp_impl) {
    rtp_rtcp_impl_ = rtp_rtcp_impl;
  }
  void SimulateNetworkDelay(int delay_ms, SimulatedClock* clock) {
    clock_ = clock;
    delay_ms_ = delay_ms;
  }
  virtual int SendPacket(int /*ch*/, const void* /*data*/, int /*len*/) {
    return -1;
  }
  virtual int SendRTCPPacket(int /*ch*/, const void *data, int len) {
    if (clock_) {
      clock_->AdvanceTimeMilliseconds(delay_ms_);
    }
    EXPECT_TRUE(rtp_rtcp_impl_ != NULL);
    EXPECT_EQ(0, rtp_rtcp_impl_->IncomingRtcpPacket(
        static_cast<const uint8_t*>(data), len));
    return len;
  }
  ModuleRtpRtcpImpl* rtp_rtcp_impl_;
  SimulatedClock* clock_;
  int delay_ms_;
};
}  // namespace

class RtpRtcpImplTest : public ::testing::Test {
 protected:
  RtpRtcpImplTest()
      : clock_(1335900000),
        receive_statistics_(ReceiveStatistics::Create(&clock_)) {
    RtpRtcp::Configuration configuration;
    configuration.id = 0;
    configuration.audio = false;
    configuration.clock = &clock_;
    configuration.outgoing_transport = &transport_;
    configuration.receive_statistics = receive_statistics_.get();
    configuration.rtt_stats = &rtt_stats_;

    rtp_rtcp_impl_.reset(new ModuleRtpRtcpImpl(configuration));
    transport_.SetRtpRtcpModule(rtp_rtcp_impl_.get());
  }

  SimulatedClock clock_;
  scoped_ptr<ReceiveStatistics> receive_statistics_;
  scoped_ptr<ModuleRtpRtcpImpl> rtp_rtcp_impl_;
  SendTransport transport_;
  RtcpRttStatsTestImpl rtt_stats_;
};

TEST_F(RtpRtcpImplTest, Rtt) {
  const uint32_t kSsrc = 0x12345;
  RTPHeader header = {};
  header.timestamp = 1;
  header.sequenceNumber = 123;
  header.ssrc = kSsrc;
  header.headerLength = 12;
  receive_statistics_->IncomingPacket(header, 100, false);

  rtp_rtcp_impl_->SetRemoteSSRC(kSsrc);
  EXPECT_EQ(0, rtp_rtcp_impl_->SetSendingStatus(true));
  EXPECT_EQ(0, rtp_rtcp_impl_->SetRTCPStatus(kRtcpCompound));
  EXPECT_EQ(0, rtp_rtcp_impl_->SetSSRC(kSsrc));

  // A SR should have been sent and received.
  EXPECT_EQ(0, rtp_rtcp_impl_->SendRTCP(kRtcpReport));

  // Send new SR. A response to the last SR should be sent.
  clock_.AdvanceTimeMilliseconds(1000);
  transport_.SimulateNetworkDelay(100, &clock_);
  EXPECT_EQ(0, rtp_rtcp_impl_->SendRTCP(kRtcpReport));

  // Verify RTT.
  uint16_t rtt;
  uint16_t avg_rtt;
  uint16_t min_rtt;
  uint16_t max_rtt;
  EXPECT_EQ(0, rtp_rtcp_impl_->RTT(kSsrc, &rtt, &avg_rtt, &min_rtt, &max_rtt));
  EXPECT_EQ(100, rtt);
  EXPECT_EQ(100, avg_rtt);
  EXPECT_EQ(100, min_rtt);
  EXPECT_EQ(100, max_rtt);

  // No RTT from other ssrc.
  EXPECT_EQ(-1,
      rtp_rtcp_impl_->RTT(kSsrc + 1, &rtt, &avg_rtt, &min_rtt, &max_rtt));

  // Verify RTT from rtt_stats config.
  EXPECT_EQ(0U, rtt_stats_.LastProcessedRtt());
  EXPECT_EQ(0U, rtp_rtcp_impl_->rtt_ms());
  rtp_rtcp_impl_->Process();
  EXPECT_EQ(100U, rtt_stats_.LastProcessedRtt());
  EXPECT_EQ(100U, rtp_rtcp_impl_->rtt_ms());
}

TEST_F(RtpRtcpImplTest, SetRtcpXrRrtrStatus) {
  EXPECT_FALSE(rtp_rtcp_impl_->RtcpXrRrtrStatus());
  rtp_rtcp_impl_->SetRtcpXrRrtrStatus(true);
  EXPECT_TRUE(rtp_rtcp_impl_->RtcpXrRrtrStatus());
}

TEST_F(RtpRtcpImplTest, RttForReceiverOnly) {
  rtp_rtcp_impl_->SetRtcpXrRrtrStatus(true);
  EXPECT_EQ(0, rtp_rtcp_impl_->SetSendingStatus(false));
  EXPECT_EQ(0, rtp_rtcp_impl_->SetRTCPStatus(kRtcpCompound));
  EXPECT_EQ(0, rtp_rtcp_impl_->SetSSRC(0x12345));

  // A Receiver time reference report (RTRR) should be sent and received.
  EXPECT_EQ(0, rtp_rtcp_impl_->SendRTCP(kRtcpReport));

  // Send new RTRR. A response to the last RTRR should be sent.
  clock_.AdvanceTimeMilliseconds(1000);
  transport_.SimulateNetworkDelay(100, &clock_);
  EXPECT_EQ(0, rtp_rtcp_impl_->SendRTCP(kRtcpReport));

  // Verify RTT.
  EXPECT_EQ(0U, rtt_stats_.LastProcessedRtt());
  EXPECT_EQ(0U, rtp_rtcp_impl_->rtt_ms());
  rtp_rtcp_impl_->Process();
  EXPECT_EQ(100U, rtt_stats_.LastProcessedRtt());
  EXPECT_EQ(100U, rtp_rtcp_impl_->rtt_ms());
}

}  // namespace webrtc
<commit_msg>Remove loopback setup in RtpRtcpImplTest. Changed to use two separate rtp/rtcp modules.<commit_after>/*
 *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

#include "webrtc/common_types.h"
#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h"
#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h"

namespace webrtc {
namespace {
const uint32_t kSenderSsrc = 0x12345;
const uint32_t kReceiverSsrc = 0x23456;
const uint32_t kOneWayNetworkDelayMs = 100;

class RtcpRttStatsTestImpl : public RtcpRttStats {
 public:
  RtcpRttStatsTestImpl() : rtt_ms_(0) {}
  virtual ~RtcpRttStatsTestImpl() {}

  virtual void OnRttUpdate(uint32_t rtt_ms) {
    rtt_ms_ = rtt_ms;
  }
  virtual uint32_t LastProcessedRtt() const {
    return rtt_ms_;
  }
  uint32_t rtt_ms_;
};

class SendTransport : public Transport,
                      public NullRtpData {
 public:
  SendTransport() : receiver_(NULL), clock_(NULL), delay_ms_(0) {}

  void SetRtpRtcpModule(ModuleRtpRtcpImpl* receiver) {
    receiver_ = receiver;
  }
  void SimulateNetworkDelay(uint32_t delay_ms, SimulatedClock* clock) {
    clock_ = clock;
    delay_ms_ = delay_ms;
  }
  virtual int SendPacket(int /*ch*/, const void* /*data*/, int /*len*/) {
    return -1;
  }
  virtual int SendRTCPPacket(int /*ch*/, const void *data, int len) {
    if (clock_) {
      clock_->AdvanceTimeMilliseconds(delay_ms_);
    }
    EXPECT_TRUE(receiver_ != NULL);
    EXPECT_EQ(0, receiver_->IncomingRtcpPacket(
        static_cast<const uint8_t*>(data), len));
    return len;
  }
  ModuleRtpRtcpImpl* receiver_;
  SimulatedClock* clock_;
  uint32_t delay_ms_;
};

class RtpRtcpModule {
 public:
  RtpRtcpModule(SimulatedClock* clock)
      : receive_statistics_(ReceiveStatistics::Create(clock)) {
    RtpRtcp::Configuration config;
    config.audio = false;
    config.clock = clock;
    config.outgoing_transport = &transport_;
    config.receive_statistics = receive_statistics_.get();
    config.rtt_stats = &rtt_stats_;

    impl_.reset(new ModuleRtpRtcpImpl(config));
    EXPECT_EQ(0, impl_->SetRTCPStatus(kRtcpCompound));

    transport_.SimulateNetworkDelay(kOneWayNetworkDelayMs, clock);
  }
  scoped_ptr<ReceiveStatistics> receive_statistics_;
  SendTransport transport_;
  RtcpRttStatsTestImpl rtt_stats_;
  scoped_ptr<ModuleRtpRtcpImpl> impl_;
};
}  // namespace

class RtpRtcpImplTest : public ::testing::Test {
 protected:
  RtpRtcpImplTest()
      : clock_(1335900000),
        sender_(&clock_),
        receiver_(&clock_) {
    // Send module.
    EXPECT_EQ(0, sender_.impl_->SetSendingStatus(true));
    EXPECT_EQ(0, sender_.impl_->SetSSRC(kSenderSsrc));
    sender_.impl_->SetRemoteSSRC(kReceiverSsrc);
    // Receive module.
    EXPECT_EQ(0, receiver_.impl_->SetSendingStatus(false));
    EXPECT_EQ(0, receiver_.impl_->SetSSRC(kReceiverSsrc));
    receiver_.impl_->SetRemoteSSRC(kSenderSsrc);
    // Transport settings.
    sender_.transport_.SetRtpRtcpModule(receiver_.impl_.get());
    receiver_.transport_.SetRtpRtcpModule(sender_.impl_.get());
  }
  SimulatedClock clock_;
  RtpRtcpModule sender_;
  RtpRtcpModule receiver_;
};

TEST_F(RtpRtcpImplTest, Rtt) {
  RTPHeader header = {};
  header.timestamp = 1;
  header.sequenceNumber = 123;
  header.ssrc = kSenderSsrc;
  header.headerLength = 12;
  receiver_.receive_statistics_->IncomingPacket(header, 100, false);

  // Sender module should send a SR.
  EXPECT_EQ(0, sender_.impl_->SendRTCP(kRtcpReport));

  // Receiver module should send a RR with a response to the last received SR.
  clock_.AdvanceTimeMilliseconds(1000);
  EXPECT_EQ(0, receiver_.impl_->SendRTCP(kRtcpReport));

  // Verify RTT.
  uint16_t rtt;
  uint16_t avg_rtt;
  uint16_t min_rtt;
  uint16_t max_rtt;
  EXPECT_EQ(0,
      sender_.impl_->RTT(kReceiverSsrc, &rtt, &avg_rtt, &min_rtt, &max_rtt));
  EXPECT_EQ(2 * kOneWayNetworkDelayMs, rtt);
  EXPECT_EQ(2 * kOneWayNetworkDelayMs, avg_rtt);
  EXPECT_EQ(2 * kOneWayNetworkDelayMs, min_rtt);
  EXPECT_EQ(2 * kOneWayNetworkDelayMs, max_rtt);

  // No RTT from other ssrc.
  EXPECT_EQ(-1,
      sender_.impl_->RTT(kReceiverSsrc+1, &rtt, &avg_rtt, &min_rtt, &max_rtt));

  // Verify RTT from rtt_stats config.
  EXPECT_EQ(0U, sender_.rtt_stats_.LastProcessedRtt());
  EXPECT_EQ(0U, sender_.impl_->rtt_ms());
  sender_.impl_->Process();
  EXPECT_EQ(2 * kOneWayNetworkDelayMs, sender_.rtt_stats_.LastProcessedRtt());
  EXPECT_EQ(2 * kOneWayNetworkDelayMs, sender_.impl_->rtt_ms());
}

TEST_F(RtpRtcpImplTest, SetRtcpXrRrtrStatus) {
  EXPECT_FALSE(receiver_.impl_->RtcpXrRrtrStatus());
  receiver_.impl_->SetRtcpXrRrtrStatus(true);
  EXPECT_TRUE(receiver_.impl_->RtcpXrRrtrStatus());
}

TEST_F(RtpRtcpImplTest, RttForReceiverOnly) {
  receiver_.impl_->SetRtcpXrRrtrStatus(true);

  // Receiver module should send a Receiver time reference report (RTRR).
  EXPECT_EQ(0, receiver_.impl_->SendRTCP(kRtcpReport));

  // Sender module should send a response to the last received RTRR (DLRR).
  clock_.AdvanceTimeMilliseconds(1000);
  EXPECT_EQ(0, sender_.impl_->SendRTCP(kRtcpReport));

  // Verify RTT.
  EXPECT_EQ(0U, receiver_.rtt_stats_.LastProcessedRtt());
  EXPECT_EQ(0U, receiver_.impl_->rtt_ms());
  receiver_.impl_->Process();
  EXPECT_EQ(2 * kOneWayNetworkDelayMs, receiver_.rtt_stats_.LastProcessedRtt());
  EXPECT_EQ(2 * kOneWayNetworkDelayMs, receiver_.impl_->rtt_ms());
}
}  // namespace webrtc
<|endoftext|>