<commit_before>/**********************************************************************
 * $Id$
 *
 * GEOS - Geometry Engine Open Source
 * http://geos.refractions.net
 *
 * Copyright (C) 2001-2002 Vivid Solutions Inc.
 * Copyright (C) 2005 Refractions Research Inc.
 *
 * This is free software; you can redistribute and/or modify it under
 * the terms of the GNU Lesser General Public Licence as published
 * by the Free Software Foundation.
 * See the COPYING file for more information.
 *
 **********************************************************************/

#include <sstream>
#include <geos/geomgraphindex.h>

namespace geos {

SweepLineEvent::SweepLineEvent(void* newEdgeSet,double x,SweepLineEvent *newInsertEvent,SweepLineEventOBJ *newObj){
	edgeSet=newEdgeSet;
	xValue=x;
	insertEvent=newInsertEvent;
	eventType=INSERT;
	if(insertEvent!=NULL)
		eventType=DELETE;
	obj=newObj;
	deleteEventIndex=0;
}

SweepLineEvent::~SweepLineEvent(){
	if (eventType==DELETE) {
		delete insertEvent;
		delete obj;
	}
}

bool SweepLineEvent::isInsert() {
	return insertEvent==NULL;
}

bool SweepLineEvent::isDelete() {
	return insertEvent!=NULL;
}

SweepLineEvent* SweepLineEvent::getInsertEvent() {
	return insertEvent;
}

int SweepLineEvent::getDeleteEventIndex() {
	return deleteEventIndex;
}

void SweepLineEvent::setDeleteEventIndex(int newDeleteEventIndex) {
	deleteEventIndex=newDeleteEventIndex;
}

SweepLineEventOBJ* SweepLineEvent::getObject() const {
	return obj;
}

/**
* ProjectionEvents are ordered first by their x-value, and then by their eventType.
* It is important that Insert events are sorted before Delete events, so that
* items whose Insert and Delete events occur at the same x-value will be
* correctly handled.
*/
int SweepLineEvent::compareTo(SweepLineEvent *sle) {
	if (xValue<sle->xValue) return -1;
	if (xValue>sle->xValue) return 1;
	if (eventType<sle->eventType) return -1;
	if (eventType>sle->eventType) return 1;
	return 0;
}

string SweepLineEvent::print() {
	ostringstream s;

	s<<"SweepLineEvent:";
	s<<" xValue="<<xValue<<" deleteEventIndex="<<deleteEventIndex;
	s<<( (eventType==INSERT) ? " INSERT" : " DELETE" );
	s<<endl<<"\tinsertEvent=";
	if (insertEvent) s<<insertEvent->print();
	else s<<"NULL";
	return s.str();
}

bool
SweepLineEventLessThen::operator()(const SweepLineEvent *f,
	const SweepLineEvent *s) const
{
	if (f->xValue<s->xValue) return true;
	if (f->eventType<s->eventType) return true;
	return false;
}

} // namespace geos

/**********************************************************************
 * $Log$
 * Revision 1.4  2005/10/27 14:05:20  strk
 * Added a SweepLineEventLessThen functor to be used by sort algorithm.
 *
 * Revision 1.3  2005/01/28 09:47:51  strk
 * Replaced sprintf uses with ostringstream.
 *
 * Revision 1.2  2004/07/02 13:28:27  strk
 * Fixed all #include lines to reflect headers layout change.
 * Added client application build tips in README.
 *
 * Revision 1.1  2004/04/14 06:04:26  ybychkov
 * "geomgraph/index" committ problem fixed.
 *
 * Revision 1.13  2004/03/19 09:49:29  ybychkov
 * "geomgraph" and "geomgraph/indexl" upgraded to JTS 1.4
 *
 * Revision 1.12  2003/11/07 01:23:42  pramsey
 * Add standard CVS headers licence notices and copyrights to all cpp and h
 * files.
 *
 * Revision 1.11  2003/10/15 15:30:32  strk
 * Declared a SweepLineEventOBJ from which MonotoneChain and
 * SweepLineSegment derive to abstract SweepLineEvent object
 * previously done on void * pointers.
 * No more compiler warnings...
 *
 **********************************************************************/

<commit_msg>Fixed bug in SweepLineEventLessThen functor (didn't conform to strict weak ordering). Note: this was introduced by previous commit.<commit_after>/**********************************************************************
 * $Id$
 *
 * GEOS - Geometry Engine Open Source
 * http://geos.refractions.net
 *
 * Copyright (C) 2001-2002 Vivid Solutions Inc.
 * Copyright (C) 2005 Refractions Research Inc.
 *
 * This is free software; you can redistribute and/or modify it under
 * the terms of the GNU Lesser General Public Licence as published
 * by the Free Software Foundation.
 * See the COPYING file for more information.
 *
 **********************************************************************/

#include <sstream>
#include <geos/geomgraphindex.h>

namespace geos {

SweepLineEvent::SweepLineEvent(void* newEdgeSet,double x,SweepLineEvent *newInsertEvent,SweepLineEventOBJ *newObj){
	edgeSet=newEdgeSet;
	xValue=x;
	insertEvent=newInsertEvent;
	eventType=INSERT;
	if(insertEvent!=NULL)
		eventType=DELETE;
	obj=newObj;
	deleteEventIndex=0;
}

SweepLineEvent::~SweepLineEvent(){
	if (eventType==DELETE) {
		delete insertEvent;
		delete obj;
	}
}

bool SweepLineEvent::isInsert() {
	return insertEvent==NULL;
}

bool SweepLineEvent::isDelete() {
	return insertEvent!=NULL;
}

SweepLineEvent* SweepLineEvent::getInsertEvent() {
	return insertEvent;
}

int SweepLineEvent::getDeleteEventIndex() {
	return deleteEventIndex;
}

void SweepLineEvent::setDeleteEventIndex(int newDeleteEventIndex) {
	deleteEventIndex=newDeleteEventIndex;
}

SweepLineEventOBJ* SweepLineEvent::getObject() const {
	return obj;
}

/**
* ProjectionEvents are ordered first by their x-value, and then by their eventType.
* It is important that Insert events are sorted before Delete events, so that
* items whose Insert and Delete events occur at the same x-value will be
* correctly handled.
*/
int SweepLineEvent::compareTo(SweepLineEvent *sle) {
	if (xValue<sle->xValue) return -1;
	if (xValue>sle->xValue) return 1;
	if (eventType<sle->eventType) return -1;
	if (eventType>sle->eventType) return 1;
	return 0;
}

string SweepLineEvent::print() {
	ostringstream s;

	s<<"SweepLineEvent:";
	s<<" xValue="<<xValue<<" deleteEventIndex="<<deleteEventIndex;
	s<<( (eventType==INSERT) ? " INSERT" : " DELETE" );
	s<<endl<<"\tinsertEvent=";
	if (insertEvent) s<<insertEvent->print();
	else s<<"NULL";
	return s.str();
}

bool
SweepLineEventLessThen::operator()(const SweepLineEvent *f,
	const SweepLineEvent *s) const
{
	if (f->xValue<s->xValue) return true;
        if (f->xValue>s->xValue) return false;
        if (f->eventType<s->eventType) return true;
        return false;
}

} // namespace geos

/**********************************************************************
 * $Log$
 * Revision 1.5  2005/11/04 15:42:52  strk
 * Fixed bug in SweepLineEventLessThen functor
 * (didn't conform to strict weak ordering).
 * Note: this was introduced by previous commit.
 *
 * Revision 1.4  2005/10/27 14:05:20  strk
 * Added a SweepLineEventLessThen functor to be used by sort algorithm.
 *
 * Revision 1.3  2005/01/28 09:47:51  strk
 * Replaced sprintf uses with ostringstream.
 *
 * Revision 1.2  2004/07/02 13:28:27  strk
 * Fixed all #include lines to reflect headers layout change.
 * Added client application build tips in README.
 *
 * Revision 1.1  2004/04/14 06:04:26  ybychkov
 * "geomgraph/index" committ problem fixed.
 *
 * Revision 1.13  2004/03/19 09:49:29  ybychkov
 * "geomgraph" and "geomgraph/indexl" upgraded to JTS 1.4
 *
 * Revision 1.12  2003/11/07 01:23:42  pramsey
 * Add standard CVS headers licence notices and copyrights to all cpp and h
 * files.
 *
 * Revision 1.11  2003/10/15 15:30:32  strk
 * Declared a SweepLineEventOBJ from which MonotoneChain and
 * SweepLineSegment derive to abstract SweepLineEvent object
 * previously done on void * pointers.
 * No more compiler warnings...
 *
 **********************************************************************/

<|endoftext|>


<commit_before>// Copyright (c) 2015 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.

#include <memory>

#include "atom/browser/api/atom_api_user_prefs.h"

#include "atom/common/native_mate_converters/v8_value_converter.h"
#include "atom/common/native_mate_converters/value_converter.h"
#include "base/values.h"
#include "chrome/browser/profiles/profile.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/sync_preferences/pref_service_syncable.h"
#include "content/public/browser/browser_thread.h"
#include "native_mate/object_template_builder.h"

namespace mate {

template<>
struct Converter<const base::DictionaryValue*> {
  static v8::Local<v8::Value> ToV8(
      v8::Isolate* isolate,
      const base::DictionaryValue* val) {
    std::unique_ptr<atom::V8ValueConverter>
        converter(new atom::V8ValueConverter);
    return converter->ToV8Value(val, isolate->GetCurrentContext());
  }
};

template<>
struct Converter<const base::ListValue*> {
  static v8::Local<v8::Value> ToV8(
      v8::Isolate* isolate,
      const base::ListValue* val) {
    std::unique_ptr<atom::V8ValueConverter>
        converter(new atom::V8ValueConverter);
    return converter->ToV8Value(val, isolate->GetCurrentContext());
  }
};

}  // namespace mate

namespace atom {

namespace api {

UserPrefs::UserPrefs(v8::Isolate* isolate,
                 content::BrowserContext* browser_context)
      : browser_context_(browser_context) {
  Init(isolate);
}

UserPrefs::~UserPrefs() {
}

Profile* UserPrefs::profile() {
  return Profile::FromBrowserContext(browser_context_);
}

void UserPrefs::RegisterStringPref(const std::string& path,
    const std::string& default_value, bool overlay) {
  profile()->pref_registry()->RegisterStringPref(path, default_value);
  if (overlay)
    profile()->AddOverlayPref(path);
}

void UserPrefs::RegisterDictionaryPref(const std::string& path,
    const base::DictionaryValue& default_value, bool overlay) {
  std::unique_ptr<base::DictionaryValue> copied(
      default_value.CreateDeepCopy());
  profile()->pref_registry()->
      RegisterDictionaryPref(path, copied.release());
  if (overlay)
    profile()->AddOverlayPref(path);
}

void UserPrefs::RegisterListPref(const std::string& path,
    const base::ListValue& default_value, bool overlay) {
  std::unique_ptr<base::ListValue> copied(
      default_value.CreateDeepCopy());
  profile()->pref_registry()->
      RegisterListPref(path, copied.release());
  if (overlay)
    profile()->AddOverlayPref(path);
}

void UserPrefs::RegisterBooleanPref(const std::string& path,
    bool default_value, bool overlay) {
  profile()->pref_registry()->RegisterBooleanPref(path, default_value);
  if (overlay)
    profile()->AddOverlayPref(path);
}

void UserPrefs::RegisterIntegerPref(const std::string& path,
    int default_value, bool overlay) {
  profile()->pref_registry()->RegisterIntegerPref(path, default_value);
  if (overlay)
    profile()->AddOverlayPref(path);
}

void UserPrefs::RegisterDoublePref(const std::string& path,
    double default_value, bool overlay) {
  profile()->pref_registry()->RegisterDoublePref(path, default_value);
  if (overlay)
    profile()->AddOverlayPref(path);
}

std::string UserPrefs::GetStringPref(const std::string& path) {
  return profile()->GetPrefs()->GetString(path);
}

const base::DictionaryValue* UserPrefs::GetDictionaryPref(
      const std::string& path) {
  return profile()->GetPrefs()->GetDictionary(path);
}

const base::ListValue* UserPrefs::GetListPref(const std::string& path) {
  return profile()->GetPrefs()->GetList(path);
}

bool UserPrefs::GetBooleanPref(const std::string& path) {
  return profile()->GetPrefs()->GetBoolean(path);
}

int UserPrefs::GetIntegerPref(const std::string& path) {
  return profile()->GetPrefs()->GetInteger(path);
}

double UserPrefs::GetDoublePref(const std::string& path) {
  return profile()->GetPrefs()->GetDouble(path);
}

void UserPrefs::SetStringPref(const std::string& path,
    const std::string& value) {
  profile()->GetPrefs()->SetString(path, value);
}

void UserPrefs::SetDictionaryPref(const std::string& path,
    const base::DictionaryValue& value) {
  profile()->GetPrefs()->Set(path, value);
}

void UserPrefs::SetListPref(const std::string& path,
    const base::ListValue& value) {
  profile()->GetPrefs()->Set(path, value);
}

void UserPrefs::SetBooleanPref(const std::string& path,
    bool value) {
  profile()->GetPrefs()->SetBoolean(path, value);
}

void UserPrefs::SetIntegerPref(const std::string& path,
    int value) {
  profile()->GetPrefs()->SetInteger(path, value);
}

void UserPrefs::SetDoublePref(const std::string& path,
    double value) {
  profile()->GetPrefs()->SetDouble(path, value);
}

double UserPrefs::GetDefaultZoomLevel() {
  return profile()->GetZoomLevelPrefs()->GetDefaultZoomLevelPref();
}

void UserPrefs::SetDefaultZoomLevel(double zoom) {
  if (!profile()->IsOffTheRecord())
    profile()->GetZoomLevelPrefs()->SetDefaultZoomLevelPref(zoom);
}

// static
mate::Handle<UserPrefs> UserPrefs::Create(
    v8::Isolate* isolate,
    content::BrowserContext* browser_context) {
  DCHECK(browser_context);
  return mate::CreateHandle(isolate, new UserPrefs(isolate, browser_context));
}

// static
void UserPrefs::BuildPrototype(v8::Isolate* isolate,
                                v8::Local<v8::FunctionTemplate> prototype) {
  prototype->SetClassName(mate::StringToV8(isolate, "UserPrefs"));
  mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
      .SetMethod("registerStringPref", &UserPrefs::RegisterStringPref)
      .SetMethod("registerDictionaryPref", &UserPrefs::RegisterDictionaryPref)
      .SetMethod("registerListPref", &UserPrefs::RegisterListPref)
      .SetMethod("registerBooleanPref", &UserPrefs::RegisterBooleanPref)
      .SetMethod("registerIntegerPref", &UserPrefs::RegisterIntegerPref)
      .SetMethod("registerDoublePref", &UserPrefs::RegisterDoublePref)
      // .SetMethod("registerFilePathPref", &UserPrefs::RegisterFilePathPref)

      .SetMethod("getStringPref", &UserPrefs::GetStringPref)
      .SetMethod("getDictionaryPref", &UserPrefs::GetDictionaryPref)
      .SetMethod("getListPref", &UserPrefs::GetListPref)
      .SetMethod("getBooleanPref", &UserPrefs::GetBooleanPref)
      .SetMethod("getIntegerPref", &UserPrefs::GetIntegerPref)
      .SetMethod("getDoublePref", &UserPrefs::GetDoublePref)
      // .SetMethod("getFilePathPref", &UserPrefs::GetFilePathPref)

      .SetMethod("setStringPref", &UserPrefs::SetStringPref)
      .SetMethod("setDictionaryPref", &UserPrefs::SetDictionaryPref)
      .SetMethod("setListPref", &UserPrefs::SetListPref)
      .SetMethod("setBooleanPref", &UserPrefs::SetBooleanPref)
      .SetMethod("setIntegerPref", &UserPrefs::SetIntegerPref)
      .SetMethod("setDoublePref", &UserPrefs::SetDoublePref)
      // .SetMethod("setFilePathPref", &UserPrefs::SetFilePathPref)

      .SetMethod("getDefaultZoomLevel", &UserPrefs::GetDefaultZoomLevel)
      .SetMethod("setDefaultZoomLevel", &UserPrefs::SetDefaultZoomLevel);
}

}  // namespace api

}  // namespace atom
<commit_msg>Fix RegisterDictionaryPref adn RegisterListPref overload calls<commit_after>// Copyright (c) 2015 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.

#include <memory>

#include "atom/browser/api/atom_api_user_prefs.h"

#include "atom/common/native_mate_converters/v8_value_converter.h"
#include "atom/common/native_mate_converters/value_converter.h"
#include "base/values.h"
#include "chrome/browser/profiles/profile.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/sync_preferences/pref_service_syncable.h"
#include "content/public/browser/browser_thread.h"
#include "native_mate/object_template_builder.h"

namespace mate {

template<>
struct Converter<const base::DictionaryValue*> {
  static v8::Local<v8::Value> ToV8(
      v8::Isolate* isolate,
      const base::DictionaryValue* val) {
    std::unique_ptr<atom::V8ValueConverter>
        converter(new atom::V8ValueConverter);
    return converter->ToV8Value(val, isolate->GetCurrentContext());
  }
};

template<>
struct Converter<const base::ListValue*> {
  static v8::Local<v8::Value> ToV8(
      v8::Isolate* isolate,
      const base::ListValue* val) {
    std::unique_ptr<atom::V8ValueConverter>
        converter(new atom::V8ValueConverter);
    return converter->ToV8Value(val, isolate->GetCurrentContext());
  }
};

}  // namespace mate

namespace atom {

namespace api {

UserPrefs::UserPrefs(v8::Isolate* isolate,
                 content::BrowserContext* browser_context)
      : browser_context_(browser_context) {
  Init(isolate);
}

UserPrefs::~UserPrefs() {
}

Profile* UserPrefs::profile() {
  return Profile::FromBrowserContext(browser_context_);
}

void UserPrefs::RegisterStringPref(const std::string& path,
    const std::string& default_value, bool overlay) {
  profile()->pref_registry()->RegisterStringPref(path, default_value);
  if (overlay)
    profile()->AddOverlayPref(path);
}

void UserPrefs::RegisterDictionaryPref(const std::string& path,
    const base::DictionaryValue& default_value, bool overlay) {
  std::unique_ptr<base::DictionaryValue> copied(
      default_value.CreateDeepCopy());
  profile()->pref_registry()->
      RegisterDictionaryPref(path, std::move(copied));
  if (overlay)
    profile()->AddOverlayPref(path);
}

void UserPrefs::RegisterListPref(const std::string& path,
    const base::ListValue& default_value, bool overlay) {
  std::unique_ptr<base::ListValue> copied(
      default_value.CreateDeepCopy());
  profile()->pref_registry()->
      RegisterListPref(path, std::move(copied));
  if (overlay)
    profile()->AddOverlayPref(path);
}

void UserPrefs::RegisterBooleanPref(const std::string& path,
    bool default_value, bool overlay) {
  profile()->pref_registry()->RegisterBooleanPref(path, default_value);
  if (overlay)
    profile()->AddOverlayPref(path);
}

void UserPrefs::RegisterIntegerPref(const std::string& path,
    int default_value, bool overlay) {
  profile()->pref_registry()->RegisterIntegerPref(path, default_value);
  if (overlay)
    profile()->AddOverlayPref(path);
}

void UserPrefs::RegisterDoublePref(const std::string& path,
    double default_value, bool overlay) {
  profile()->pref_registry()->RegisterDoublePref(path, default_value);
  if (overlay)
    profile()->AddOverlayPref(path);
}

std::string UserPrefs::GetStringPref(const std::string& path) {
  return profile()->GetPrefs()->GetString(path);
}

const base::DictionaryValue* UserPrefs::GetDictionaryPref(
      const std::string& path) {
  return profile()->GetPrefs()->GetDictionary(path);
}

const base::ListValue* UserPrefs::GetListPref(const std::string& path) {
  return profile()->GetPrefs()->GetList(path);
}

bool UserPrefs::GetBooleanPref(const std::string& path) {
  return profile()->GetPrefs()->GetBoolean(path);
}

int UserPrefs::GetIntegerPref(const std::string& path) {
  return profile()->GetPrefs()->GetInteger(path);
}

double UserPrefs::GetDoublePref(const std::string& path) {
  return profile()->GetPrefs()->GetDouble(path);
}

void UserPrefs::SetStringPref(const std::string& path,
    const std::string& value) {
  profile()->GetPrefs()->SetString(path, value);
}

void UserPrefs::SetDictionaryPref(const std::string& path,
    const base::DictionaryValue& value) {
  profile()->GetPrefs()->Set(path, value);
}

void UserPrefs::SetListPref(const std::string& path,
    const base::ListValue& value) {
  profile()->GetPrefs()->Set(path, value);
}

void UserPrefs::SetBooleanPref(const std::string& path,
    bool value) {
  profile()->GetPrefs()->SetBoolean(path, value);
}

void UserPrefs::SetIntegerPref(const std::string& path,
    int value) {
  profile()->GetPrefs()->SetInteger(path, value);
}

void UserPrefs::SetDoublePref(const std::string& path,
    double value) {
  profile()->GetPrefs()->SetDouble(path, value);
}

double UserPrefs::GetDefaultZoomLevel() {
  return profile()->GetZoomLevelPrefs()->GetDefaultZoomLevelPref();
}

void UserPrefs::SetDefaultZoomLevel(double zoom) {
  if (!profile()->IsOffTheRecord())
    profile()->GetZoomLevelPrefs()->SetDefaultZoomLevelPref(zoom);
}

// static
mate::Handle<UserPrefs> UserPrefs::Create(
    v8::Isolate* isolate,
    content::BrowserContext* browser_context) {
  DCHECK(browser_context);
  return mate::CreateHandle(isolate, new UserPrefs(isolate, browser_context));
}

// static
void UserPrefs::BuildPrototype(v8::Isolate* isolate,
                                v8::Local<v8::FunctionTemplate> prototype) {
  prototype->SetClassName(mate::StringToV8(isolate, "UserPrefs"));
  mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
      .SetMethod("registerStringPref", &UserPrefs::RegisterStringPref)
      .SetMethod("registerDictionaryPref", &UserPrefs::RegisterDictionaryPref)
      .SetMethod("registerListPref", &UserPrefs::RegisterListPref)
      .SetMethod("registerBooleanPref", &UserPrefs::RegisterBooleanPref)
      .SetMethod("registerIntegerPref", &UserPrefs::RegisterIntegerPref)
      .SetMethod("registerDoublePref", &UserPrefs::RegisterDoublePref)
      // .SetMethod("registerFilePathPref", &UserPrefs::RegisterFilePathPref)

      .SetMethod("getStringPref", &UserPrefs::GetStringPref)
      .SetMethod("getDictionaryPref", &UserPrefs::GetDictionaryPref)
      .SetMethod("getListPref", &UserPrefs::GetListPref)
      .SetMethod("getBooleanPref", &UserPrefs::GetBooleanPref)
      .SetMethod("getIntegerPref", &UserPrefs::GetIntegerPref)
      .SetMethod("getDoublePref", &UserPrefs::GetDoublePref)
      // .SetMethod("getFilePathPref", &UserPrefs::GetFilePathPref)

      .SetMethod("setStringPref", &UserPrefs::SetStringPref)
      .SetMethod("setDictionaryPref", &UserPrefs::SetDictionaryPref)
      .SetMethod("setListPref", &UserPrefs::SetListPref)
      .SetMethod("setBooleanPref", &UserPrefs::SetBooleanPref)
      .SetMethod("setIntegerPref", &UserPrefs::SetIntegerPref)
      .SetMethod("setDoublePref", &UserPrefs::SetDoublePref)
      // .SetMethod("setFilePathPref", &UserPrefs::SetFilePathPref)

      .SetMethod("getDefaultZoomLevel", &UserPrefs::GetDefaultZoomLevel)
      .SetMethod("setDefaultZoomLevel", &UserPrefs::SetDefaultZoomLevel);
}

}  // namespace api

}  // namespace atom
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: d_token.cxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: vg $ $Date: 2007-09-18 13:49:36 $
 *
 *  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
 *
 ************************************************************************/

#include <precomp.h>
#include <ary_i/d_token.hxx>

// NOT FULLY DEFINED SERVICES
#include <ary_i/disdocum.hxx>

namespace csi
{
namespace dsapi
{

bool
DT_Dsapi::IsWhiteOnly() const
{
    return false;
}

DT_TextToken::~DT_TextToken()
{
}

void
DT_TextToken::DisplayAt( DocumentationDisplay & o_rDisplay ) const
{
    o_rDisplay.Display_TextToken( *this );
}

bool
DT_TextToken::IsWhiteOnly() const
{
    for ( const char * it = sText.c_str();
          static_cast<UINT8>(*it) > 32;
          ++it )
    {
        return false;
    }
    return true;
}

DT_White::~DT_White()
{
}

void
DT_White::DisplayAt( DocumentationDisplay & o_rDisplay ) const
{
    o_rDisplay.Display_White();
}

bool
DT_White::IsWhiteOnly() const
{
    return true;
}

DT_MupType::~DT_MupType()
{
}

void
DT_MupType::DisplayAt( DocumentationDisplay & o_rDisplay ) const
{
    o_rDisplay.Display_MupType( *this );
}

DT_MupMember::~DT_MupMember()
{
}

void
DT_MupMember::DisplayAt( DocumentationDisplay & o_rDisplay ) const
{
    o_rDisplay.Display_MupMember( *this );
}

DT_MupConst::~DT_MupConst()
{
}

void
DT_MupConst::DisplayAt( DocumentationDisplay & o_rDisplay ) const
{
    o_rDisplay.Display_MupConst( *this );
}

DT_Style::~DT_Style()
{
}

void
DT_Style::DisplayAt( DocumentationDisplay & o_rDisplay ) const
{
    o_rDisplay.Display_Style( *this );
}

DT_EOL::~DT_EOL()
{
}

void
DT_EOL::DisplayAt( DocumentationDisplay & o_rDisplay ) const
{
    o_rDisplay.Display_EOL();
}

bool
DT_EOL::IsWhiteOnly() const
{
    return true;
}

DT_StdAtTag::~DT_StdAtTag()
{
}

void
DT_StdAtTag::DisplayAt( DocumentationDisplay & o_rDisplay ) const
{
    o_rDisplay.Display_StdAtTag( *this );
}

DT_SeeAlsoAtTag::~DT_SeeAlsoAtTag()
{
}

void
DT_SeeAlsoAtTag::DisplayAt( DocumentationDisplay & o_rDisplay ) const
{
    o_rDisplay.Display_SeeAlsoAtTag( *this );
}

DT_ParameterAtTag::~DT_ParameterAtTag()
{
}

void
DT_ParameterAtTag::DisplayAt( DocumentationDisplay & o_rDisplay ) const
{
    o_rDisplay.Display_ParameterAtTag( *this );
}

DT_SinceAtTag::~DT_SinceAtTag()
{
}

void
DT_SinceAtTag::DisplayAt( DocumentationDisplay & o_rDisplay ) const
{
    o_rDisplay.Display_SinceAtTag( *this );
}

}   // namespace dsapi
}   // namespace csi
<commit_msg>INTEGRATION: CWS changefileheader (1.6.26); FILE MERGED 2008/03/28 16:01:55 rt 1.6.26.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: d_token.cxx,v $
 * $Revision: 1.7 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#include <precomp.h>
#include <ary_i/d_token.hxx>

// NOT FULLY DEFINED SERVICES
#include <ary_i/disdocum.hxx>

namespace csi
{
namespace dsapi
{

bool
DT_Dsapi::IsWhiteOnly() const
{
    return false;
}

DT_TextToken::~DT_TextToken()
{
}

void
DT_TextToken::DisplayAt( DocumentationDisplay & o_rDisplay ) const
{
    o_rDisplay.Display_TextToken( *this );
}

bool
DT_TextToken::IsWhiteOnly() const
{
    for ( const char * it = sText.c_str();
          static_cast<UINT8>(*it) > 32;
          ++it )
    {
        return false;
    }
    return true;
}

DT_White::~DT_White()
{
}

void
DT_White::DisplayAt( DocumentationDisplay & o_rDisplay ) const
{
    o_rDisplay.Display_White();
}

bool
DT_White::IsWhiteOnly() const
{
    return true;
}

DT_MupType::~DT_MupType()
{
}

void
DT_MupType::DisplayAt( DocumentationDisplay & o_rDisplay ) const
{
    o_rDisplay.Display_MupType( *this );
}

DT_MupMember::~DT_MupMember()
{
}

void
DT_MupMember::DisplayAt( DocumentationDisplay & o_rDisplay ) const
{
    o_rDisplay.Display_MupMember( *this );
}

DT_MupConst::~DT_MupConst()
{
}

void
DT_MupConst::DisplayAt( DocumentationDisplay & o_rDisplay ) const
{
    o_rDisplay.Display_MupConst( *this );
}

DT_Style::~DT_Style()
{
}

void
DT_Style::DisplayAt( DocumentationDisplay & o_rDisplay ) const
{
    o_rDisplay.Display_Style( *this );
}

DT_EOL::~DT_EOL()
{
}

void
DT_EOL::DisplayAt( DocumentationDisplay & o_rDisplay ) const
{
    o_rDisplay.Display_EOL();
}

bool
DT_EOL::IsWhiteOnly() const
{
    return true;
}

DT_StdAtTag::~DT_StdAtTag()
{
}

void
DT_StdAtTag::DisplayAt( DocumentationDisplay & o_rDisplay ) const
{
    o_rDisplay.Display_StdAtTag( *this );
}

DT_SeeAlsoAtTag::~DT_SeeAlsoAtTag()
{
}

void
DT_SeeAlsoAtTag::DisplayAt( DocumentationDisplay & o_rDisplay ) const
{
    o_rDisplay.Display_SeeAlsoAtTag( *this );
}

DT_ParameterAtTag::~DT_ParameterAtTag()
{
}

void
DT_ParameterAtTag::DisplayAt( DocumentationDisplay & o_rDisplay ) const
{
    o_rDisplay.Display_ParameterAtTag( *this );
}

DT_SinceAtTag::~DT_SinceAtTag()
{
}

void
DT_SinceAtTag::DisplayAt( DocumentationDisplay & o_rDisplay ) const
{
    o_rDisplay.Display_SinceAtTag( *this );
}

}   // namespace dsapi
}   // namespace csi
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: hfi_enum.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-07 17:40:15 $
 *
 *  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 ADC_DISPLAY_HFI_ENUM_HXX
#define ADC_DISPLAY_HFI_ENUM_HXX

// USED SERVICES
    // BASE CLASSES
#include "hi_factory.hxx"
    // COMPONENTS
    // PARAMETERS

class HF_IdlEnum : public HtmlFactory_Idl
{
  public:
                        HF_IdlEnum(
                            Environment &       io_rEnv,
                            Xml::Element &      o_rOut );
    virtual             ~HF_IdlEnum();

    void                Produce_byData(
                            const client &      ce ) const;
  private:
    HF_NaviSubRow &     make_Navibar(
                            const client &      ce ) const;
    virtual void        produce_MemberDetails(
                            HF_SubTitleTable &  o_table,
                            const client &      ce ) const;
};

// IMPLEMENTATION

extern const String
    C_sCePrefix_Enum;

#endif

<commit_msg>INTEGRATION: CWS changefileheader (1.2.80); FILE MERGED 2008/03/28 16:02:03 rt 1.2.80.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: hfi_enum.hxx,v $
 * $Revision: 1.3 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef ADC_DISPLAY_HFI_ENUM_HXX
#define ADC_DISPLAY_HFI_ENUM_HXX

// USED SERVICES
    // BASE CLASSES
#include "hi_factory.hxx"
    // COMPONENTS
    // PARAMETERS

class HF_IdlEnum : public HtmlFactory_Idl
{
  public:
                        HF_IdlEnum(
                            Environment &       io_rEnv,
                            Xml::Element &      o_rOut );
    virtual             ~HF_IdlEnum();

    void                Produce_byData(
                            const client &      ce ) const;
  private:
    HF_NaviSubRow &     make_Navibar(
                            const client &      ce ) const;
    virtual void        produce_MemberDetails(
                            HF_SubTitleTable &  o_table,
                            const client &      ce ) const;
};

// IMPLEMENTATION

extern const String
    C_sCePrefix_Enum;

#endif

<|endoftext|>


<commit_before>// doosabin_regression.cpp

// Includes
#include <algorithm>
#include <fstream>
#include <iostream>
#include <memory>
#include <string>
#include <utility>

#include "ceres/ceres.h"
#include "gflags/gflags.h"
#include "glog/logging.h"

#include <Eigen/Dense>

#include "Math/linalg.h"
#include "Ceres/compose_cost_functions.h"

#include "doosabin.h"

#include "surface.h"
#include "ceres_surface.h"

#include "doosabin_regression.pb.h"

// DooSabinSurface
class DooSabinSurface : public Surface {
 public:
  typedef doosabin::Surface<double> Surface;

  explicit DooSabinSurface(const Surface* surface)
    : surface_(surface)
  {}

  #define EVALUATE(M) \
  virtual void M(double* r, const int p, const double* u, \
                 const double* const* X) const { \
    const Eigen::Map<const Eigen::Vector2d> _u(u); \
    const linalg::MatrixOfColumnPointers<double> _X( \
      X, 3, surface_->patch_vertex_indices(p).size()); \
    Eigen::Map<Eigen::Vector3d> _r(r); \
    surface_->M(p, _u, _X, &_r); \
  }
  EVALUATE(M);
  EVALUATE(Mu);
  EVALUATE(Mv);
  EVALUATE(Muu);
  EVALUATE(Muv);
  EVALUATE(Mvv);
  #undef EVALUATE

  virtual void Mx(double* r, const int p, const double* u) const {
    const Eigen::Map<const Eigen::Vector2d> _u(u);
    // `X` is only used by `surface_` to infer the geometry dimensions.
    Eigen::Matrix<double, 3, 0> X;
    Eigen::Map<Eigen::VectorXd> _r(
      r, 3 * 3 * surface_->patch_vertex_indices(p).size());
    surface_->Mx(p, _u, X, &_r);
  }

  virtual int number_of_vertices() const {
    return surface_->number_of_vertices();
  }

  virtual int number_of_faces() const {
    return surface_->number_of_faces();
  }

  virtual int number_of_patches() const {
    return surface_->number_of_patches();
  }

  virtual const std::vector<int>& patch_vertex_indices(const int p) const {
    return surface_->patch_vertex_indices(p);
  }

  virtual const std::vector<int>& adjacent_patch_indices(const int p) const {
    return surface_->adjacent_patch_indices(p);
  }

 private:
  const Surface* surface_;
};

// LoadProblemFromFile
bool LoadProblemFromFile(const std::string& input_path,
                         Eigen::MatrixXd* Y,
                         std::vector<int>* raw_face_array,
                         Eigen::MatrixXd* X,
                         Eigen::VectorXi* p,
                         Eigen::MatrixXd* U) {
  doosabin_regression::Problem problem;
  {
    std::fstream input(input_path, std::ios::in | std::ios::binary);
    if (!input) {
      LOG(ERROR) << "File \"" << input_path << "\" not found.";
      return false;
    } else if (!problem.ParseFromIstream(&input)) {
      LOG(ERROR) << "Failed to parse input problem.";
      return false;
    }
  }

  #define LOAD_MATRIX(SRC, DST, DIM) { \
    auto& _SRC = problem.SRC(); \
    CHECK_EQ(_SRC.size() % DIM, 0); \
    DST->resize(DIM, _SRC.size() / DIM); \
    std::copy(_SRC.data(), _SRC.data() + _SRC.size(), DST->data()); \
  }

  #define LOAD_VECTOR(SRC, DST) { \
    auto& _SRC = problem.SRC(); \
    DST->resize(_SRC.size()); \
    std::copy(_SRC.data(), _SRC.data() + _SRC.size(), DST->data()); \
  }

  LOAD_MATRIX(y_3, Y, 3);
  LOAD_VECTOR(t, raw_face_array);
  LOAD_MATRIX(x_3, X, 3);
  LOAD_VECTOR(p, p);
  LOAD_MATRIX(u_2, U, 2);

  #undef LOAD_MATRIX
  #undef LOAD_VECTOR

  return true;
}

// UpdateProblemToFile
bool UpdateProblemToFile(const std::string& input_path,
                         const std::string& output_path,
                         const Eigen::MatrixXd& X,
                         const Eigen::VectorXi& p,
                         const Eigen::MatrixXd& U) {
  doosabin_regression::Problem problem;
  {
    std::fstream input(input_path, std::ios::in | std::ios::binary);
    if (!input) {
      LOG(ERROR) << "File \"" << input_path << "\" not found.";
      return false;
    } else if (!problem.ParseFromIstream(&input)) {
      LOG(ERROR) << "Failed to parse input problem.";
      return false;
    }
  }

  std::copy(X.data(), X.data() + X.rows() * X.cols(),
            problem.mutable_x_3()->begin());
  std::copy(p.data(), p.data() + p.size(),
            problem.mutable_p()->begin());
  std::copy(U.data(), U.data() + U.rows() * U.cols(),
            problem.mutable_u_2()->begin());

  {
    std::fstream output(output_path, std::ios::out |
                                     std::ios::trunc |
                                     std::ios::binary);
    if (!problem.SerializeToOstream(&output)) {
      LOG(ERROR) << "Failed to write to \"" << output_path << "\"";
      return false;
    }
  }

  return true;
}

// PositionErrorFunctor
class PositionErrorFunctor {
 public:
  template <typename M>
  PositionErrorFunctor(const M& m0)
    : m0_(m0)
  {}

  template <typename T>
  bool operator()(const T* m, T* e) const {
    e[0] = T(m0_[0]) - m[0];
    e[1] = T(m0_[1]) - m[1];
    e[2] = T(m0_[2]) - m[2];
    return true;
  }

 private:
  Eigen::Vector3d m0_;
};

// PairwiseErrorFunctor
class PairwiseErrorFunctor {
 public:
  PairwiseErrorFunctor(const double& sqrt_w = 1.0)
    : sqrt_w_(sqrt_w)
  {}

  template <typename T>
  bool operator()(const T* x0, const T* x1, T* e) const {
    e[0] = T(sqrt_w_) * (x1[0] - x0[0]);
    e[1] = T(sqrt_w_) * (x1[1] - x0[1]);
    e[2] = T(sqrt_w_) * (x1[2] - x0[2]);
    return true;
  }

 private:
  const double sqrt_w_;
};

// main
DEFINE_int32(max_num_iterations, 1000, "Maximum number of iterations.");
DEFINE_double(function_tolerance, 0.0,
  "Minimizer terminates when "
  "(new_cost - old_cost) < function_tolerance * old_cost");
DEFINE_double(gradient_tolerance, 0.0,
  "Minimizer terminates when "
  "max_i |gradient_i| < gradient_tolerance * max_i|initial_gradient_i|");
DEFINE_double(parameter_tolerance, 0.0,
  "Minimizer terminates when "
  "|step|_2 <= parameter_tolerance * ( |x|_2 +  parameter_tolerance)");
DEFINE_double(min_trust_region_radius, 1e-9,
  "Minimizer terminates when the trust region radius becomes smaller than "
  "this value");

DEFINE_int32(num_threads, 1, "Number of threads to use for Jacobian evaluation.");
DEFINE_int32(num_linear_solver_threads, 1, "Number of threads to use for the linear solver.");

int main(int argc, char** argv) {
 GOOGLE_PROTOBUF_VERIFY_VERSION;

  google::ParseCommandLineFlags(&argc, &argv, true);
  google::InitGoogleLogging(argv[0]);

  if (argc < 4) {
    LOG(ERROR) << "Usage: " << argv[0] << " input_path lambda output_path";
    return -1;
  }

  // Load the problem data ...
  Eigen::MatrixXd Y;
  std::vector<int> raw_face_array;
  Eigen::MatrixXd X;
  Eigen::VectorXi p;
  Eigen::MatrixXd U;
  if (!LoadProblemFromFile(argv[1], &Y, &raw_face_array, &X, &p, &U)) {
    return -1;
  }

  // ... and check consistency of dimensions.
  typedef Eigen::DenseIndex Index;
  const Index num_data_points = Y.cols();
  CHECK_EQ(num_data_points, p.size());
  CHECK_EQ(num_data_points, U.cols());

  doosabin::GeneralMesh T(std::move(raw_face_array));
  doosabin::Surface<double> surface(T);
  DooSabinSurface ceres_surface(&surface);
  CHECK_EQ(surface.number_of_vertices(), X.cols());

  // Set lambda.
  const double lambda = atof(argv[2]);

  // Setup `problem`.
  ceres::Problem problem;

  // Encode patch indices into the preimage positions.
  for (Index i = 0; i < num_data_points; ++i) {
    EncodePatchIndexInPlace(U.data() + 2 * i, p[i]);
  }

  // Add error residuals.
  std::vector<double*> parameter_blocks;
  parameter_blocks.reserve(1 + surface.number_of_vertices());
  parameter_blocks.push_back(nullptr); // `u`.
  for (Index i = 0; i < X.cols(); ++i) {
    parameter_blocks.push_back(X.data() + 3 * i);
  }

  for (Index i = 0; i < num_data_points; ++i) {
    parameter_blocks[0] = U.data() + 2 * i;

    auto position_error = new ceres_utility::GeneralCostFunctionComposition(
      new ceres::AutoDiffCostFunction<PositionErrorFunctor, 3, 3>(
        new PositionErrorFunctor(Y.col(i))));
    position_error->AddInputCostFunction(
      new SurfacePositionCostFunction(&ceres_surface),
      parameter_blocks);
    position_error->Finalise();

    problem.AddResidualBlock(position_error, nullptr, parameter_blocks);
  }

  // Add regularisation residuals.
  std::set<std::pair<int, int>> edges;
  for (auto& half_edge : T.iterate_half_edges()) {
    int i = half_edge.first, j = half_edge.second;
    if (i > j) {
      std::swap(i, j);
    }
    auto full_edge = std::make_pair(i, j);
    if (edges.count(full_edge)) {
      continue;
    }

    problem.AddResidualBlock(new ceres::AutoDiffCostFunction<PairwiseErrorFunctor, 3, 3, 3>(
      new PairwiseErrorFunctor(sqrt(num_data_points * lambda))),
      nullptr,
      X.data() + 3 * i,
      X.data() + 3 * j);

    edges.insert(full_edge);
  }

  typedef doosabin::SurfaceWalker<double> DooSabinWalker;
  DooSabinWalker walker(&surface);
  for (Index i = 0; i < num_data_points; ++i) {
    problem.SetParameterization(
      U.data() + 2 * i,
      new PreimageLocalParameterisation<DooSabinWalker, Eigen::MatrixXd>(
        &walker, &X));
  }

  // Initialise the solver options.
  std::cout << "Solver options:" << std::endl;
  ceres::Solver::Options options;

  options.num_threads = FLAGS_num_threads;
  options.num_linear_solver_threads = FLAGS_num_linear_solver_threads;

  // Disable auto-scaling and set LM to be additive (instead of multiplicative).
  options.min_lm_diagonal = 1.0;
  options.max_lm_diagonal = 1.0;
  options.jacobi_scaling = false;

  options.minimizer_progress_to_stdout = FLAGS_v >= 1;

  // Termination criteria.
  options.max_num_iterations = FLAGS_max_num_iterations;
  std::cout << " max_num_iterations: " << options.max_num_iterations <<
               std::endl;
  options.max_num_consecutive_invalid_steps = FLAGS_max_num_iterations;

  options.function_tolerance = FLAGS_function_tolerance;
  options.gradient_tolerance = FLAGS_gradient_tolerance;
  options.parameter_tolerance = FLAGS_parameter_tolerance;
  options.min_trust_region_radius = FLAGS_min_trust_region_radius;

  // Solver selection.
  options.dynamic_sparsity = true;

  // `update_state_every_iteration` is required by
  // `PreimageLocalParameterisation` instances.
  options.update_state_every_iteration = true;

  // Solve.
  std::cout << "Solving ..." << std::endl;
  ceres::Solver::Summary summary;
  ceres::Solve(options, &problem, &summary);

  std::cout << summary.FullReport() << std::endl;

  // Decode patch indices.
  for (Index i = 0; i < num_data_points; ++i) {
    p[i] = DecodePatchIndexInPlace(U.data() + 2 * i);
  }

  if (!UpdateProblemToFile(argv[1], argv[3], X, p, U)) {
    return -1;
  }

  return 0;
}
<commit_msg>Add `sqrt_w` as argument to `PositionErrorFunctor` in src/doosabin_regression.cpp<commit_after>// doosabin_regression.cpp

// Includes
#include <algorithm>
#include <fstream>
#include <iostream>
#include <memory>
#include <string>
#include <utility>

#include "ceres/ceres.h"
#include "gflags/gflags.h"
#include "glog/logging.h"

#include <Eigen/Dense>

#include "Math/linalg.h"
#include "Ceres/compose_cost_functions.h"

#include "doosabin.h"

#include "surface.h"
#include "ceres_surface.h"

#include "doosabin_regression.pb.h"

// DooSabinSurface
class DooSabinSurface : public Surface {
 public:
  typedef doosabin::Surface<double> Surface;

  explicit DooSabinSurface(const Surface* surface)
    : surface_(surface)
  {}

  #define EVALUATE(M) \
  virtual void M(double* r, const int p, const double* u, \
                 const double* const* X) const { \
    const Eigen::Map<const Eigen::Vector2d> _u(u); \
    const linalg::MatrixOfColumnPointers<double> _X( \
      X, 3, surface_->patch_vertex_indices(p).size()); \
    Eigen::Map<Eigen::Vector3d> _r(r); \
    surface_->M(p, _u, _X, &_r); \
  }
  EVALUATE(M);
  EVALUATE(Mu);
  EVALUATE(Mv);
  EVALUATE(Muu);
  EVALUATE(Muv);
  EVALUATE(Mvv);
  #undef EVALUATE

  virtual void Mx(double* r, const int p, const double* u) const {
    const Eigen::Map<const Eigen::Vector2d> _u(u);
    // `X` is only used by `surface_` to infer the geometry dimensions.
    Eigen::Matrix<double, 3, 0> X;
    Eigen::Map<Eigen::VectorXd> _r(
      r, 3 * 3 * surface_->patch_vertex_indices(p).size());
    surface_->Mx(p, _u, X, &_r);
  }

  virtual int number_of_vertices() const {
    return surface_->number_of_vertices();
  }

  virtual int number_of_faces() const {
    return surface_->number_of_faces();
  }

  virtual int number_of_patches() const {
    return surface_->number_of_patches();
  }

  virtual const std::vector<int>& patch_vertex_indices(const int p) const {
    return surface_->patch_vertex_indices(p);
  }

  virtual const std::vector<int>& adjacent_patch_indices(const int p) const {
    return surface_->adjacent_patch_indices(p);
  }

 private:
  const Surface* surface_;
};

// LoadProblemFromFile
bool LoadProblemFromFile(const std::string& input_path,
                         Eigen::MatrixXd* Y,
                         std::vector<int>* raw_face_array,
                         Eigen::MatrixXd* X,
                         Eigen::VectorXi* p,
                         Eigen::MatrixXd* U) {
  doosabin_regression::Problem problem;
  {
    std::fstream input(input_path, std::ios::in | std::ios::binary);
    if (!input) {
      LOG(ERROR) << "File \"" << input_path << "\" not found.";
      return false;
    } else if (!problem.ParseFromIstream(&input)) {
      LOG(ERROR) << "Failed to parse input problem.";
      return false;
    }
  }

  #define LOAD_MATRIX(SRC, DST, DIM) { \
    auto& _SRC = problem.SRC(); \
    CHECK_EQ(_SRC.size() % DIM, 0); \
    DST->resize(DIM, _SRC.size() / DIM); \
    std::copy(_SRC.data(), _SRC.data() + _SRC.size(), DST->data()); \
  }

  #define LOAD_VECTOR(SRC, DST) { \
    auto& _SRC = problem.SRC(); \
    DST->resize(_SRC.size()); \
    std::copy(_SRC.data(), _SRC.data() + _SRC.size(), DST->data()); \
  }

  LOAD_MATRIX(y_3, Y, 3);
  LOAD_VECTOR(t, raw_face_array);
  LOAD_MATRIX(x_3, X, 3);
  LOAD_VECTOR(p, p);
  LOAD_MATRIX(u_2, U, 2);

  #undef LOAD_MATRIX
  #undef LOAD_VECTOR

  return true;
}

// UpdateProblemToFile
bool UpdateProblemToFile(const std::string& input_path,
                         const std::string& output_path,
                         const Eigen::MatrixXd& X,
                         const Eigen::VectorXi& p,
                         const Eigen::MatrixXd& U) {
  doosabin_regression::Problem problem;
  {
    std::fstream input(input_path, std::ios::in | std::ios::binary);
    if (!input) {
      LOG(ERROR) << "File \"" << input_path << "\" not found.";
      return false;
    } else if (!problem.ParseFromIstream(&input)) {
      LOG(ERROR) << "Failed to parse input problem.";
      return false;
    }
  }

  std::copy(X.data(), X.data() + X.rows() * X.cols(),
            problem.mutable_x_3()->begin());
  std::copy(p.data(), p.data() + p.size(),
            problem.mutable_p()->begin());
  std::copy(U.data(), U.data() + U.rows() * U.cols(),
            problem.mutable_u_2()->begin());

  {
    std::fstream output(output_path, std::ios::out |
                                     std::ios::trunc |
                                     std::ios::binary);
    if (!problem.SerializeToOstream(&output)) {
      LOG(ERROR) << "Failed to write to \"" << output_path << "\"";
      return false;
    }
  }

  return true;
}

// PositionErrorFunctor
class PositionErrorFunctor {
 public:
  template <typename M>
  PositionErrorFunctor(const M& m0, const double& sqrt_w = 1.0)
    : m0_(m0), sqrt_w_(sqrt_w)
  {}

  template <typename T>
  bool operator()(const T* m, T* e) const {
    e[0] = T(sqrt_w_) * (T(m0_[0]) - m[0]);
    e[1] = T(sqrt_w_) * (T(m0_[1]) - m[1]);
    e[2] = T(sqrt_w_) * (T(m0_[2]) - m[2]);
    return true;
  }

 private:
  Eigen::Vector3d m0_;
  const double sqrt_w_;
};

// PairwiseErrorFunctor
class PairwiseErrorFunctor {
 public:
  PairwiseErrorFunctor(const double& sqrt_w = 1.0)
    : sqrt_w_(sqrt_w)
  {}

  template <typename T>
  bool operator()(const T* x0, const T* x1, T* e) const {
    e[0] = T(sqrt_w_) * (x1[0] - x0[0]);
    e[1] = T(sqrt_w_) * (x1[1] - x0[1]);
    e[2] = T(sqrt_w_) * (x1[2] - x0[2]);
    return true;
  }

 private:
  const double sqrt_w_;
};

// main
DEFINE_int32(max_num_iterations, 1000, "Maximum number of iterations.");
DEFINE_double(function_tolerance, 0.0,
  "Minimizer terminates when "
  "(new_cost - old_cost) < function_tolerance * old_cost");
DEFINE_double(gradient_tolerance, 0.0,
  "Minimizer terminates when "
  "max_i |gradient_i| < gradient_tolerance * max_i|initial_gradient_i|");
DEFINE_double(parameter_tolerance, 0.0,
  "Minimizer terminates when "
  "|step|_2 <= parameter_tolerance * ( |x|_2 +  parameter_tolerance)");
DEFINE_double(min_trust_region_radius, 1e-9,
  "Minimizer terminates when the trust region radius becomes smaller than "
  "this value");

DEFINE_int32(num_threads, 1, "Number of threads to use for Jacobian evaluation.");
DEFINE_int32(num_linear_solver_threads, 1, "Number of threads to use for the linear solver.");

int main(int argc, char** argv) {
 GOOGLE_PROTOBUF_VERIFY_VERSION;

  google::ParseCommandLineFlags(&argc, &argv, true);
  google::InitGoogleLogging(argv[0]);

  if (argc < 4) {
    LOG(ERROR) << "Usage: " << argv[0] << " input_path lambda output_path";
    return -1;
  }

  // Load the problem data ...
  Eigen::MatrixXd Y;
  std::vector<int> raw_face_array;
  Eigen::MatrixXd X;
  Eigen::VectorXi p;
  Eigen::MatrixXd U;
  if (!LoadProblemFromFile(argv[1], &Y, &raw_face_array, &X, &p, &U)) {
    return -1;
  }

  // ... and check consistency of dimensions.
  typedef Eigen::DenseIndex Index;
  const Index num_data_points = Y.cols();
  CHECK_EQ(num_data_points, p.size());
  CHECK_EQ(num_data_points, U.cols());

  doosabin::GeneralMesh T(std::move(raw_face_array));
  doosabin::Surface<double> surface(T);
  DooSabinSurface ceres_surface(&surface);
  CHECK_EQ(surface.number_of_vertices(), X.cols());

  // Set lambda.
  const double lambda = atof(argv[2]);

  // Setup `problem`.
  ceres::Problem problem;

  // Encode patch indices into the preimage positions.
  for (Index i = 0; i < num_data_points; ++i) {
    EncodePatchIndexInPlace(U.data() + 2 * i, p[i]);
  }

  // Add error residuals.
  std::vector<double*> parameter_blocks;
  parameter_blocks.reserve(1 + surface.number_of_vertices());
  parameter_blocks.push_back(nullptr); // `u`.
  for (Index i = 0; i < X.cols(); ++i) {
    parameter_blocks.push_back(X.data() + 3 * i);
  }

  for (Index i = 0; i < num_data_points; ++i) {
    parameter_blocks[0] = U.data() + 2 * i;

    auto position_error = new ceres_utility::GeneralCostFunctionComposition(
      new ceres::AutoDiffCostFunction<PositionErrorFunctor, 3, 3>(
        new PositionErrorFunctor(Y.col(i))));
    position_error->AddInputCostFunction(
      new SurfacePositionCostFunction(&ceres_surface),
      parameter_blocks);
    position_error->Finalise();

    problem.AddResidualBlock(position_error, nullptr, parameter_blocks);
  }

  // Add regularisation residuals.
  std::set<std::pair<int, int>> edges;
  for (auto& half_edge : T.iterate_half_edges()) {
    int i = half_edge.first, j = half_edge.second;
    if (i > j) {
      std::swap(i, j);
    }
    auto full_edge = std::make_pair(i, j);
    if (edges.count(full_edge)) {
      continue;
    }

    problem.AddResidualBlock(new ceres::AutoDiffCostFunction<PairwiseErrorFunctor, 3, 3, 3>(
      new PairwiseErrorFunctor(sqrt(num_data_points * lambda))),
      nullptr,
      X.data() + 3 * i,
      X.data() + 3 * j);

    edges.insert(full_edge);
  }

  typedef doosabin::SurfaceWalker<double> DooSabinWalker;
  DooSabinWalker walker(&surface);
  for (Index i = 0; i < num_data_points; ++i) {
    problem.SetParameterization(
      U.data() + 2 * i,
      new PreimageLocalParameterisation<DooSabinWalker, Eigen::MatrixXd>(
        &walker, &X));
  }

  // Initialise the solver options.
  std::cout << "Solver options:" << std::endl;
  ceres::Solver::Options options;

  options.num_threads = FLAGS_num_threads;
  options.num_linear_solver_threads = FLAGS_num_linear_solver_threads;

  // Disable auto-scaling and set LM to be additive (instead of multiplicative).
  options.min_lm_diagonal = 1.0;
  options.max_lm_diagonal = 1.0;
  options.jacobi_scaling = false;

  options.minimizer_progress_to_stdout = FLAGS_v >= 1;

  // Termination criteria.
  options.max_num_iterations = FLAGS_max_num_iterations;
  std::cout << " max_num_iterations: " << options.max_num_iterations <<
               std::endl;
  options.max_num_consecutive_invalid_steps = FLAGS_max_num_iterations;

  options.function_tolerance = FLAGS_function_tolerance;
  options.gradient_tolerance = FLAGS_gradient_tolerance;
  options.parameter_tolerance = FLAGS_parameter_tolerance;
  options.min_trust_region_radius = FLAGS_min_trust_region_radius;

  // Solver selection.
  options.dynamic_sparsity = true;

  // `update_state_every_iteration` is required by
  // `PreimageLocalParameterisation` instances.
  options.update_state_every_iteration = true;

  // Solve.
  std::cout << "Solving ..." << std::endl;
  ceres::Solver::Summary summary;
  ceres::Solve(options, &problem, &summary);

  std::cout << summary.FullReport() << std::endl;

  // Decode patch indices.
  for (Index i = 0; i < num_data_points; ++i) {
    p[i] = DecodePatchIndexInPlace(U.data() + 2 * i);
  }

  if (!UpdateProblemToFile(argv[1], argv[3], X, p, U)) {
    return -1;
  }

  return 0;
}
<|endoftext|>


<commit_before><commit_msg>planning: keep in pull-over scenario when fail to find pull-over position<commit_after><|endoftext|>


<commit_before>#ifndef ENTT_CORE_TYPE_INFO_HPP
#define ENTT_CORE_TYPE_INFO_HPP

#include "../config/config.h"
#include "../core/attribute.h"
#include "hashed_string.hpp"
#include "fwd.hpp"

namespace entt {

/**
 * @cond TURN_OFF_DOXYGEN
 * Internal details not to be documented.
 */

namespace internal {

struct ENTT_API type_index {
    static id_type next() ENTT_NOEXCEPT {
        static ENTT_MAYBE_ATOMIC(id_type) value{};
        return value++;
    }
};

}

/**
 * Internal details not to be documented.
 * @endcond TURN_OFF_DOXYGEN
 */

/**
 * @brief Type index.
 * @tparam Type Type for which to generate a sequential identifier.
 */
template<typename Type, typename = void>
struct ENTT_API type_index {
    /**
     * @brief Returns the sequential identifier of a given type.
     * @return The sequential identifier of a given type.
     */
    static id_type value() ENTT_NOEXCEPT {
        static const id_type value = internal::type_index::next();
        return value;
    }
};

/**
 * @brief Type info.
 * @tparam Type Type for which to generate information.
 */
template<typename Type, typename = void>
struct ENTT_API type_info {
    /**
     * @brief Returns the numeric representation of a given type.
     * @return The numeric representation of the given type.
     */
#if defined ENTT_PRETTY_FUNCTION_CONSTEXPR
    static constexpr id_type id() ENTT_NOEXCEPT {
        constexpr auto value = entt::hashed_string::value(ENTT_PRETTY_FUNCTION_CONSTEXPR);
        return value;
    }
#elif defined ENTT_PRETTY_FUNCTION
    static id_type id() ENTT_NOEXCEPT {
        static const auto value = entt::hashed_string::value(ENTT_PRETTY_FUNCTION);
        return value;
    }
#else
    static id_type id() ENTT_NOEXCEPT {
        return type_index<Type>::value();
    }
#endif
};

}

#endif
<commit_msg>type info: added has_type_index[_v]<commit_after>#ifndef ENTT_CORE_TYPE_INFO_HPP
#define ENTT_CORE_TYPE_INFO_HPP

#include "../config/config.h"
#include "../core/attribute.h"
#include "hashed_string.hpp"
#include "fwd.hpp"

namespace entt {

/**
 * @cond TURN_OFF_DOXYGEN
 * Internal details not to be documented.
 */

namespace internal {

struct ENTT_API type_index {
    static id_type next() ENTT_NOEXCEPT {
        static ENTT_MAYBE_ATOMIC(id_type) value{};
        return value++;
    }
};

}

/**
 * Internal details not to be documented.
 * @endcond TURN_OFF_DOXYGEN
 */

/**
 * @brief Type index.
 * @tparam Type Type for which to generate a sequential identifier.
 */
template<typename Type, typename = void>
struct ENTT_API type_index {
    /**
     * @brief Returns the sequential identifier of a given type.
     * @return The sequential identifier of a given type.
     */
    static id_type value() ENTT_NOEXCEPT {
        static const id_type value = internal::type_index::next();
        return value;
    }
};

/**
 * @brief Provides the member constant `value` to true if a given type is
 * indexable, false otherwise.
 * @tparam Type Potentially indexable type.
 */
template<typename, typename = void>
struct has_type_index: std::false_type {};

/*! @brief has_type_index */
template<typename Type>
struct has_type_index<Type, std::void_t<decltype(type_index<Type>::value())>>: std::true_type {};

/**
 * @brief Helper variable template.
 * @tparam Type Potentially indexable type.
 */
template<typename Type>
inline constexpr bool has_type_index_v = has_type_index<Type>::value;

/**
 * @brief Type info.
 * @tparam Type Type for which to generate information.
 */
template<typename Type, typename = void>
struct ENTT_API type_info {
    /**
     * @brief Returns the numeric representation of a given type.
     * @return The numeric representation of the given type.
     */
#if defined ENTT_PRETTY_FUNCTION_CONSTEXPR
    static constexpr id_type id() ENTT_NOEXCEPT {
        constexpr auto value = entt::hashed_string::value(ENTT_PRETTY_FUNCTION_CONSTEXPR);
        return value;
    }
#elif defined ENTT_PRETTY_FUNCTION
    static id_type id() ENTT_NOEXCEPT {
        static const auto value = entt::hashed_string::value(ENTT_PRETTY_FUNCTION);
        return value;
    }
#else
    static id_type id() ENTT_NOEXCEPT {
        return type_index<Type>::value();
    }
#endif
};

}

#endif
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2016-present, Facebook, Inc.
 *
 * 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.
 */
/* Modifications Copyright (c) Microsoft. */

#include "roialign.h"

#include <cmath>
#include "core/util/math_cpuonly.h"
#include "core/common/common.h"
#include "core/framework/tensor.h"
#include "core/platform/threadpool.h"

using namespace onnxruntime::concurrency;

namespace onnxruntime {

#define ADD_TYPED_ROIALIGN_OP(data_type)                                                            \
  ONNX_CPU_OPERATOR_TYPED_KERNEL(RoiAlign, 10, data_type,                                           \
                                 KernelDefBuilder()                                                 \
                                     .TypeConstraint("T", DataTypeImpl::GetTensorType<data_type>()) \
                                     .TypeConstraint("T2", DataTypeImpl::GetTensorType<int64_t>()), \
                                 RoiAlign<data_type>);

ADD_TYPED_ROIALIGN_OP(float);
ADD_TYPED_ROIALIGN_OP(double);

namespace {
template <typename T>
struct PreCalc {
  int64_t pos1;
  int64_t pos2;
  int64_t pos3;
  int64_t pos4;
  T w1;
  T w2;
  T w3;
  T w4;
};

template <typename T>
void pre_calc_for_bilinear_interpolate(const int64_t height, const int64_t width, const int64_t pooled_height,
                                       const int64_t pooled_width, const int64_t iy_upper, const int64_t ix_upper,
                                       T roi_start_h, T roi_start_w, T bin_size_h, T bin_size_w, int64_t roi_bin_grid_h,
                                       int64_t roi_bin_grid_w, std::vector<PreCalc<T>>& pre_calc) {
  int64_t pre_calc_index = 0;
  for (int64_t ph = 0; ph < pooled_height; ph++) {
    for (int64_t pw = 0; pw < pooled_width; pw++) {
      for (int64_t iy = 0; iy < iy_upper; iy++) {
        const T yy = roi_start_h + ph * bin_size_h +
                     static_cast<T>(iy + .5f) * bin_size_h / static_cast<T>(roi_bin_grid_h);  // e.g., 0.5, 1.5
        for (int64_t ix = 0; ix < ix_upper; ix++) {
          const T xx =
              roi_start_w + pw * bin_size_w + static_cast<T>(ix + .5f) * bin_size_w / static_cast<T>(roi_bin_grid_w);

          T x = xx;
          T y = yy;
          // deal with: inverse elements are out of feature map boundary
          if (y < -1.0 || y > height || x < -1.0 || x > width) {
            // empty
            PreCalc<T> pc;
            pc.pos1 = 0;
            pc.pos2 = 0;
            pc.pos3 = 0;
            pc.pos4 = 0;
            pc.w1 = 0;
            pc.w2 = 0;
            pc.w3 = 0;
            pc.w4 = 0;
            pre_calc[pre_calc_index] = pc;
            pre_calc_index += 1;
            continue;
          }

          if (y <= 0) {
            y = 0;
          }
          if (x <= 0) {
            x = 0;
          }

          auto y_low = static_cast<int64_t>(y);
          auto x_low = static_cast<int64_t>(x);
          int64_t y_high;
          int64_t x_high;

          if (y_low >= height - 1) {
            y_high = y_low = height - 1;
            y = (T)y_low;
          } else {
            y_high = y_low + 1;
          }

          if (x_low >= width - 1) {
            x_high = x_low = width - 1;
            x = (T)x_low;
          } else {
            x_high = x_low + 1;
          }

          T ly = y - y_low;
          T lx = x - x_low;
          T hy = static_cast<T>(1.) - ly;
          T hx = static_cast<T>(1.) - lx;
          T w1 = hy * hx;
          T w2 = hy * lx;
          T w3 = ly * hx;
          T w4 = ly * lx;

          // save weights and indeces
          PreCalc<T> pc;
          pc.pos1 = y_low * width + x_low;
          pc.pos2 = y_low * width + x_high;
          pc.pos3 = y_high * width + x_low;
          pc.pos4 = y_high * width + x_high;
          pc.w1 = w1;
          pc.w2 = w2;
          pc.w3 = w3;
          pc.w4 = w4;
          pre_calc[pre_calc_index] = pc;

          pre_calc_index += 1;
        }
      }
    }
  }
}

template <typename T>
void RoiAlignForward(const TensorShape& output_shape, const T* bottom_data, float spatial_scale, int64_t height,
                     int64_t width, int64_t sampling_ratio, const T* bottom_rois, int64_t num_roi_cols, T* top_data,
                     RoiAlignMode mode, const int64_t* batch_indices_ptr, ThreadPool* ttp) {
  int64_t n_rois = output_shape[0];
  int64_t channels = output_shape[1];
  int64_t pooled_height = output_shape[2];
  int64_t pooled_width = output_shape[3];

  //100 is a random chosed value, need be tuned
  double cost = static_cast<double>(channels * pooled_width * pooled_height * 100);

  ThreadPool::TryParallelFor(ttp, static_cast<ptrdiff_t>(n_rois), cost, [&](ptrdiff_t n, ptrdiff_t end) {
    for (; n != end; ++n) {
      int64_t index_n = n * channels * pooled_width * pooled_height;

      const T* offset_bottom_rois = bottom_rois + n * num_roi_cols;
      const auto roi_batch_ind = batch_indices_ptr[n];

      // Do not using rounding; this implementation detail is critical
      T roi_start_w = offset_bottom_rois[0] * spatial_scale;
      T roi_start_h = offset_bottom_rois[1] * spatial_scale;
      T roi_end_w = offset_bottom_rois[2] * spatial_scale;
      T roi_end_h = offset_bottom_rois[3] * spatial_scale;

      // Force malformed ROIs to be 1x1
      T roi_width = std::max(roi_end_w - roi_start_w, (T)1.);
      T roi_height = std::max(roi_end_h - roi_start_h, (T)1.);
      T bin_size_h = static_cast<T>(roi_height) / static_cast<T>(pooled_height);
      T bin_size_w = static_cast<T>(roi_width) / static_cast<T>(pooled_width);

      // We use roi_bin_grid to sample the grid and mimic integral
      int64_t roi_bin_grid_h = (sampling_ratio > 0) ?
                                   sampling_ratio :
                                   static_cast<int64_t>(std::ceil(roi_height / pooled_height));  // e.g., = 2
      int64_t roi_bin_grid_w =
          (sampling_ratio > 0) ? sampling_ratio : static_cast<int64_t>(std::ceil(roi_width / pooled_width));

      // We do average (integral) pooling inside a bin
      const int64_t count = roi_bin_grid_h * roi_bin_grid_w;  // e.g. = 4

      // we want to precalculate indices and weights shared by all channels,
      // this is the key point of optimization
      std::vector<PreCalc<T>> pre_calc(roi_bin_grid_h * roi_bin_grid_w * pooled_width * pooled_height);
      pre_calc_for_bilinear_interpolate(height, width, pooled_height, pooled_width, roi_bin_grid_h, roi_bin_grid_w,
                                        roi_start_h, roi_start_w, bin_size_h, bin_size_w, roi_bin_grid_h,
                                        roi_bin_grid_w, pre_calc);

      for (int64_t c = 0; c < channels; c++) {
        int64_t index_n_c = index_n + c * pooled_width * pooled_height;
        const T* offset_bottom_data =
            bottom_data + static_cast<int64_t>((roi_batch_ind * channels + c) * height * width);
        int64_t pre_calc_index = 0;

        for (int64_t ph = 0; ph < pooled_height; ph++) {
          for (int64_t pw = 0; pw < pooled_width; pw++) {
            int64_t index = index_n_c + ph * pooled_width + pw;

            T output_val = 0.;
            if (mode == RoiAlignMode::avg) {  // avg pooling
              for (int64_t iy = 0; iy < roi_bin_grid_h; iy++) {
                for (int64_t ix = 0; ix < roi_bin_grid_w; ix++) {
                  PreCalc<T> pc = pre_calc[pre_calc_index];
                  output_val += pc.w1 * offset_bottom_data[pc.pos1] + pc.w2 * offset_bottom_data[pc.pos2] +
                                pc.w3 * offset_bottom_data[pc.pos3] + pc.w4 * offset_bottom_data[pc.pos4];

                  pre_calc_index += 1;
                }
              }
              output_val /= count;
            } else {  // max pooling
              bool max_flag = false;
              for (int64_t iy = 0; iy < roi_bin_grid_h; iy++) {
                for (int64_t ix = 0; ix < roi_bin_grid_w; ix++) {
                  PreCalc<T> pc = pre_calc[pre_calc_index];
                  T val = std::max(
                      std::max(std::max(pc.w1 * offset_bottom_data[pc.pos1], pc.w2 * offset_bottom_data[pc.pos2]),
                               pc.w3 * offset_bottom_data[pc.pos3]),
                      pc.w4 * offset_bottom_data[pc.pos4]);
                  if (!max_flag) {
                    output_val = val;
                    max_flag = true;
                  } else {
                    output_val = std::max(output_val, val);
                  }

                  pre_calc_index += 1;
                }
              }
            }

            top_data[index] = output_val;
          }  // for pw
        }    // for ph
      }      // for c
    }        // for n
  });
}
}  // namespace

Status CheckROIAlignValidInput(const Tensor* X_ptr, const Tensor* rois_ptr, const Tensor* batch_indices_ptr) {
  const int64_t EXPECTED_NUM_ROI_DIMS = 2;
  const int64_t EXPECTED_SECOND_ROI_DIM = 4;
  if (!X_ptr) {
    return Status(common::ONNXRUNTIME, common::INVALID_ARGUMENT, "Null input X ptr");
  }
  if (!rois_ptr) {
    return Status(common::ONNXRUNTIME, common::INVALID_ARGUMENT, "Null rois_ptr");
  }
  if (!batch_indices_ptr) {
    return Status(common::ONNXRUNTIME, common::INVALID_ARGUMENT, "Null batch_indices_ptr");
  }

  const auto& rois_dims = rois_ptr->Shape();
  const auto& batch_indices_dims = batch_indices_ptr->Shape();

  if (batch_indices_dims.NumDimensions() != 1) {
    return Status(common::ONNXRUNTIME, common::INVALID_ARGUMENT,
                  "Number of dimensions for batch indices should be exactly 1");
  }

  // validate rois_dims
  if (rois_dims.NumDimensions() != EXPECTED_NUM_ROI_DIMS) {
    return Status(common::ONNXRUNTIME, common::INVALID_ARGUMENT,
                  "Number of dimensions for rois should be exactly " + std::to_string(EXPECTED_NUM_ROI_DIMS));
  }
  if (rois_dims[1] != EXPECTED_SECOND_ROI_DIM) {
    return Status(common::ONNXRUNTIME, common::INVALID_ARGUMENT,
                  "Second dimension for rois should be exactly " + std::to_string(EXPECTED_SECOND_ROI_DIM));
  }

  // first dimension of batch_indices and rois should match
  if (batch_indices_dims[0] != rois_dims[0]) {
    return Status(common::ONNXRUNTIME, common::INVALID_ARGUMENT,
                  "First dimension (num_rois) of batch_indices and rois don't match");
  }
  return Status::OK();
}

template <typename T>
Status RoiAlign<T>::Compute(OpKernelContext* context) const {
  const auto* X_ptr = context->Input<Tensor>(0);
  const auto* rois_ptr = context->Input<Tensor>(1);
  const auto* batch_indices_ptr = context->Input<Tensor>(2);

  const auto& x_dims = X_ptr->Shape();
  const auto& rois_dims = rois_ptr->Shape();
  const auto& batch_indices_dims = batch_indices_ptr->Shape();

  auto num_channels = x_dims[1];
  auto num_rois = batch_indices_dims[0];
  auto num_roi_cols = rois_dims[1];

  auto status = CheckROIAlignValidInput(X_ptr, rois_ptr, batch_indices_ptr);
  if (!status.IsOK()) {
    return status;
  }

  auto& Y = *context->Output(0, {num_rois, num_channels, this->output_height_, this->output_width_});

  RoiAlignForward<T>(Y.Shape(), X_ptr->Data<T>(), this->spatial_scale_,
                     x_dims[2],  // height
                     x_dims[3],  // width
                     this->sampling_ratio_, rois_ptr->Data<T>(), num_roi_cols, Y.template MutableData<T>(), this->mode_,
                     batch_indices_ptr->Data<int64_t>(), context->GetOperatorThreadPool());

  return Status::OK();
}

}  // namespace onnxruntime
<commit_msg>Cleanup in RoiAlign (#7012)<commit_after>/**
 * Copyright (c) 2016-present, Facebook, Inc.
 *
 * 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.
 */
/* Modifications Copyright (c) Microsoft. */

#include "roialign.h"

#include <cmath>
#include "core/util/math_cpuonly.h"
#include "core/common/common.h"
#include "core/framework/tensor.h"
#include "core/platform/threadpool.h"

using namespace onnxruntime::concurrency;

namespace onnxruntime {

#define ADD_TYPED_ROIALIGN_OP(data_type)                                                            \
  ONNX_CPU_OPERATOR_TYPED_KERNEL(RoiAlign, 10, data_type,                                           \
                                 KernelDefBuilder()                                                 \
                                     .TypeConstraint("T", DataTypeImpl::GetTensorType<data_type>()) \
                                     .TypeConstraint("T2", DataTypeImpl::GetTensorType<int64_t>()), \
                                 RoiAlign<data_type>);

ADD_TYPED_ROIALIGN_OP(float);
ADD_TYPED_ROIALIGN_OP(double);

namespace {
template <typename T>
struct PreCalc {
  int64_t pos1;
  int64_t pos2;
  int64_t pos3;
  int64_t pos4;
  T w1;
  T w2;
  T w3;
  T w4;
};

template <typename T>
static void PreCalcForBilinearInterpolate(const int64_t height, const int64_t width, const int64_t pooled_height,
                                          const int64_t pooled_width, const int64_t iy_upper, const int64_t ix_upper,
                                          T roi_start_h, T roi_start_w, T bin_size_h, T bin_size_w, int64_t roi_bin_grid_h,
                                          int64_t roi_bin_grid_w, std::vector<PreCalc<T>>& pre_calc) {
  int64_t pre_calc_index = 0;
  for (int64_t ph = 0; ph < pooled_height; ph++) {
    for (int64_t pw = 0; pw < pooled_width; pw++) {
      for (int64_t iy = 0; iy < iy_upper; iy++) {
        const T yy = roi_start_h + ph * bin_size_h +
                     static_cast<T>(iy + .5f) * bin_size_h / static_cast<T>(roi_bin_grid_h);  // e.g., 0.5, 1.5
        for (int64_t ix = 0; ix < ix_upper; ix++) {
          const T xx =
              roi_start_w + pw * bin_size_w + static_cast<T>(ix + .5f) * bin_size_w / static_cast<T>(roi_bin_grid_w);

          T x = xx;
          T y = yy;
          // deal with: inverse elements are out of feature map boundary
          if (y < -1.0 || y > height || x < -1.0 || x > width) {
            auto& pc = pre_calc[pre_calc_index];
            pc.pos1 = 0;
            pc.pos2 = 0;
            pc.pos3 = 0;
            pc.pos4 = 0;
            pc.w1 = 0;
            pc.w2 = 0;
            pc.w3 = 0;
            pc.w4 = 0;
            pre_calc_index += 1;
            continue;
          }

          if (y <= 0) {
            y = 0;
          }
          if (x <= 0) {
            x = 0;
          }

          auto y_low = static_cast<int64_t>(y);
          auto x_low = static_cast<int64_t>(x);
          int64_t y_high;
          int64_t x_high;

          if (y_low >= height - 1) {
            y_high = y_low = height - 1;
            y = (T)y_low;
          } else {
            y_high = y_low + 1;
          }

          if (x_low >= width - 1) {
            x_high = x_low = width - 1;
            x = (T)x_low;
          } else {
            x_high = x_low + 1;
          }

          T ly = y - y_low;
          T lx = x - x_low;
          T hy = static_cast<T>(1.) - ly;
          T hx = static_cast<T>(1.) - lx;
          T w1 = hy * hx;
          T w2 = hy * lx;
          T w3 = ly * hx;
          T w4 = ly * lx;

          // save weights and indeces
          PreCalc<T> pc;
          pc.pos1 = y_low * width + x_low;
          pc.pos2 = y_low * width + x_high;
          pc.pos3 = y_high * width + x_low;
          pc.pos4 = y_high * width + x_high;
          pc.w1 = w1;
          pc.w2 = w2;
          pc.w3 = w3;
          pc.w4 = w4;
          pre_calc[pre_calc_index] = pc;

          pre_calc_index += 1;
        }
      }
    }
  }
}

template <typename T>
void RoiAlignForward(const TensorShape& output_shape, const T* bottom_data, float spatial_scale, int64_t height,
                     int64_t width, int64_t sampling_ratio, const T* bottom_rois, int64_t num_roi_cols, T* top_data,
                     RoiAlignMode mode, const int64_t* batch_indices_ptr, ThreadPool* ttp) {
  int64_t n_rois = output_shape[0];
  int64_t channels = output_shape[1];
  int64_t pooled_height = output_shape[2];
  int64_t pooled_width = output_shape[3];

  //100 is a random chosed value, need be tuned
  double cost = static_cast<double>(channels * pooled_width * pooled_height * 100);

  ThreadPool::TryParallelFor(ttp, static_cast<ptrdiff_t>(n_rois), cost, [&](ptrdiff_t n, ptrdiff_t end) {
    for (; n != end; ++n) {
      int64_t index_n = n * channels * pooled_width * pooled_height;

      const T* offset_bottom_rois = bottom_rois + n * num_roi_cols;
      const auto roi_batch_ind = batch_indices_ptr[n];

      // Do not using rounding; this implementation detail is critical
      T roi_start_w = offset_bottom_rois[0] * spatial_scale;
      T roi_start_h = offset_bottom_rois[1] * spatial_scale;
      T roi_end_w = offset_bottom_rois[2] * spatial_scale;
      T roi_end_h = offset_bottom_rois[3] * spatial_scale;

      // Force malformed ROIs to be 1x1
      T roi_width = std::max(roi_end_w - roi_start_w, (T)1.);
      T roi_height = std::max(roi_end_h - roi_start_h, (T)1.);
      T bin_size_h = static_cast<T>(roi_height) / static_cast<T>(pooled_height);
      T bin_size_w = static_cast<T>(roi_width) / static_cast<T>(pooled_width);

      // We use roi_bin_grid to sample the grid and mimic integral
      int64_t roi_bin_grid_h = (sampling_ratio > 0) ? sampling_ratio : static_cast<int64_t>(std::ceil(roi_height / pooled_height));  // e.g., = 2
      int64_t roi_bin_grid_w =
          (sampling_ratio > 0) ? sampling_ratio : static_cast<int64_t>(std::ceil(roi_width / pooled_width));

      // We do average (integral) pooling inside a bin
      const int64_t count = roi_bin_grid_h * roi_bin_grid_w;  // e.g. = 4

      // we want to precalculate indices and weights shared by all channels,
      // this is the key point of optimization
      std::vector<PreCalc<T>> pre_calc(roi_bin_grid_h * roi_bin_grid_w * pooled_width * pooled_height);
      PreCalcForBilinearInterpolate(height, width, pooled_height, pooled_width, roi_bin_grid_h, roi_bin_grid_w,
                                    roi_start_h, roi_start_w, bin_size_h, bin_size_w, roi_bin_grid_h,
                                    roi_bin_grid_w, pre_calc);

      for (int64_t c = 0; c < channels; c++) {
        int64_t index_n_c = index_n + c * pooled_width * pooled_height;
        const T* offset_bottom_data =
            bottom_data + static_cast<int64_t>((roi_batch_ind * channels + c) * height * width);
        int64_t pre_calc_index = 0;

        for (int64_t ph = 0; ph < pooled_height; ph++) {
          for (int64_t pw = 0; pw < pooled_width; pw++) {
            int64_t index = index_n_c + ph * pooled_width + pw;

            T output_val = 0.;
            if (mode == RoiAlignMode::avg) {  // avg pooling
              for (int64_t iy = 0; iy < roi_bin_grid_h; iy++) {
                for (int64_t ix = 0; ix < roi_bin_grid_w; ix++) {
                  const auto& pc = pre_calc[pre_calc_index];
                  output_val += pc.w1 * offset_bottom_data[pc.pos1] + pc.w2 * offset_bottom_data[pc.pos2] +
                                pc.w3 * offset_bottom_data[pc.pos3] + pc.w4 * offset_bottom_data[pc.pos4];

                  pre_calc_index += 1;
                }
              }
              output_val /= count;
            } else {  // max pooling
              bool max_flag = false;
              for (int64_t iy = 0; iy < roi_bin_grid_h; iy++) {
                for (int64_t ix = 0; ix < roi_bin_grid_w; ix++) {
                  const auto& pc = pre_calc[pre_calc_index];
                  T val = std::max(
                      std::max(std::max(pc.w1 * offset_bottom_data[pc.pos1], pc.w2 * offset_bottom_data[pc.pos2]),
                               pc.w3 * offset_bottom_data[pc.pos3]),
                      pc.w4 * offset_bottom_data[pc.pos4]);
                  if (!max_flag) {
                    output_val = val;
                    max_flag = true;
                  } else {
                    output_val = std::max(output_val, val);
                  }

                  pre_calc_index += 1;
                }
              }
            }

            top_data[index] = output_val;
          }  // for pw
        }    // for ph
      }      // for c
    }        // for n
  });
}
}  // namespace

Status CheckROIAlignValidInput(const Tensor* X_ptr, const Tensor* rois_ptr, const Tensor* batch_indices_ptr) {
  const int64_t EXPECTED_NUM_ROI_DIMS = 2;
  const int64_t EXPECTED_SECOND_ROI_DIM = 4;
  if (!X_ptr) {
    return Status(common::ONNXRUNTIME, common::INVALID_ARGUMENT, "Null input X ptr");
  }
  if (!rois_ptr) {
    return Status(common::ONNXRUNTIME, common::INVALID_ARGUMENT, "Null rois_ptr");
  }
  if (!batch_indices_ptr) {
    return Status(common::ONNXRUNTIME, common::INVALID_ARGUMENT, "Null batch_indices_ptr");
  }

  const auto& rois_dims = rois_ptr->Shape();
  const auto& batch_indices_dims = batch_indices_ptr->Shape();

  if (batch_indices_dims.NumDimensions() != 1) {
    return Status(common::ONNXRUNTIME, common::INVALID_ARGUMENT,
                  "Number of dimensions for batch indices should be exactly 1");
  }

  // validate rois_dims
  if (rois_dims.NumDimensions() != EXPECTED_NUM_ROI_DIMS) {
    return Status(common::ONNXRUNTIME, common::INVALID_ARGUMENT,
                  "Number of dimensions for rois should be exactly " + std::to_string(EXPECTED_NUM_ROI_DIMS));
  }
  if (rois_dims[1] != EXPECTED_SECOND_ROI_DIM) {
    return Status(common::ONNXRUNTIME, common::INVALID_ARGUMENT,
                  "Second dimension for rois should be exactly " + std::to_string(EXPECTED_SECOND_ROI_DIM));
  }

  // first dimension of batch_indices and rois should match
  if (batch_indices_dims[0] != rois_dims[0]) {
    return Status(common::ONNXRUNTIME, common::INVALID_ARGUMENT,
                  "First dimension (num_rois) of batch_indices and rois don't match");
  }
  return Status::OK();
}

template <typename T>
Status RoiAlign<T>::Compute(OpKernelContext* context) const {
  const auto* X_ptr = context->Input<Tensor>(0);
  const auto* rois_ptr = context->Input<Tensor>(1);
  const auto* batch_indices_ptr = context->Input<Tensor>(2);

  const auto& x_dims = X_ptr->Shape();
  const auto& rois_dims = rois_ptr->Shape();
  const auto& batch_indices_dims = batch_indices_ptr->Shape();

  auto num_channels = x_dims[1];
  auto num_rois = batch_indices_dims[0];
  auto num_roi_cols = rois_dims[1];

  auto status = CheckROIAlignValidInput(X_ptr, rois_ptr, batch_indices_ptr);
  if (!status.IsOK()) {
    return status;
  }

  auto& Y = *context->Output(0, {num_rois, num_channels, this->output_height_, this->output_width_});

  RoiAlignForward<T>(Y.Shape(), X_ptr->Data<T>(), this->spatial_scale_,
                     x_dims[2],  // height
                     x_dims[3],  // width
                     this->sampling_ratio_, rois_ptr->Data<T>(), num_roi_cols, Y.template MutableData<T>(), this->mode_,
                     batch_indices_ptr->Data<int64_t>(), context->GetOperatorThreadPool());

  return Status::OK();
}

}  // namespace onnxruntime
<|endoftext|>


<commit_before>/*
 * 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.
 *
 * Written (W) 2011 Evgeniy Andreev (gsomix)
 *
 * Copyright (C) 2011 Berlin Institute of Technology and Max-Planck-Society
 */

#include "lib/FibonacciHeap.h"
#include "stdio.h"

using namespace shogun;

CFibonacciHeap::CFibonacciHeap()
{
	min_root = NULL;

	max_num_nodes = 0;
	nodes = NULL;

	num_nodes = 0;
	num_trees = 0;
}

CFibonacciHeap::CFibonacciHeap(int32_t capacity)
{
	min_root = NULL;

	max_num_nodes = capacity;
	nodes = SG_MALLOC(FibonacciHeapNode* , max_num_nodes);
	for(int32_t i = 0; i < max_num_nodes; i++)
	{
		nodes[i] = new FibonacciHeapNode;
		clear_node(i);
	}

	num_nodes = 0;
	num_trees = 0;
}

CFibonacciHeap::~CFibonacciHeap()
{
	for(int32_t i = 0; i < max_num_nodes; i++)
	{
		if(nodes[i] != NULL)
			delete nodes[i];
	}

	delete [] nodes;
}

void CFibonacciHeap::insert(int32_t index, float64_t key)
{
	if(index >= max_num_nodes || index < 0)
		return;

	if(nodes[index]->index != -1)
		return; // node is not empty

	// init "new" node in array
	nodes[index]->child = NULL;
	nodes[index]->parent = NULL;

	nodes[index]->rank = 0;
	nodes[index]->index = index;
	nodes[index]->key = key;
	nodes[index]->marked = false;

	add_to_roots(nodes[index]);
	num_nodes++;
}

int32_t CFibonacciHeap::extract_min(float64_t &ret_key)
{
	FibonacciHeapNode *min_node;
	FibonacciHeapNode *child, *next_child;

	int32_t result;

	if(num_nodes == 0)
		return -1;

	min_node = min_root;
	if(min_node == NULL)
		return -1; // heap is empty now

	child = min_node->child;
	while(child != NULL && child->parent != NULL)
	{
		next_child = child->right;

		// delete current child from childs list
		child->left->right = child->right;
		child->right->left = child->left;

		add_to_roots(child);

		// next iteration
		child = next_child;
	}

	// delete minimun from root list
	min_node->left->right = min_node->right;
	min_node->right->left = min_node->left;

	num_trees--;

	if(min_node == min_node->right)
	{
		min_root = NULL; // remove last element
	}
	else
	{
		min_root = min_node->right;
		consolidate();
	}

	result = min_node->index;
	ret_key = min_node->key;
	clear_node(result);

	num_nodes--;

	return result;
}

void CFibonacciHeap::clear()
{
	min_root = NULL;

	// clear all nodes
	for(int32_t i = 0; i < max_num_nodes; i++)
	{
		clear_node(i);
	}

	num_nodes = 0;
	num_trees = 0;
}

int32_t CFibonacciHeap::get_key(int32_t index, float64_t &ret_key)
{
	if(index >= max_num_nodes || index < 0)
		return -1;
	if(nodes[index]->index == -1)
		return -1;

	int32_t result = nodes[index]->index;
	ret_key = nodes[index]->key;

	return result;
}

void CFibonacciHeap::decrease_key(int32_t index, float64_t key)
{
	FibonacciHeapNode* parent;

	if(index >= max_num_nodes || index < 0)
		return;
	if(nodes[index]->index == -1)
		return; // node is empty
	if(key > nodes[index]->key)
		return;

	nodes[index]->key = key;

	parent = nodes[index]->parent;

	if(parent != NULL && nodes[index]->key < parent->key)
	{
		cut(nodes[index], parent);
		cascading_cut(parent);
	}

	if(nodes[index]->key < min_root->key)
		min_root = nodes[index];
}

void CFibonacciHeap::add_to_roots(FibonacciHeapNode *up_node)
{
	if(min_root == NULL)
	{
		// if heap is empty, node becomes circular root list
		min_root = up_node;

		up_node->left = up_node;
		up_node->right = up_node;
	}
	else
	{
		// insert node to root list
		up_node->right = min_root->right;
		up_node->left = min_root;

		up_node->left->right = up_node;
		up_node->right->left = up_node;

		// nomination of new minimum node
		if(up_node->key < min_root->key)
		{
			min_root = up_node;
		}
	}

	up_node->parent = NULL;
	num_trees++;
}

void CFibonacciHeap::consolidate()
{
	FibonacciHeapNode *x, *y, *w;
	FibonacciHeapNode **A;

	int32_t Dn, d;

	Dn = 1 + (int32_t)(CMath::log2(max_num_nodes));

	A = SG_MALLOC(FibonacciHeapNode* , Dn);
	for(int32_t i = 0; i < Dn; i++)
	{
		A[i] = NULL;
	}

	min_root->left->right = NULL;
	min_root->left = NULL;
	w = min_root;

	do
	{
		x = w;
		d = x->rank;
		w = w->right;

		while(A[d] != NULL)
		{
			y = A[d];

			if(y->key < x->key)
			{
				FibonacciHeapNode *temp;

				temp = y;
				y = x;
				x = temp;
			}

			link_nodes(y, x);

			A[d] = NULL;
			d++;
		}
		A[d] = x;
	}
	while(w != NULL);

	min_root = NULL;
	num_trees = 0;

	for(int32_t i = 0; i < Dn; i++)
	{
		if(A[i] != NULL)
		{
			A[i]->marked = false;
			add_to_roots(A[i]);
		}
	}
}

void CFibonacciHeap::link_nodes(FibonacciHeapNode *y, FibonacciHeapNode *x)
{
	if(y->right != NULL)
		y->right->left = y->left;
	if(y->left != NULL)
		y->left->right = y->right;

	num_trees--;

	y->left = y;
	y->right = y;

	y->parent = x;

	if(x->child == NULL)
	{
		x->child = y;
	}
	else
	{
		y->left = x->child;
		y->right = x->child->right;

		x->child->right = y;
		y->right->left = y;
	}

	x->rank++;

	y->marked = false;
}

void CFibonacciHeap::clear_node(int32_t index)
{
	nodes[index]->parent = NULL;
	nodes[index]->child = NULL;
	nodes[index]->left = NULL;
	nodes[index]->right = NULL;

	nodes[index]->rank = 0;
	nodes[index]->index = -1;
	nodes[index]->key = 0;

	nodes[index]->marked = false;
}

void CFibonacciHeap::cut(FibonacciHeapNode *child, FibonacciHeapNode *parent)
{
	if(parent->child == child)
		parent->child = child->right;

	if(parent->child == child)
		parent->child = NULL;

	parent->rank--;

	child->left->right = child->right;
	child->right->left = child->left;

	add_to_roots(child);
	child->marked = false;
}

void CFibonacciHeap::cascading_cut(FibonacciHeapNode *tree)
{
	FibonacciHeapNode *temp;

	temp = tree->parent;
	if(temp != NULL)
	{
		if(!tree->marked)
		{
			tree->marked = true;
		}
		else
		{
			cut(tree, temp);
			cascading_cut(temp);
		}
	}
}

void CFibonacciHeap::debug_print()
{
	SG_SPRINT("%d %d\n", num_trees, num_nodes);
	for(int32_t i = 0; i < max_num_nodes; i++)
	{
		if(nodes[i]->index == -1)
		{
			SG_SPRINT("None\n");
		}
		else
		{
			SG_SPRINT("%f\n",nodes[i]->key);
		}
	}
}
<commit_msg>Micro fix<commit_after>/*
 * 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.
 *
 * Written (W) 2011 Evgeniy Andreev (gsomix)
 *
 * Copyright (C) 2011 Berlin Institute of Technology and Max-Planck-Society
 */

#include "lib/FibonacciHeap.h"

using namespace shogun;

CFibonacciHeap::CFibonacciHeap()
{
	min_root = NULL;

	max_num_nodes = 0;
	nodes = NULL;

	num_nodes = 0;
	num_trees = 0;
}

CFibonacciHeap::CFibonacciHeap(int32_t capacity)
{
	min_root = NULL;

	max_num_nodes = capacity;
	nodes = SG_MALLOC(FibonacciHeapNode* , max_num_nodes);
	for(int32_t i = 0; i < max_num_nodes; i++)
	{
		nodes[i] = new FibonacciHeapNode;
		clear_node(i);
	}

	num_nodes = 0;
	num_trees = 0;
}

CFibonacciHeap::~CFibonacciHeap()
{
	for(int32_t i = 0; i < max_num_nodes; i++)
	{
		if(nodes[i] != NULL)
			delete nodes[i];
	}

	delete [] nodes;
}

void CFibonacciHeap::insert(int32_t index, float64_t key)
{
	if(index >= max_num_nodes || index < 0)
		return;

	if(nodes[index]->index != -1)
		return; // node is not empty

	// init "new" node in array
	nodes[index]->child = NULL;
	nodes[index]->parent = NULL;

	nodes[index]->rank = 0;
	nodes[index]->index = index;
	nodes[index]->key = key;
	nodes[index]->marked = false;

	add_to_roots(nodes[index]);
	num_nodes++;
}

int32_t CFibonacciHeap::extract_min(float64_t &ret_key)
{
	FibonacciHeapNode *min_node;
	FibonacciHeapNode *child, *next_child;

	int32_t result;

	if(num_nodes == 0)
		return -1;

	min_node = min_root;
	if(min_node == NULL)
		return -1; // heap is empty now

	child = min_node->child;
	while(child != NULL && child->parent != NULL)
	{
		next_child = child->right;

		// delete current child from childs list
		child->left->right = child->right;
		child->right->left = child->left;

		add_to_roots(child);

		// next iteration
		child = next_child;
	}

	// delete minimun from root list
	min_node->left->right = min_node->right;
	min_node->right->left = min_node->left;

	num_trees--;

	if(min_node == min_node->right)
	{
		min_root = NULL; // remove last element
	}
	else
	{
		min_root = min_node->right;
		consolidate();
	}

	result = min_node->index;
	ret_key = min_node->key;
	clear_node(result);

	num_nodes--;

	return result;
}

void CFibonacciHeap::clear()
{
	min_root = NULL;

	// clear all nodes
	for(int32_t i = 0; i < max_num_nodes; i++)
	{
		clear_node(i);
	}

	num_nodes = 0;
	num_trees = 0;
}

int32_t CFibonacciHeap::get_key(int32_t index, float64_t &ret_key)
{
	if(index >= max_num_nodes || index < 0)
		return -1;
	if(nodes[index]->index == -1)
		return -1;

	int32_t result = nodes[index]->index;
	ret_key = nodes[index]->key;

	return result;
}

void CFibonacciHeap::decrease_key(int32_t index, float64_t key)
{
	FibonacciHeapNode* parent;

	if(index >= max_num_nodes || index < 0)
		return;
	if(nodes[index]->index == -1)
		return; // node is empty
	if(key > nodes[index]->key)
		return;

	nodes[index]->key = key;

	parent = nodes[index]->parent;

	if(parent != NULL && nodes[index]->key < parent->key)
	{
		cut(nodes[index], parent);
		cascading_cut(parent);
	}

	if(nodes[index]->key < min_root->key)
		min_root = nodes[index];
}

void CFibonacciHeap::add_to_roots(FibonacciHeapNode *up_node)
{
	if(min_root == NULL)
	{
		// if heap is empty, node becomes circular root list
		min_root = up_node;

		up_node->left = up_node;
		up_node->right = up_node;
	}
	else
	{
		// insert node to root list
		up_node->right = min_root->right;
		up_node->left = min_root;

		up_node->left->right = up_node;
		up_node->right->left = up_node;

		// nomination of new minimum node
		if(up_node->key < min_root->key)
		{
			min_root = up_node;
		}
	}

	up_node->parent = NULL;
	num_trees++;
}

void CFibonacciHeap::consolidate()
{
	FibonacciHeapNode *x, *y, *w;
	FibonacciHeapNode **A;

	int32_t Dn, d;

	eoDn = 1 + (int32_t)(CMath::log2(max_num_nodes));

	A = SG_MALLOC(FibonacciHeapNode* , Dn);
	for(int32_t i = 0; i < Dn; i++)
	{
		A[i] = NULL;
	}

	min_root->left->right = NULL;
	min_root->left = NULL;
	w = min_root;

	do
	{
		x = w;
		d = x->rank;
		w = w->right;

		while(A[d] != NULL)
		{
			y = A[d];

			if(y->key < x->key)
			{
				FibonacciHeapNode *temp;

				temp = y;
				y = x;
				x = temp;
			}

			link_nodes(y, x);

			A[d] = NULL;
			d++;
		}
		A[d] = x;
	}
	while(w != NULL);

	min_root = NULL;
	num_trees = 0;

	for(int32_t i = 0; i < Dn; i++)
	{
		if(A[i] != NULL)
		{
			A[i]->marked = false;
			add_to_roots(A[i]);
		}
	}
}

void CFibonacciHeap::link_nodes(FibonacciHeapNode *y, FibonacciHeapNode *x)
{
	if(y->right != NULL)
		y->right->left = y->left;
	if(y->left != NULL)
		y->left->right = y->right;

	num_trees--;

	y->left = y;
	y->right = y;

	y->parent = x;

	if(x->child == NULL)
	{
		x->child = y;
	}
	else
	{
		y->left = x->child;
		y->right = x->child->right;

		x->child->right = y;
		y->right->left = y;
	}

	x->rank++;

	y->marked = false;
}

void CFibonacciHeap::clear_node(int32_t index)
{
	nodes[index]->parent = NULL;
	nodes[index]->child = NULL;
	nodes[index]->left = NULL;
	nodes[index]->right = NULL;

	nodes[index]->rank = 0;
	nodes[index]->index = -1;
	nodes[index]->key = 0;

	nodes[index]->marked = false;
}

void CFibonacciHeap::cut(FibonacciHeapNode *child, FibonacciHeapNode *parent)
{
	if(parent->child == child)
		parent->child = child->right;

	if(parent->child == child)
		parent->child = NULL;

	parent->rank--;

	child->left->right = child->right;
	child->right->left = child->left;

	add_to_roots(child);
	child->marked = false;
}

void CFibonacciHeap::cascading_cut(FibonacciHeapNode *tree)
{
	FibonacciHeapNode *temp;

	temp = tree->parent;
	if(temp != NULL)
	{
		if(!tree->marked)
		{
			tree->marked = true;
		}
		else
		{
			cut(tree, temp);
			cascading_cut(temp);
		}
	}
}

void CFibonacciHeap::debug_print()
{
	SG_SPRINT("%d %d\n", num_trees, num_nodes);
	for(int32_t i = 0; i < max_num_nodes; i++)
	{
		if(nodes[i]->index == -1)
		{
			SG_SPRINT("None\n");
		}
		else
		{
			SG_SPRINT("%f\n",nodes[i]->key);
		}
	}
}
<|endoftext|>