<commit_before>/*************************************************************************
 *
 *  $RCSfile: rangenam.hxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: rt $ $Date: 2004-11-09 14:58:46 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef SC_RANGENAM_HXX
#define SC_RANGENAM_HXX

#ifndef SC_SCGLOB_HXX
#include "global.hxx" // -> enum UpdateRefMode
#endif
#ifndef SC_ADDRESS_HXX
#include "address.hxx"
#endif
#ifndef SC_COLLECT_HXX
#include "collect.hxx"
#endif

//------------------------------------------------------------------------

class ScDocument;
class ScMultipleReadHeader;
class ScMultipleWriteHeader;

namespace rtl {
    class OUStringBuffer;
}

//------------------------------------------------------------------------

typedef USHORT RangeType;

#define RT_NAME             ((RangeType)0x0000)
#define RT_DATABASE         ((RangeType)0x0001)
#define RT_CRITERIA         ((RangeType)0x0002)
#define RT_PRINTAREA        ((RangeType)0x0004)
#define RT_COLHEADER        ((RangeType)0x0008)
#define RT_ROWHEADER        ((RangeType)0x0010)
#define RT_ABSAREA          ((RangeType)0x0020)
#define RT_REFAREA          ((RangeType)0x0040)
#define RT_ABSPOS           ((RangeType)0x0080)
#define RT_SHARED           ((RangeType)0x0100)
#define RT_SHAREDMOD        ((RangeType)0x0200)

//------------------------------------------------------------------------

class ScTokenArray;
class ScIndexMap;

class ScRangeData : public DataObject
{
#if defined( ICC ) && defined( OS2 )
    friend static int _Optlink   ICCQsortNameCompare( const void* a, const void* b);
#endif
private:
    String          aName;
    ScTokenArray*   pCode;
    ScAddress       aPos;
    RangeType       eType;
    ScDocument*     pDoc;
    USHORT          nIndex;
    USHORT          nExportIndex;
    BOOL            bModified;          // wird bei UpdateReference gesetzt/geloescht

    friend class ScRangeName;
    ScRangeData( USHORT nIndex );
public:
                    ScRangeData( ScDocument* pDoc,
                                 const String& rName,
                                 const String& rSymbol,
                                 const ScAddress& rAdr = ScAddress(),
                                 RangeType nType = RT_NAME,
                                 BOOL bEnglish = FALSE );
                    ScRangeData( ScDocument* pDoc,
                                 const String& rName,
                                 const ScTokenArray& rArr,
                                 const ScAddress& rAdr = ScAddress(),
                                 RangeType nType = RT_NAME );
                    ScRangeData( ScDocument* pDoc,
                                 const String& rName,
                                 const ScAddress& rTarget );
                                // rTarget ist ABSPOS Sprungmarke
                    ScRangeData(const ScRangeData& rScRangeData);
                    ScRangeData( SvStream& rStream,
                                 ScMultipleReadHeader& rHdr,
                                 USHORT nVer );

    virtual         ~ScRangeData();

    virtual DataObject* Clone() const;

    BOOL            Store( SvStream& rStream, ScMultipleWriteHeader& rHdr ) const;

    BOOL            operator== (const ScRangeData& rData) const;

    void            GetName( String& rName ) const  { rName = aName; }
    const String&   GetName( void ) const           { return aName; }
    ScAddress       GetPos() const                  { return aPos; }
    // Der Index muss eindeutig sein. Ist er 0, wird ein neuer Index vergeben
    void            SetIndex( USHORT nInd )         { nIndex = nExportIndex = nInd; }
    const USHORT    GetIndex() const                { return nIndex; }
    void            SetExportIndex( USHORT nInd )   { nExportIndex = nInd; }
    const USHORT    GetExportIndex() const          { return nExportIndex; }
    ScTokenArray*   GetCode()                       { return pCode; }
    USHORT          GetErrCode();
    BOOL            HasReferences() const;
    void            SetDocument( ScDocument* pDocument){ pDoc = pDocument; }
    ScDocument*     GetDocument() const             { return pDoc; }
    void            SetType( RangeType nType )      { eType = nType; }
    void            AddType( RangeType nType )      { eType = eType|nType; }
    RangeType       GetType() const                 { return eType; }
    BOOL            HasType( RangeType nType ) const;
    void            GetSymbol(String& rSymbol) const;
    void            GetEnglishSymbol(String& rSymbol, BOOL bCompileXML = FALSE) const;
    void            UpdateSymbol( String& rSymbol, const ScAddress&,
                                    BOOL bEnglish = FALSE, BOOL bCompileXML = FALSE );
    void            UpdateSymbol( rtl::OUStringBuffer& rBuffer, const ScAddress&,
                                    BOOL bEnglish = FALSE, BOOL bCompileXML = FALSE );
    void            UpdateReference( UpdateRefMode eUpdateRefMode,
                             const ScRange& r,
                             SCsCOL nDx, SCsROW nDy, SCsTAB nDz );
    BOOL            IsModified() const              { return bModified; }

    void            GuessPosition();

    void            UpdateTranspose( const ScRange& rSource, const ScAddress& rDest );
    void            UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY );

    BOOL            IsReference( ScRange& rRef ) const;

    BOOL            IsRangeAtCursor( const ScAddress&, BOOL bStartOnly ) const;
    BOOL            IsRangeAtBlock( const ScRange& ) const;

    void            UpdateTabRef(SCTAB nOldTable, USHORT nFlag, SCTAB nNewTable);
    void            TransferTabRef( SCTAB nOldTab, SCTAB nNewTab );

    void            ValidateTabRefs();

    void            ReplaceRangeNamesInUse( const ScIndexMap& rMap );

    BOOL            IsBeyond( SCROW nMaxRow ) const;

    static void     MakeValidName( String& rName );
    static BOOL     IsNameValid( const String& rName, ScDocument* pDoc );
#ifdef WNT
    static int __cdecl  QsortNameCompare( const void*, const void* );
#else
    static int      QsortNameCompare( const void*, const void* );
#endif
};

inline BOOL ScRangeData::HasType( RangeType nType ) const
{
    return ( ( eType & nType ) == nType );
}

#if defined( ICC ) && defined( OS2 )
    static int _Optlink  ICCQsortNameCompare( const void* a, const void* b)
                            { ScRangeData::QsortNameCompare(a,b); }
#endif

//------------------------------------------------------------------------

class ScRangeName : public SortedCollection
{
private:
    ScDocument* pDoc;
    USHORT nSharedMaxIndex;
public:
    ScRangeName(USHORT nLim = 4, USHORT nDel = 4, BOOL bDup = FALSE,
                ScDocument* pDocument = NULL) :
        SortedCollection    ( nLim, nDel, bDup ),
        pDoc                ( pDocument ),
        nSharedMaxIndex     ( 1 ) {}            // darf nicht 0 sein!!

    ScRangeName(const ScRangeName& rScRangeName, ScDocument* pDocument);

    virtual DataObject*     Clone(ScDocument* pDoc) const
                             { return new ScRangeName(*this, pDoc); }
    ScRangeData*            operator[]( const USHORT nIndex) const
                             { return (ScRangeData*)At(nIndex); }
    virtual short           Compare(DataObject* pKey1, DataObject* pKey2) const;
    virtual BOOL            IsEqual(DataObject* pKey1, DataObject* pKey2) const;

    ScRangeData*            GetRangeAtCursor( const ScAddress&, BOOL bStartOnly ) const;
    ScRangeData*            GetRangeAtBlock( const ScRange& ) const;

    BOOL                    Load( SvStream& rStream, USHORT nVer );
    BOOL                    Store( SvStream& rStream ) const;
    BOOL                    SearchName( const String& rName, USHORT& rPos ) const;
    void                    UpdateReference(UpdateRefMode eUpdateRefMode,
                                const ScRange& rRange,
                                SCsCOL nDx, SCsROW nDy, SCsTAB nDz );
    void                    UpdateTabRef(SCTAB nTable, USHORT nFlag, SCTAB nNewTable = 0);
    void                    UpdateTranspose( const ScRange& rSource, const ScAddress& rDest );
    void                    UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY );
    virtual BOOL            Insert(DataObject* pDataObject);
    ScRangeData*            FindIndex(USHORT nIndex);
    USHORT                  GetSharedMaxIndex()             { return nSharedMaxIndex; }
    void                    SetSharedMaxIndex(USHORT nInd)  { nSharedMaxIndex = nInd; }
    USHORT                  GetEntryIndex();
};

#endif

<commit_msg>INTEGRATION: CWS dr31 (1.7.32); FILE MERGED 2004/12/17 15:03:09 dr 1.7.32.1: #i38792# #i38821# Excel export of defined names and database ranges reimplemented<commit_after>/*************************************************************************
 *
 *  $RCSfile: rangenam.hxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: kz $ $Date: 2005-01-14 11:58:54 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef SC_RANGENAM_HXX
#define SC_RANGENAM_HXX

#ifndef SC_SCGLOB_HXX
#include "global.hxx" // -> enum UpdateRefMode
#endif
#ifndef SC_ADDRESS_HXX
#include "address.hxx"
#endif
#ifndef SC_COLLECT_HXX
#include "collect.hxx"
#endif

//------------------------------------------------------------------------

class ScDocument;
class ScMultipleReadHeader;
class ScMultipleWriteHeader;

namespace rtl {
    class OUStringBuffer;
}

//------------------------------------------------------------------------

typedef USHORT RangeType;

#define RT_NAME             ((RangeType)0x0000)
#define RT_DATABASE         ((RangeType)0x0001)
#define RT_CRITERIA         ((RangeType)0x0002)
#define RT_PRINTAREA        ((RangeType)0x0004)
#define RT_COLHEADER        ((RangeType)0x0008)
#define RT_ROWHEADER        ((RangeType)0x0010)
#define RT_ABSAREA          ((RangeType)0x0020)
#define RT_REFAREA          ((RangeType)0x0040)
#define RT_ABSPOS           ((RangeType)0x0080)
#define RT_SHARED           ((RangeType)0x0100)
#define RT_SHAREDMOD        ((RangeType)0x0200)

//------------------------------------------------------------------------

class ScTokenArray;
class ScIndexMap;

class ScRangeData : public DataObject
{
#if defined( ICC ) && defined( OS2 )
    friend static int _Optlink   ICCQsortNameCompare( const void* a, const void* b);
#endif
private:
    String          aName;
    ScTokenArray*   pCode;
    ScAddress       aPos;
    RangeType       eType;
    ScDocument*     pDoc;
    USHORT          nIndex;
    BOOL            bModified;          // wird bei UpdateReference gesetzt/geloescht

    friend class ScRangeName;
    ScRangeData( USHORT nIndex );
public:
                    ScRangeData( ScDocument* pDoc,
                                 const String& rName,
                                 const String& rSymbol,
                                 const ScAddress& rAdr = ScAddress(),
                                 RangeType nType = RT_NAME,
                                 BOOL bEnglish = FALSE );
                    ScRangeData( ScDocument* pDoc,
                                 const String& rName,
                                 const ScTokenArray& rArr,
                                 const ScAddress& rAdr = ScAddress(),
                                 RangeType nType = RT_NAME );
                    ScRangeData( ScDocument* pDoc,
                                 const String& rName,
                                 const ScAddress& rTarget );
                                // rTarget ist ABSPOS Sprungmarke
                    ScRangeData(const ScRangeData& rScRangeData);
                    ScRangeData( SvStream& rStream,
                                 ScMultipleReadHeader& rHdr,
                                 USHORT nVer );

    virtual         ~ScRangeData();

    virtual DataObject* Clone() const;

    BOOL            Store( SvStream& rStream, ScMultipleWriteHeader& rHdr ) const;

    BOOL            operator== (const ScRangeData& rData) const;

    void            GetName( String& rName ) const  { rName = aName; }
    const String&   GetName( void ) const           { return aName; }
    ScAddress       GetPos() const                  { return aPos; }
    // Der Index muss eindeutig sein. Ist er 0, wird ein neuer Index vergeben
    void            SetIndex( USHORT nInd )         { nIndex = nInd; }
    const USHORT    GetIndex() const                { return nIndex; }
    ScTokenArray*   GetCode()                       { return pCode; }
    USHORT          GetErrCode();
    BOOL            HasReferences() const;
    void            SetDocument( ScDocument* pDocument){ pDoc = pDocument; }
    ScDocument*     GetDocument() const             { return pDoc; }
    void            SetType( RangeType nType )      { eType = nType; }
    void            AddType( RangeType nType )      { eType = eType|nType; }
    RangeType       GetType() const                 { return eType; }
    BOOL            HasType( RangeType nType ) const;
    void            GetSymbol(String& rSymbol) const;
    void            GetEnglishSymbol(String& rSymbol, BOOL bCompileXML = FALSE) const;
    void            UpdateSymbol( String& rSymbol, const ScAddress&,
                                    BOOL bEnglish = FALSE, BOOL bCompileXML = FALSE );
    void            UpdateSymbol( rtl::OUStringBuffer& rBuffer, const ScAddress&,
                                    BOOL bEnglish = FALSE, BOOL bCompileXML = FALSE );
    void            UpdateReference( UpdateRefMode eUpdateRefMode,
                             const ScRange& r,
                             SCsCOL nDx, SCsROW nDy, SCsTAB nDz );
    BOOL            IsModified() const              { return bModified; }

    void            GuessPosition();

    void            UpdateTranspose( const ScRange& rSource, const ScAddress& rDest );
    void            UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY );

    BOOL            IsReference( ScRange& rRef ) const;

    BOOL            IsRangeAtCursor( const ScAddress&, BOOL bStartOnly ) const;
    BOOL            IsRangeAtBlock( const ScRange& ) const;

    void            UpdateTabRef(SCTAB nOldTable, USHORT nFlag, SCTAB nNewTable);
    void            TransferTabRef( SCTAB nOldTab, SCTAB nNewTab );

    void            ValidateTabRefs();

    void            ReplaceRangeNamesInUse( const ScIndexMap& rMap );

    BOOL            IsBeyond( SCROW nMaxRow ) const;

    static void     MakeValidName( String& rName );
    static BOOL     IsNameValid( const String& rName, ScDocument* pDoc );
#ifdef WNT
    static int __cdecl  QsortNameCompare( const void*, const void* );
#else
    static int      QsortNameCompare( const void*, const void* );
#endif
};

inline BOOL ScRangeData::HasType( RangeType nType ) const
{
    return ( ( eType & nType ) == nType );
}

#if defined( ICC ) && defined( OS2 )
    static int _Optlink  ICCQsortNameCompare( const void* a, const void* b)
                            { ScRangeData::QsortNameCompare(a,b); }
#endif

//------------------------------------------------------------------------

class ScRangeName : public SortedCollection
{
private:
    ScDocument* pDoc;
    USHORT nSharedMaxIndex;
public:
    ScRangeName(USHORT nLim = 4, USHORT nDel = 4, BOOL bDup = FALSE,
                ScDocument* pDocument = NULL) :
        SortedCollection    ( nLim, nDel, bDup ),
        pDoc                ( pDocument ),
        nSharedMaxIndex     ( 1 ) {}            // darf nicht 0 sein!!

    ScRangeName(const ScRangeName& rScRangeName, ScDocument* pDocument);

    virtual DataObject*     Clone(ScDocument* pDoc) const
                             { return new ScRangeName(*this, pDoc); }
    ScRangeData*            operator[]( const USHORT nIndex) const
                             { return (ScRangeData*)At(nIndex); }
    virtual short           Compare(DataObject* pKey1, DataObject* pKey2) const;
    virtual BOOL            IsEqual(DataObject* pKey1, DataObject* pKey2) const;

    ScRangeData*            GetRangeAtCursor( const ScAddress&, BOOL bStartOnly ) const;
    ScRangeData*            GetRangeAtBlock( const ScRange& ) const;

    BOOL                    Load( SvStream& rStream, USHORT nVer );
    BOOL                    Store( SvStream& rStream ) const;
    BOOL                    SearchName( const String& rName, USHORT& rPos ) const;
    void                    UpdateReference(UpdateRefMode eUpdateRefMode,
                                const ScRange& rRange,
                                SCsCOL nDx, SCsROW nDy, SCsTAB nDz );
    void                    UpdateTabRef(SCTAB nTable, USHORT nFlag, SCTAB nNewTable = 0);
    void                    UpdateTranspose( const ScRange& rSource, const ScAddress& rDest );
    void                    UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY );
    virtual BOOL            Insert(DataObject* pDataObject);
    ScRangeData*            FindIndex(USHORT nIndex);
    USHORT                  GetSharedMaxIndex()             { return nSharedMaxIndex; }
    void                    SetSharedMaxIndex(USHORT nInd)  { nSharedMaxIndex = nInd; }
    USHORT                  GetEntryIndex();
};

#endif

<|endoftext|>


<commit_before>/*************************************************************************/
/*  sprite.cpp                                                           */
/*************************************************************************/
/*                       This file is part of:                           */
/*                           GODOT ENGINE                                */
/*                      https://godotengine.org                          */
/*************************************************************************/
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur.                 */
/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md)    */
/*                                                                       */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the       */
/* "Software"), to deal in the Software without restriction, including   */
/* without limitation the rights to use, copy, modify, merge, publish,   */
/* distribute, sublicense, and/or sell copies of the Software, and to    */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions:                                             */
/*                                                                       */
/* The above copyright notice and this permission notice shall be        */
/* included in all copies or substantial portions of the Software.       */
/*                                                                       */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
/*************************************************************************/

#include "sprite.h"
#include "core/core_string_names.h"
#include "os/os.h"
#include "scene/main/viewport.h"
#include "scene/scene_string_names.h"

Dictionary Sprite::_edit_get_state() const {
	Dictionary state = Node2D::_edit_get_state();
	state["offset"] = offset;
	return state;
}

void Sprite::_edit_set_state(const Dictionary &p_state) {
	Node2D::_edit_set_state(p_state);
	set_offset(p_state["offset"]);
}

void Sprite::_edit_set_pivot(const Point2 &p_pivot) {
	set_offset(get_offset() - p_pivot);
	set_position(get_transform().xform(p_pivot));
}

Point2 Sprite::_edit_get_pivot() const {
	return Vector2();
}

bool Sprite::_edit_use_pivot() const {
	return true;
}

void Sprite::_get_rects(Rect2 &r_src_rect, Rect2 &r_dst_rect, bool &r_filter_clip) const {

	Size2 s;
	r_filter_clip = false;

	if (region) {

		s = region_rect.size;
		r_src_rect = region_rect;
		r_filter_clip = region_filter_clip;
	} else {
		s = Size2(texture->get_size());
		s = s / Size2(hframes, vframes);

		r_src_rect.size = s;
		r_src_rect.position.x += float(frame % hframes) * s.x;
		r_src_rect.position.y += float(frame / hframes) * s.y;
	}

	Point2 ofs = offset;
	if (centered)
		ofs -= s / 2;
	if (Engine::get_singleton()->get_use_pixel_snap()) {
		ofs = ofs.floor();
	}

	r_dst_rect = Rect2(ofs, s);

	if (hflip)
		r_dst_rect.size.x = -r_dst_rect.size.x;
	if (vflip)
		r_dst_rect.size.y = -r_dst_rect.size.y;
}

void Sprite::_notification(int p_what) {

	switch (p_what) {

		case NOTIFICATION_DRAW: {

			if (texture.is_null())
				return;

			RID ci = get_canvas_item();

			/*
			texture->draw(ci,Point2());
			break;
			*/

			Rect2 src_rect, dst_rect;
			bool filter_clip;
			_get_rects(src_rect, dst_rect, filter_clip);
			texture->draw_rect_region(ci, dst_rect, src_rect, Color(1, 1, 1), false, normal_map, filter_clip);

		} break;
	}
}

void Sprite::set_texture(const Ref<Texture> &p_texture) {

	if (p_texture == texture)
		return;
	texture = p_texture;
	update();
	emit_signal("texture_changed");
	item_rect_changed();
	_change_notify("texture");
}

void Sprite::set_normal_map(const Ref<Texture> &p_texture) {

	normal_map = p_texture;
	update();
}

Ref<Texture> Sprite::get_normal_map() const {

	return normal_map;
}

Ref<Texture> Sprite::get_texture() const {

	return texture;
}

void Sprite::set_centered(bool p_center) {

	centered = p_center;
	update();
	item_rect_changed();
}

bool Sprite::is_centered() const {

	return centered;
}

void Sprite::set_offset(const Point2 &p_offset) {

	offset = p_offset;
	update();
	item_rect_changed();
	_change_notify("offset");
}
Point2 Sprite::get_offset() const {

	return offset;
}

void Sprite::set_flip_h(bool p_flip) {

	hflip = p_flip;
	update();
}
bool Sprite::is_flipped_h() const {

	return hflip;
}

void Sprite::set_flip_v(bool p_flip) {

	vflip = p_flip;
	update();
}
bool Sprite::is_flipped_v() const {

	return vflip;
}

void Sprite::set_region(bool p_region) {

	if (p_region == region)
		return;

	region = p_region;
	update();
}

bool Sprite::is_region() const {

	return region;
}

void Sprite::set_region_rect(const Rect2 &p_region_rect) {

	if (region_rect == p_region_rect)
		return;

	region_rect = p_region_rect;

	if (region)
		item_rect_changed();

	_change_notify("region_rect");
}

Rect2 Sprite::get_region_rect() const {

	return region_rect;
}

void Sprite::set_region_filter_clip(bool p_enable) {
	region_filter_clip = p_enable;
	update();
}

bool Sprite::is_region_filter_clip_enabled() const {
	return region_filter_clip;
}

void Sprite::set_frame(int p_frame) {

	ERR_FAIL_INDEX(p_frame, vframes * hframes);

	if (frame != p_frame)
		item_rect_changed();

	frame = p_frame;

	_change_notify("frame");
	emit_signal(SceneStringNames::get_singleton()->frame_changed);
}

int Sprite::get_frame() const {

	return frame;
}

void Sprite::set_vframes(int p_amount) {

	ERR_FAIL_COND(p_amount < 1);
	vframes = p_amount;
	update();
	item_rect_changed();
	_change_notify();
}
int Sprite::get_vframes() const {

	return vframes;
}

void Sprite::set_hframes(int p_amount) {

	ERR_FAIL_COND(p_amount < 1);
	hframes = p_amount;
	update();
	item_rect_changed();
	_change_notify();
}
int Sprite::get_hframes() const {

	return hframes;
}

bool Sprite::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const {

	if (texture.is_null())
		return false;

	Rect2 src_rect, dst_rect;
	bool filter_clip;
	_get_rects(src_rect, dst_rect, filter_clip);

	if (!dst_rect.has_point(p_point))
		return false;

	Vector2 q = ((p_point - dst_rect.position) / dst_rect.size) * src_rect.size + src_rect.position;

	Ref<Image> image = texture->get_data();
	ERR_FAIL_COND_V(image.is_null(), false);

	image->lock();
	const Color c = image->get_pixel((int)q.x, (int)q.y);
	image->unlock();

	return c.a > 0.01;
}

Rect2 Sprite::get_rect() const {

	if (texture.is_null())
		return Rect2(0, 0, 1, 1);
	/*
	if (texture.is_null())
		return CanvasItem::_edit_get_rect();
	*/

	Size2i s;

	if (region) {

		s = region_rect.size;
	} else {
		s = texture->get_size();
		s = s / Point2(hframes, vframes);
	}

	Point2 ofs = offset;
	if (centered)
		ofs -= s / 2;

	if (s == Size2(0, 0))
		s = Size2(1, 1);

	return Rect2(ofs, s);
}

void Sprite::_validate_property(PropertyInfo &property) const {

	if (property.name == "frame") {

		property.hint = PROPERTY_HINT_SPRITE_FRAME;

		property.hint_string = "0," + itos(vframes * hframes - 1) + ",1";
	}
}

void Sprite::_bind_methods() {

	ClassDB::bind_method(D_METHOD("set_texture", "texture"), &Sprite::set_texture);
	ClassDB::bind_method(D_METHOD("get_texture"), &Sprite::get_texture);

	ClassDB::bind_method(D_METHOD("set_normal_map", "normal_map"), &Sprite::set_normal_map);
	ClassDB::bind_method(D_METHOD("get_normal_map"), &Sprite::get_normal_map);

	ClassDB::bind_method(D_METHOD("set_centered", "centered"), &Sprite::set_centered);
	ClassDB::bind_method(D_METHOD("is_centered"), &Sprite::is_centered);

	ClassDB::bind_method(D_METHOD("set_offset", "offset"), &Sprite::set_offset);
	ClassDB::bind_method(D_METHOD("get_offset"), &Sprite::get_offset);

	ClassDB::bind_method(D_METHOD("set_flip_h", "flip_h"), &Sprite::set_flip_h);
	ClassDB::bind_method(D_METHOD("is_flipped_h"), &Sprite::is_flipped_h);

	ClassDB::bind_method(D_METHOD("set_flip_v", "flip_v"), &Sprite::set_flip_v);
	ClassDB::bind_method(D_METHOD("is_flipped_v"), &Sprite::is_flipped_v);

	ClassDB::bind_method(D_METHOD("set_region", "enabled"), &Sprite::set_region);
	ClassDB::bind_method(D_METHOD("is_region"), &Sprite::is_region);

	ClassDB::bind_method(D_METHOD("set_region_rect", "rect"), &Sprite::set_region_rect);
	ClassDB::bind_method(D_METHOD("get_region_rect"), &Sprite::get_region_rect);

	ClassDB::bind_method(D_METHOD("set_region_filter_clip", "enabled"), &Sprite::set_region_filter_clip);
	ClassDB::bind_method(D_METHOD("is_region_filter_clip_enabled"), &Sprite::is_region_filter_clip_enabled);

	ClassDB::bind_method(D_METHOD("set_frame", "frame"), &Sprite::set_frame);
	ClassDB::bind_method(D_METHOD("get_frame"), &Sprite::get_frame);

	ClassDB::bind_method(D_METHOD("set_vframes", "vframes"), &Sprite::set_vframes);
	ClassDB::bind_method(D_METHOD("get_vframes"), &Sprite::get_vframes);

	ClassDB::bind_method(D_METHOD("set_hframes", "hframes"), &Sprite::set_hframes);
	ClassDB::bind_method(D_METHOD("get_hframes"), &Sprite::get_hframes);

	ClassDB::bind_method(D_METHOD("get_rect"), &Sprite::get_rect);

	ADD_SIGNAL(MethodInfo("frame_changed"));
	ADD_SIGNAL(MethodInfo("texture_changed"));

	ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture");
	ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "normal_map", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_normal_map", "get_normal_map");
	ADD_GROUP("Offset", "");
	ADD_PROPERTYNO(PropertyInfo(Variant::BOOL, "centered"), "set_centered", "is_centered");
	ADD_PROPERTYNZ(PropertyInfo(Variant::VECTOR2, "offset"), "set_offset", "get_offset");
	ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "flip_h"), "set_flip_h", "is_flipped_h");
	ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "flip_v"), "set_flip_v", "is_flipped_v");
	ADD_GROUP("Animation", "");
	ADD_PROPERTYNO(PropertyInfo(Variant::INT, "vframes", PROPERTY_HINT_RANGE, "1,16384,1"), "set_vframes", "get_vframes");
	ADD_PROPERTYNO(PropertyInfo(Variant::INT, "hframes", PROPERTY_HINT_RANGE, "1,16384,1"), "set_hframes", "get_hframes");
	ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "frame", PROPERTY_HINT_SPRITE_FRAME), "set_frame", "get_frame");

	ADD_GROUP("Region", "region_");
	ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "region_enabled"), "set_region", "is_region");
	ADD_PROPERTYNZ(PropertyInfo(Variant::RECT2, "region_rect"), "set_region_rect", "get_region_rect");
	ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "region_filter_clip"), "set_region_filter_clip", "is_region_filter_clip_enabled");
}

Sprite::Sprite() {

	centered = true;
	hflip = false;
	vflip = false;
	region = false;
	region_filter_clip = false;

	frame = 0;

	vframes = 1;
	hframes = 1;
}
<commit_msg>Fix selection of Sprites using AtlasTexture in the editor.<commit_after>/*************************************************************************/
/*  sprite.cpp                                                           */
/*************************************************************************/
/*                       This file is part of:                           */
/*                           GODOT ENGINE                                */
/*                      https://godotengine.org                          */
/*************************************************************************/
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur.                 */
/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md)    */
/*                                                                       */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the       */
/* "Software"), to deal in the Software without restriction, including   */
/* without limitation the rights to use, copy, modify, merge, publish,   */
/* distribute, sublicense, and/or sell copies of the Software, and to    */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions:                                             */
/*                                                                       */
/* The above copyright notice and this permission notice shall be        */
/* included in all copies or substantial portions of the Software.       */
/*                                                                       */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
/*************************************************************************/

#include "sprite.h"
#include "core/core_string_names.h"
#include "os/os.h"
#include "scene/main/viewport.h"
#include "scene/scene_string_names.h"

Dictionary Sprite::_edit_get_state() const {
	Dictionary state = Node2D::_edit_get_state();
	state["offset"] = offset;
	return state;
}

void Sprite::_edit_set_state(const Dictionary &p_state) {
	Node2D::_edit_set_state(p_state);
	set_offset(p_state["offset"]);
}

void Sprite::_edit_set_pivot(const Point2 &p_pivot) {
	set_offset(get_offset() - p_pivot);
	set_position(get_transform().xform(p_pivot));
}

Point2 Sprite::_edit_get_pivot() const {
	return Vector2();
}

bool Sprite::_edit_use_pivot() const {
	return true;
}

void Sprite::_get_rects(Rect2 &r_src_rect, Rect2 &r_dst_rect, bool &r_filter_clip) const {

	Size2 s;
	r_filter_clip = false;

	if (region) {

		s = region_rect.size;
		r_src_rect = region_rect;
		r_filter_clip = region_filter_clip;
	} else {
		s = Size2(texture->get_size());
		s = s / Size2(hframes, vframes);

		r_src_rect.size = s;
		r_src_rect.position.x += float(frame % hframes) * s.x;
		r_src_rect.position.y += float(frame / hframes) * s.y;
	}

	Point2 ofs = offset;
	if (centered)
		ofs -= s / 2;
	if (Engine::get_singleton()->get_use_pixel_snap()) {
		ofs = ofs.floor();
	}

	r_dst_rect = Rect2(ofs, s);

	if (hflip)
		r_dst_rect.size.x = -r_dst_rect.size.x;
	if (vflip)
		r_dst_rect.size.y = -r_dst_rect.size.y;
}

void Sprite::_notification(int p_what) {

	switch (p_what) {

		case NOTIFICATION_DRAW: {

			if (texture.is_null())
				return;

			RID ci = get_canvas_item();

			/*
			texture->draw(ci,Point2());
			break;
			*/

			Rect2 src_rect, dst_rect;
			bool filter_clip;
			_get_rects(src_rect, dst_rect, filter_clip);
			texture->draw_rect_region(ci, dst_rect, src_rect, Color(1, 1, 1), false, normal_map, filter_clip);

		} break;
	}
}

void Sprite::set_texture(const Ref<Texture> &p_texture) {

	if (p_texture == texture)
		return;
	texture = p_texture;
	update();
	emit_signal("texture_changed");
	item_rect_changed();
	_change_notify("texture");
}

void Sprite::set_normal_map(const Ref<Texture> &p_texture) {

	normal_map = p_texture;
	update();
}

Ref<Texture> Sprite::get_normal_map() const {

	return normal_map;
}

Ref<Texture> Sprite::get_texture() const {

	return texture;
}

void Sprite::set_centered(bool p_center) {

	centered = p_center;
	update();
	item_rect_changed();
}

bool Sprite::is_centered() const {

	return centered;
}

void Sprite::set_offset(const Point2 &p_offset) {

	offset = p_offset;
	update();
	item_rect_changed();
	_change_notify("offset");
}
Point2 Sprite::get_offset() const {

	return offset;
}

void Sprite::set_flip_h(bool p_flip) {

	hflip = p_flip;
	update();
}
bool Sprite::is_flipped_h() const {

	return hflip;
}

void Sprite::set_flip_v(bool p_flip) {

	vflip = p_flip;
	update();
}
bool Sprite::is_flipped_v() const {

	return vflip;
}

void Sprite::set_region(bool p_region) {

	if (p_region == region)
		return;

	region = p_region;
	update();
}

bool Sprite::is_region() const {

	return region;
}

void Sprite::set_region_rect(const Rect2 &p_region_rect) {

	if (region_rect == p_region_rect)
		return;

	region_rect = p_region_rect;

	if (region)
		item_rect_changed();

	_change_notify("region_rect");
}

Rect2 Sprite::get_region_rect() const {

	return region_rect;
}

void Sprite::set_region_filter_clip(bool p_enable) {
	region_filter_clip = p_enable;
	update();
}

bool Sprite::is_region_filter_clip_enabled() const {
	return region_filter_clip;
}

void Sprite::set_frame(int p_frame) {

	ERR_FAIL_INDEX(p_frame, vframes * hframes);

	if (frame != p_frame)
		item_rect_changed();

	frame = p_frame;

	_change_notify("frame");
	emit_signal(SceneStringNames::get_singleton()->frame_changed);
}

int Sprite::get_frame() const {

	return frame;
}

void Sprite::set_vframes(int p_amount) {

	ERR_FAIL_COND(p_amount < 1);
	vframes = p_amount;
	update();
	item_rect_changed();
	_change_notify();
}
int Sprite::get_vframes() const {

	return vframes;
}

void Sprite::set_hframes(int p_amount) {

	ERR_FAIL_COND(p_amount < 1);
	hframes = p_amount;
	update();
	item_rect_changed();
	_change_notify();
}
int Sprite::get_hframes() const {

	return hframes;
}

bool Sprite::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const {

	if (texture.is_null())
		return false;

	Rect2 src_rect, dst_rect;
	bool filter_clip;
	_get_rects(src_rect, dst_rect, filter_clip);

	if (!dst_rect.has_point(p_point))
		return false;

	Vector2 q = ((p_point - dst_rect.position) / dst_rect.size) * src_rect.size + src_rect.position;

	Ref<Image> image;
	Ref<AtlasTexture> atlasTexture = texture;
	if (atlasTexture.is_null()) {
		image = texture->get_data();
	} else {
		ERR_FAIL_COND_V(atlasTexture->get_atlas().is_null(), false);

		image = atlasTexture->get_atlas()->get_data();

		Rect2 region = atlasTexture->get_region();
		Rect2 margin = atlasTexture->get_margin();

		q -= margin.position;

		if ((q.x > region.size.width) || (q.y > region.size.height)) {
			return false;
		}

		q += region.position;
	}

	ERR_FAIL_COND_V(image.is_null(), false);

	image->lock();
	const Color c = image->get_pixel((int)q.x, (int)q.y);
	image->unlock();

	return c.a > 0.01;
}

Rect2 Sprite::get_rect() const {

	if (texture.is_null())
		return Rect2(0, 0, 1, 1);
	/*
	if (texture.is_null())
		return CanvasItem::_edit_get_rect();
	*/

	Size2i s;

	if (region) {

		s = region_rect.size;
	} else {
		s = texture->get_size();
		s = s / Point2(hframes, vframes);
	}

	Point2 ofs = offset;
	if (centered)
		ofs -= s / 2;

	if (s == Size2(0, 0))
		s = Size2(1, 1);

	return Rect2(ofs, s);
}

void Sprite::_validate_property(PropertyInfo &property) const {

	if (property.name == "frame") {

		property.hint = PROPERTY_HINT_SPRITE_FRAME;

		property.hint_string = "0," + itos(vframes * hframes - 1) + ",1";
	}
}

void Sprite::_bind_methods() {

	ClassDB::bind_method(D_METHOD("set_texture", "texture"), &Sprite::set_texture);
	ClassDB::bind_method(D_METHOD("get_texture"), &Sprite::get_texture);

	ClassDB::bind_method(D_METHOD("set_normal_map", "normal_map"), &Sprite::set_normal_map);
	ClassDB::bind_method(D_METHOD("get_normal_map"), &Sprite::get_normal_map);

	ClassDB::bind_method(D_METHOD("set_centered", "centered"), &Sprite::set_centered);
	ClassDB::bind_method(D_METHOD("is_centered"), &Sprite::is_centered);

	ClassDB::bind_method(D_METHOD("set_offset", "offset"), &Sprite::set_offset);
	ClassDB::bind_method(D_METHOD("get_offset"), &Sprite::get_offset);

	ClassDB::bind_method(D_METHOD("set_flip_h", "flip_h"), &Sprite::set_flip_h);
	ClassDB::bind_method(D_METHOD("is_flipped_h"), &Sprite::is_flipped_h);

	ClassDB::bind_method(D_METHOD("set_flip_v", "flip_v"), &Sprite::set_flip_v);
	ClassDB::bind_method(D_METHOD("is_flipped_v"), &Sprite::is_flipped_v);

	ClassDB::bind_method(D_METHOD("set_region", "enabled"), &Sprite::set_region);
	ClassDB::bind_method(D_METHOD("is_region"), &Sprite::is_region);

	ClassDB::bind_method(D_METHOD("set_region_rect", "rect"), &Sprite::set_region_rect);
	ClassDB::bind_method(D_METHOD("get_region_rect"), &Sprite::get_region_rect);

	ClassDB::bind_method(D_METHOD("set_region_filter_clip", "enabled"), &Sprite::set_region_filter_clip);
	ClassDB::bind_method(D_METHOD("is_region_filter_clip_enabled"), &Sprite::is_region_filter_clip_enabled);

	ClassDB::bind_method(D_METHOD("set_frame", "frame"), &Sprite::set_frame);
	ClassDB::bind_method(D_METHOD("get_frame"), &Sprite::get_frame);

	ClassDB::bind_method(D_METHOD("set_vframes", "vframes"), &Sprite::set_vframes);
	ClassDB::bind_method(D_METHOD("get_vframes"), &Sprite::get_vframes);

	ClassDB::bind_method(D_METHOD("set_hframes", "hframes"), &Sprite::set_hframes);
	ClassDB::bind_method(D_METHOD("get_hframes"), &Sprite::get_hframes);

	ClassDB::bind_method(D_METHOD("get_rect"), &Sprite::get_rect);

	ADD_SIGNAL(MethodInfo("frame_changed"));
	ADD_SIGNAL(MethodInfo("texture_changed"));

	ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture");
	ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "normal_map", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_normal_map", "get_normal_map");
	ADD_GROUP("Offset", "");
	ADD_PROPERTYNO(PropertyInfo(Variant::BOOL, "centered"), "set_centered", "is_centered");
	ADD_PROPERTYNZ(PropertyInfo(Variant::VECTOR2, "offset"), "set_offset", "get_offset");
	ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "flip_h"), "set_flip_h", "is_flipped_h");
	ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "flip_v"), "set_flip_v", "is_flipped_v");
	ADD_GROUP("Animation", "");
	ADD_PROPERTYNO(PropertyInfo(Variant::INT, "vframes", PROPERTY_HINT_RANGE, "1,16384,1"), "set_vframes", "get_vframes");
	ADD_PROPERTYNO(PropertyInfo(Variant::INT, "hframes", PROPERTY_HINT_RANGE, "1,16384,1"), "set_hframes", "get_hframes");
	ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "frame", PROPERTY_HINT_SPRITE_FRAME), "set_frame", "get_frame");

	ADD_GROUP("Region", "region_");
	ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "region_enabled"), "set_region", "is_region");
	ADD_PROPERTYNZ(PropertyInfo(Variant::RECT2, "region_rect"), "set_region_rect", "get_region_rect");
	ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "region_filter_clip"), "set_region_filter_clip", "is_region_filter_clip_enabled");
}

Sprite::Sprite() {

	centered = true;
	hflip = false;
	vflip = false;
	region = false;
	region_filter_clip = false;

	frame = 0;

	vframes = 1;
	hframes = 1;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <memory>
#include <algorithm>
#include <chrono>
#include <random>
#include <iomanip>
#include <fenwick.hpp>

inline int lambda(uint64_t word) { return 63 - __builtin_clzll(word); }
inline int rho(uint64_t word) { return __builtin_ctzll(word); }
inline uint64_t mask_rho(uint64_t word) { return word & (-word); }
inline uint64_t mask_lambda(uint64_t word) { return 0x8000000000000000 >> __builtin_clzll(word); }
inline uint64_t clear_rho(uint64_t word) { return word & (word - 1ULL); }

class FenwickL
{
public:
    static constexpr size_t LEAF_MAXVAL = 64; // Leaves store values up to 64
    static constexpr size_t LEAF_BITSIZE = 9; // log2(65);

protected:
    std::unique_ptr<uint64_t[]> tree;
    std::unique_ptr<size_t[]> level;
    size_t size, levels;

public:
    FenwickL(uint64_t sequence[], size_t size):
        tree(std::make_unique<size_t[]>(size)),
        level(std::make_unique<uint64_t[]>(lambda(size) + 2)),
        size(size),
        levels(lambda(size)+1)
    {
        size_t level_size = lambda(size) + 2;

        level[0] = 0;
        for (size_t i = 1; i < level_size; i++)
            level[i] = ((size + (1<<(i-1))) / (1<<i)) + level[i-1];

        const size_t levels = level_size - 1;
        for (size_t l = 0; l < levels; l++) {
            for (size_t node = 1<<l; node <= size; node += 1 << (l+1)) {
                size_t sequence_idx = node-1;
                uint64_t value = sequence[sequence_idx];
                for (size_t j = 0; j < l; j++) {
                    sequence_idx >>= 1;
                    value += tree[level[j] + sequence_idx];
                }

                tree[level[l] + (node >> (l+1))] = value;
            }
        }
    }

    // top-down: from the "root" to idx
    uint64_t reversed_prefix(size_t idx) const
    {
        uint64_t sum = 0;
        size_t index = 0;

        while (idx != index) {
            index += mask_lambda(idx ^ index);

            const int height = rho(index);
            const size_t level_idx = index >> (1 + height);
            sum += tree[level[height] + level_idx];
        }

        return sum;
    }

    // bottom-up: classical parent relationship and conversion
    uint64_t fenwick_prefix(size_t idx) const
    {
        uint64_t sum = 0;

        while (idx != 0) {
            const int height = rho(idx);
            const size_t level_idx = idx >> (1 + height);
            sum += tree[level[height] + level_idx];

            idx = clear_rho(idx);
        }

        return sum;
    }

    // bottom-up: level-order parent formulae
    uint64_t level_prefix(size_t idx) const
    {
        uint64_t sum = 0;
        int height = rho(idx);
        size_t level_idx = idx >> (1 + height);

        while (level_idx < level[height+1] && height < levels) {
            sum += tree[level[height] + level_idx];

            const int next = rho(level_idx) + 1;
            height += next;
            level_idx >>= next;
        }

        return sum;
    }

};

class FenwickF
{
public:
    static constexpr size_t LEAF_MAXVAL = 64; // Leaves store values up to 64
    static constexpr size_t LEAF_BITSIZE = 9; // log2(65);

protected:
    std::unique_ptr<uint64_t[]> tree;
    size_t size;

public:
    FenwickF(uint64_t sequence[], size_t size):
        tree(std::make_unique<size_t[]>(size)),
        size(size)
    {
        std::copy_n(sequence, size, tree.get());

        for (size_t m = 2; m <= size; m <<= 1) {
            for (size_t idx = m; idx <= size; idx += m)
                tree[idx - 1] += tree[idx - m/2 - 1];
        }
    }

    // top-down: from the "root" to idx
    uint64_t reversed_prefix(size_t idx) const
    {
        uint64_t sum = 0;
        size_t index = 0;

        while (idx != index) {
            index += mask_lambda(idx ^ index);
            sum += tree[index - 1];
        }

        return sum;
    }

    // bottom-up: classical parent relationship and conversion
    uint64_t fenwick_prefix(size_t idx) const
    {
        uint64_t sum = 0;

        while (idx != 0) {
            sum += tree[idx - 1];
            idx = clear_rho(idx);
        }

        return sum;
    }

};

int main(int argc, char *argv[])
{
    using namespace hft;
    using namespace std;
    using namespace std::chrono;

    size_t SIZE, QUERIES;
    istringstream(argv[1]) >> SIZE;
    istringstream(argv[2]) >> QUERIES;
    double C = 1. / QUERIES;

    random_device rd;
    mt19937 mte(rd());
    uniform_int_distribution<size_t> idxdist(0, SIZE);
    uniform_int_distribution<size_t> valdist(0, 64);

    auto sequence = make_unique<uint64_t[]>(SIZE);
    for (size_t i = 0; i < SIZE; ++i)
        sequence[i] = valdist(mte);

    FenwickF fenF(sequence.get(), SIZE);
    FenwickL fenL(sequence.get(), SIZE);
    // hft::fenwick::FixedL<64> realL(sequence.get(), SIZE);
    // hft::fenwick::FixedF<64> realF(sequence.get(), SIZE);

    uint64_t tmp = 0;
    high_resolution_clock::time_point begin, end;

    // repeat the benchmark few times to see if the results are consistent
    for (size_t i = 0; i < 3; i++) {
        cout << "fenF fenwick_prefix... " << flush;
        begin = high_resolution_clock::now();
        for (size_t i = 0; i < QUERIES; ++i)
            tmp ^= fenF.fenwick_prefix(idxdist(mte));
        end = high_resolution_clock::now();
        auto fenf_fenwick_prefix = duration_cast<nanoseconds>(end-begin).count();
        cout << fenf_fenwick_prefix * C << " ns\n";

        cout << "fenF reversed_prefix... " << flush;
        begin = high_resolution_clock::now();
        for (size_t i = 0; i < QUERIES; ++i)
            tmp ^= fenF.reversed_prefix(idxdist(mte));
        end = high_resolution_clock::now();
        auto fenf_reversed_prefix = duration_cast<nanoseconds>(end-begin).count();
        cout << fenf_reversed_prefix * C << " ns\n";

        cout << "fenL fenwick_prefix... " << flush;
        begin = high_resolution_clock::now();
        for (size_t i = 0; i < QUERIES; ++i)
            tmp ^= fenL.fenwick_prefix(idxdist(mte));
        end = high_resolution_clock::now();
        auto fenl_fenwick_prefix = duration_cast<nanoseconds>(end-begin).count();
        cout << fenl_fenwick_prefix * C << " ns\n";

        cout << "fenL reversed_prefix... " << flush;
        begin = high_resolution_clock::now();
        for (size_t i = 0; i < QUERIES; ++i)
            tmp ^= fenL.reversed_prefix(idxdist(mte));
        end = high_resolution_clock::now();
        auto fenl_reversed_prefix = duration_cast<nanoseconds>(end-begin).count();
        cout << fenl_reversed_prefix * C << " ns\n";

        cout << "fenL level_prefix... " << flush;
        begin = high_resolution_clock::now();
        for (size_t i = 0; i < QUERIES; ++i)
            tmp ^= fenL.level_prefix(idxdist(mte));
        end = high_resolution_clock::now();
        auto fenl_level_prefix = duration_cast<nanoseconds>(end-begin).count();
        cout << fenl_level_prefix * C << " ns\n";

        // cout << "realF prefix... " << flush;
        // begin = high_resolution_clock::now();
        // for (size_t i = 0; i < QUERIES; ++i)
        //     tmp ^= realF.prefix(idxdist(mte));
        // end = high_resolution_clock::now();
        // auto realF_prefix = duration_cast<nanoseconds>(end-begin).count();
        // cout << realF_prefix * C << " ns\n";

        // cout << "realL prefix... " << flush;
        // begin = high_resolution_clock::now();
        // for (size_t i = 0; i < QUERIES; ++i)
        //     tmp ^= realL.prefix(idxdist(mte));
        // end = high_resolution_clock::now();
        // auto realL_prefix = duration_cast<nanoseconds>(end-begin).count();
        // cout << realL_prefix * C << " ns\n";

        cout << "\n";
    }

    const volatile uint64_t __attribute__((unused)) unused = tmp;

    // Check if everything is working
    // for (size_t i = 0; i < SIZE; ++i) {
    //     auto a = fenF.fenwick_prefix(i);
    //     auto b = fenF.reversed_prefix(i);
    //     auto c = fenL.fenwick_prefix(i);
    //     auto d = fenL.reversed_prefix(i);
    //     auto e = fenL.level_prefix(i);
    //     auto f = realF.prefix(i);
    //     auto g = realL.prefix(i);

    //     bool error = a != b || b != c || c != d || d != e || e != f || f != g;

    //     if (error) {
    //         cout << "idx(" << i << ") => "
    //                   << a << " " << b << " " << c << " " << d << " " << e << " " << f << " " << g << "\n";

    //     }
    // }

    return 0;
}
<commit_msg>Cleanup<commit_after>#include <iostream>
#include <memory>
#include <algorithm>
#include <chrono>
#include <random>
#include <iomanip>
//#include <fenwick.hpp>

inline int lambda(uint64_t word) { return 63 - __builtin_clzll(word); }
inline int rho(uint64_t word) { return __builtin_ctzll(word); }
inline uint64_t mask_rho(uint64_t word) { return word & (-word); }
inline uint64_t mask_lambda(uint64_t word) { return 0x8000000000000000 >> __builtin_clzll(word); }
inline uint64_t clear_rho(uint64_t word) { return word & (word - 1ULL); }

class FenwickL
{
public:
    static constexpr size_t LEAF_MAXVAL = 64; // Leaves store values up to 64
    static constexpr size_t LEAF_BITSIZE = 9; // log2(65);

protected:
    std::unique_ptr<uint64_t[]> tree;
    std::unique_ptr<size_t[]> level;
    size_t size, levels;

public:
    FenwickL(uint64_t sequence[], size_t size):
        tree(std::make_unique<size_t[]>(size)),
        level(std::make_unique<uint64_t[]>(lambda(size) + 2)),
        size(size),
        levels(lambda(size)+1)
    {
        size_t level_size = lambda(size) + 2;

        level[0] = 0;
        for (size_t i = 1; i < level_size; i++)
            level[i] = ((size + (1<<(i-1))) / (1<<i)) + level[i-1];

        const size_t levels = level_size - 1;
        for (size_t l = 0; l < levels; l++) {
            for (size_t node = 1<<l; node <= size; node += 1 << (l+1)) {
                size_t sequence_idx = node-1;
                uint64_t value = sequence[sequence_idx];
                for (size_t j = 0; j < l; j++) {
                    sequence_idx >>= 1;
                    value += tree[level[j] + sequence_idx];
                }

                tree[level[l] + (node >> (l+1))] = value;
            }
        }
    }

    // top-down: from the "root" to idx
    uint64_t reversed_prefix(size_t idx) const
    {
        uint64_t sum = 0;
        size_t index = 0;

        while (idx != index) {
            index += mask_lambda(idx ^ index);

            const int height = rho(index);
            const size_t level_idx = index >> (1 + height);
            sum += tree[level[height] + level_idx];
        }

        return sum;
    }

    // bottom-up: classical parent relationship and conversion
    uint64_t fenwick_prefix(size_t idx) const
    {
        uint64_t sum = 0;

        while (idx != 0) {
            const int height = rho(idx);
            const size_t level_idx = idx >> (1 + height);
            sum += tree[level[height] + level_idx];

            idx = clear_rho(idx);
        }

        return sum;
    }

    // bottom-up: level-order parent formulae
    uint64_t level_prefix(size_t idx) const
    {
        uint64_t sum = 0;
        int height = rho(idx);
        size_t level_idx = idx >> (1 + height);

        while (level_idx < level[height+1] && height < levels) {
            sum += tree[level[height] + level_idx];

            const int next = rho(level_idx) + 1;
            height += next;
            level_idx >>= next;
        }

        return sum;
    }

};

class FenwickF
{
public:
    static constexpr size_t LEAF_MAXVAL = 64; // Leaves store values up to 64
    static constexpr size_t LEAF_BITSIZE = 9; // log2(65);

protected:
    std::unique_ptr<uint64_t[]> tree;
    size_t size;

public:
    FenwickF(uint64_t sequence[], size_t size):
        tree(std::make_unique<size_t[]>(size)),
        size(size)
    {
        std::copy_n(sequence, size, tree.get());

        for (size_t m = 2; m <= size; m <<= 1) {
            for (size_t idx = m; idx <= size; idx += m)
                tree[idx - 1] += tree[idx - m/2 - 1];
        }
    }

    // top-down: from the "root" to idx
    uint64_t reversed_prefix(size_t idx) const
    {
        uint64_t sum = 0;
        size_t index = 0;

        while (idx != index) {
            index += mask_lambda(idx ^ index);
            sum += tree[index - 1];
        }

        return sum;
    }

    // bottom-up: classical parent relationship and conversion
    uint64_t fenwick_prefix(size_t idx) const
    {
        uint64_t sum = 0;

        while (idx != 0) {
            sum += tree[idx - 1];
            idx = clear_rho(idx);
        }

        return sum;
    }

};

int main(int argc, char *argv[])
{
    using namespace hft;
    using namespace std;
    using namespace std::chrono;

    size_t SIZE, QUERIES;
    istringstream(argv[1]) >> SIZE;
    istringstream(argv[2]) >> QUERIES;
    double C = 1. / QUERIES;

    random_device rd;
    mt19937 mte(rd());
    uniform_int_distribution<size_t> idxdist(0, SIZE);
    uniform_int_distribution<size_t> valdist(0, 64);

    auto sequence = make_unique<uint64_t[]>(SIZE);
    for (size_t i = 0; i < SIZE; ++i)
        sequence[i] = valdist(mte);

    FenwickF fenF(sequence.get(), SIZE);
    FenwickL fenL(sequence.get(), SIZE);
    // hft::fenwick::FixedL<64> realL(sequence.get(), SIZE);
    // hft::fenwick::FixedF<64> realF(sequence.get(), SIZE);

    uint64_t tmp = 0;
    high_resolution_clock::time_point begin, end;

    // repeat the benchmark few times to see if the results are consistent
    for (size_t i = 0; i < 3; i++) {
        cout << "fenF fenwick_prefix... " << flush;
        begin = high_resolution_clock::now();
        for (size_t i = 0; i < QUERIES; ++i)
            tmp ^= fenF.fenwick_prefix(idxdist(mte));
        end = high_resolution_clock::now();
        auto fenf_fenwick_prefix = duration_cast<nanoseconds>(end-begin).count();
        cout << fenf_fenwick_prefix * C << " ns\n";

        cout << "fenF reversed_prefix... " << flush;
        begin = high_resolution_clock::now();
        for (size_t i = 0; i < QUERIES; ++i)
            tmp ^= fenF.reversed_prefix(idxdist(mte));
        end = high_resolution_clock::now();
        auto fenf_reversed_prefix = duration_cast<nanoseconds>(end-begin).count();
        cout << fenf_reversed_prefix * C << " ns\n";

        cout << "fenL fenwick_prefix... " << flush;
        begin = high_resolution_clock::now();
        for (size_t i = 0; i < QUERIES; ++i)
            tmp ^= fenL.fenwick_prefix(idxdist(mte));
        end = high_resolution_clock::now();
        auto fenl_fenwick_prefix = duration_cast<nanoseconds>(end-begin).count();
        cout << fenl_fenwick_prefix * C << " ns\n";

        cout << "fenL reversed_prefix... " << flush;
        begin = high_resolution_clock::now();
        for (size_t i = 0; i < QUERIES; ++i)
            tmp ^= fenL.reversed_prefix(idxdist(mte));
        end = high_resolution_clock::now();
        auto fenl_reversed_prefix = duration_cast<nanoseconds>(end-begin).count();
        cout << fenl_reversed_prefix * C << " ns\n";

        cout << "fenL level_prefix... " << flush;
        begin = high_resolution_clock::now();
        for (size_t i = 0; i < QUERIES; ++i)
            tmp ^= fenL.level_prefix(idxdist(mte));
        end = high_resolution_clock::now();
        auto fenl_level_prefix = duration_cast<nanoseconds>(end-begin).count();
        cout << fenl_level_prefix * C << " ns\n";

        // cout << "realF prefix... " << flush;
        // begin = high_resolution_clock::now();
        // for (size_t i = 0; i < QUERIES; ++i)
        //     tmp ^= realF.prefix(idxdist(mte));
        // end = high_resolution_clock::now();
        // auto realF_prefix = duration_cast<nanoseconds>(end-begin).count();
        // cout << realF_prefix * C << " ns\n";

        // cout << "realL prefix... " << flush;
        // begin = high_resolution_clock::now();
        // for (size_t i = 0; i < QUERIES; ++i)
        //     tmp ^= realL.prefix(idxdist(mte));
        // end = high_resolution_clock::now();
        // auto realL_prefix = duration_cast<nanoseconds>(end-begin).count();
        // cout << realL_prefix * C << " ns\n";

        cout << "\n";
    }

    const volatile uint64_t __attribute__((unused)) unused = tmp;

    // Check if everything is working
    // for (size_t i = 0; i < SIZE; ++i) {
    //     auto a = fenF.fenwick_prefix(i);
    //     auto b = fenF.reversed_prefix(i);
    //     auto c = fenL.fenwick_prefix(i);
    //     auto d = fenL.reversed_prefix(i);
    //     auto e = fenL.level_prefix(i);
    //     auto f = realF.prefix(i);
    //     auto g = realL.prefix(i);

    //     bool error = a != b || b != c || c != d || d != e || e != f || f != g;

    //     if (error) {
    //         cout << "idx(" << i << ") => "
    //                   << a << " " << b << " " << c << " " << d << " " << e << " " << f << " " << g << "\n";

    //     }
    // }

    return 0;
}
<|endoftext|>


<commit_before>#include <algorithm>
#include <array>
#include <cassert>
#include <chrono>
#include <ctime>
#include <functional>
#include <iostream>
#include <random>
#include <string>
#include <type_traits>
#include <utility>
#include <vector>
#include <cpp-sort/sorters.h>

#ifdef _WIN32
    #include <intrin.h>
    #define rdtsc __rdtsc
#else
    #ifdef __i386__
        static __inline__ unsigned long long rdtsc() {
            unsigned long long int x;
            __asm__ volatile(".byte 0x0f, 0x31" : "=A" (x));
            return x;
        }
    #elif defined(__x86_64__)
        static __inline__ unsigned long long rdtsc(){
            unsigned hi, lo;
            __asm__ __volatile__("rdtsc" : "=a"(lo), "=d"(hi));
            return ((unsigned long long) lo) | (((unsigned long long) hi) << 32);
        }
    #else
        #error no rdtsc implementation
    #endif
#endif

inline std::vector<int> shuffled_int(size_t size, std::mt19937_64& rng) {
    std::vector<int> v; v.reserve(size);
    for (int i = 0; i < size; ++i) v.push_back(i);
    std::shuffle(v.begin(), v.end(), rng);
    return v;
}

inline std::vector<int> shuffled_16_values_int(size_t size, std::mt19937_64& rng) {
    std::vector<int> v; v.reserve(size);
    for (int i = 0; i < size; ++i) v.push_back(i % 16);
    std::shuffle(v.begin(), v.end(), rng);
    return v;
}

inline std::vector<int> all_equal_int(size_t size, std::mt19937_64&) {
    std::vector<int> v; v.reserve(size);
    for (int i = 0; i < size; ++i) v.push_back(0);
    return v;
}

inline std::vector<int> ascending_int(size_t size, std::mt19937_64&) {
    std::vector<int> v; v.reserve(size);
    for (int i = 0; i < size; ++i) v.push_back(i);
    return v;
}

inline std::vector<int> descending_int(size_t size, std::mt19937_64&) {
    std::vector<int> v; v.reserve(size);
    for (int i = size - 1; i >= 0; --i) v.push_back(i);
    return v;
}

inline std::vector<int> pipe_organ_int(size_t size, std::mt19937_64&) {
    std::vector<int> v; v.reserve(size);
    for (int i = 0; i < size/2; ++i) v.push_back(i);
    for (int i = size/2; i < size; ++i) v.push_back(size - i);
    return v;
}

inline std::vector<int> push_front_int(size_t size, std::mt19937_64&) {
    std::vector<int> v; v.reserve(size);
    for (int i = 1; i < size; ++i) v.push_back(i);
    v.push_back(0);
    return v;
}

inline std::vector<int> push_middle_int(size_t size, std::mt19937_64&) {
    std::vector<int> v; v.reserve(size);
    for (int i = 0; i < size; ++i) {
        if (i != size/2) v.push_back(i);
    }
    v.push_back(size/2);
    return v;
}

inline std::vector<int> ascending_sawtooth_int(size_t size, std::mt19937_64&) {
    std::vector<int> v; v.reserve(size);
    int limit = size / log2(size) * 1.1;
    for (int i = 0; i < size; ++i) v.push_back(i % limit);
    return v;
}

inline std::vector<int> descending_sawtooth_int(size_t size, std::mt19937_64&) {
    std::vector<int> v; v.reserve(size);
    int limit = size / log2(size) * 1.1;
    for (int i = size - 1; i >= 0; --i) v.push_back(i % limit);
    return v;
}

inline std::vector<int> alternating_int(size_t size, std::mt19937_64&) {
    std::vector<int> v; v.reserve(size);
    for (int i = 0; i < size; ++i) v.push_back(i);
    for (int i = 0; i < size; i += 2) v[i] *= -1;
    return v;
}

inline std::vector<int> alternating_16_values_int(size_t size, std::mt19937_64&) {
    std::vector<int> v; v.reserve(size);
    for (int i = 0; i < size; ++i) v.push_back(i % 16);
    for (int i = 0; i < size; i += 2) v[i] *= -1;
    return v;
}

int main()
{
    auto seed = std::time(0);
    std::mt19937_64 el;

    using distr_f    = std::vector<int>(*)(size_t, std::mt19937_64&);
    using sort_f     = void(*)(std::vector<int>&);

    std::pair<std::string, distr_f> distributions[] = {
        { "shuffled_int",               shuffled_int                },
        { "shuffled_16_values_int",     shuffled_16_values_int      },
        { "all_equal_int",              all_equal_int               },
        { "ascending_int",              ascending_int               },
        { "descending_int",             descending_int              },
        { "pipe_organ_int",             pipe_organ_int              },
        { "push_front_int",             push_front_int              },
        { "push_middle_int",            push_middle_int             },
        { "ascending_sawtooth_int",     ascending_sawtooth_int      },
        { "descending_sawtooth_int",    descending_sawtooth_int     },
        { "alternating_int",            alternating_int             },
        { "alternating_16_values_int",  alternating_16_values_int   }
    };

    std::pair<std::string, sort_f> sorts[] = {
        { "heapsort",   cppsort::heap_sorter()              },
        { "introsort",  cppsort::std_sorter()               },
        { "pdqsort",    cppsort::pdq_sorter()               },
        { "vergesort",  cppsort::verge_sorter()             },
        { "timsort",    cppsort::tim_sorter()               },
        { "spreadsort", cppsort::integer_spread_sorter()    }
    };

    int sizes[] = { 1'000'000 };

    for (auto& distribution : distributions) {
        for (auto& sort : sorts) {
            el.seed(seed);

            for (auto size : sizes) {
                std::chrono::time_point<std::chrono::high_resolution_clock> total_start, total_end;
                std::vector<uint64_t> cycles;

                total_start = std::chrono::high_resolution_clock::now();
                total_end = std::chrono::high_resolution_clock::now();
                while (std::chrono::duration_cast<std::chrono::milliseconds>(total_end - total_start).count() < 10000) {
                    std::vector<int> vec = distribution.second(size, el);
                    uint64_t start = rdtsc();
                    sort.second(vec);
                    uint64_t end = rdtsc();
                    assert(std::is_sorted(vec.begin(), vec.end()));
                    cycles.push_back(double(end - start) / size + 0.5);
                    total_end = std::chrono::high_resolution_clock::now();
                }

                std::sort(cycles.begin(), cycles.end());

                std::cerr << size << " " << distribution.first << " " << sort.first << "\n";
                std::cout << size << " " << distribution.first << " " << sort.first << " ";
                for (uint64_t cycle : cycles) std::cout << cycle << " ";
                std::cout << "\n";
            }
        }
    }

    return 0;
}
<commit_msg>Make benchmark less tied to std::vector.<commit_after>#include <algorithm>
#include <array>
#include <cassert>
#include <chrono>
#include <ctime>
#include <functional>
#include <iostream>
#include <random>
#include <string>
#include <type_traits>
#include <utility>
#include <vector>
#include <cpp-sort/sorters.h>

#ifdef _WIN32
    #include <intrin.h>
    #define rdtsc __rdtsc
#else
    #ifdef __i386__
        static __inline__ unsigned long long rdtsc() {
            unsigned long long int x;
            __asm__ volatile(".byte 0x0f, 0x31" : "=A" (x));
            return x;
        }
    #elif defined(__x86_64__)
        static __inline__ unsigned long long rdtsc(){
            unsigned hi, lo;
            __asm__ __volatile__("rdtsc" : "=a"(lo), "=d"(hi));
            return ((unsigned long long) lo) | (((unsigned long long) hi) << 32);
        }
    #else
        #error no rdtsc implementation
    #endif
#endif

template<template<typename...> class Collection>
Collection<int> shuffled_int(size_t size, std::mt19937_64& rng) {
    std::vector<int> v; v.reserve(size);
    for (int i = 0; i < size; ++i) v.push_back(i);
    std::shuffle(v.begin(), v.end(), rng);
    return Collection<int>(std::begin(v), std::end(v));
}

template<template<typename...> class Collection>
Collection<int> shuffled_16_values_int(size_t size, std::mt19937_64& rng) {
    std::vector<int> v; v.reserve(size);
    for (int i = 0; i < size; ++i) v.push_back(i % 16);
    std::shuffle(v.begin(), v.end(), rng);
    return Collection<int>(std::begin(v), std::end(v));
}

template<template<typename...> class Collection>
Collection<int> all_equal_int(size_t size, std::mt19937_64&) {
    std::vector<int> v; v.reserve(size);
    for (int i = 0; i < size; ++i) v.push_back(0);
    return Collection<int>(std::begin(v), std::end(v));
}

template<template<typename...> class Collection>
Collection<int> ascending_int(size_t size, std::mt19937_64&) {
    std::vector<int> v; v.reserve(size);
    for (int i = 0; i < size; ++i) v.push_back(i);
    return Collection<int>(std::begin(v), std::end(v));
}

template<template<typename...> class Collection>
Collection<int> descending_int(size_t size, std::mt19937_64&) {
    std::vector<int> v; v.reserve(size);
    for (int i = size - 1; i >= 0; --i) v.push_back(i);
    return Collection<int>(std::begin(v), std::end(v));
}

template<template<typename...> class Collection>
Collection<int> pipe_organ_int(size_t size, std::mt19937_64&) {
    std::vector<int> v; v.reserve(size);
    for (int i = 0; i < size/2; ++i) v.push_back(i);
    for (int i = size/2; i < size; ++i) v.push_back(size - i);
    return Collection<int>(std::begin(v), std::end(v));
}

template<template<typename...> class Collection>
Collection<int> push_front_int(size_t size, std::mt19937_64&) {
    std::vector<int> v; v.reserve(size);
    for (int i = 1; i < size; ++i) v.push_back(i);
    v.push_back(0);
    return Collection<int>(std::begin(v), std::end(v));
}

template<template<typename...> class Collection>
Collection<int> push_middle_int(size_t size, std::mt19937_64&) {
    std::vector<int> v; v.reserve(size);
    for (int i = 0; i < size; ++i) {
        if (i != size/2) v.push_back(i);
    }
    v.push_back(size/2);
    return Collection<int>(std::begin(v), std::end(v));
}

template<template<typename...> class Collection>
Collection<int> ascending_sawtooth_int(size_t size, std::mt19937_64&) {
    std::vector<int> v; v.reserve(size);
    int limit = size / log2(size) * 1.1;
    for (int i = 0; i < size; ++i) v.push_back(i % limit);
    return Collection<int>(std::begin(v), std::end(v));
}

template<template<typename...> class Collection>
Collection<int> descending_sawtooth_int(size_t size, std::mt19937_64&) {
    std::vector<int> v; v.reserve(size);
    int limit = size / log2(size) * 1.1;
    for (int i = size - 1; i >= 0; --i) v.push_back(i % limit);
    return Collection<int>(std::begin(v), std::end(v));
}

template<template<typename...> class Collection>
Collection<int> alternating_int(size_t size, std::mt19937_64&) {
    std::vector<int> v; v.reserve(size);
    for (int i = 0; i < size; ++i) v.push_back(i);
    for (int i = 0; i < size; i += 2) v[i] *= -1;
    return Collection<int>(std::begin(v), std::end(v));
}

template<template<typename...> class Collection>
Collection<int> alternating_16_values_int(size_t size, std::mt19937_64&) {
    std::vector<int> v; v.reserve(size);
    for (int i = 0; i < size; ++i) v.push_back(i % 16);
    for (int i = 0; i < size; i += 2) v[i] *= -1;
    return Collection<int>(std::begin(v), std::end(v));
}

int main()
{
    auto seed = std::time(0);
    std::mt19937_64 el;

    using distr_f    = std::vector<int>(*)(size_t, std::mt19937_64&);
    using sort_f     = void(*)(std::vector<int>&);

    std::pair<std::string, distr_f> distributions[] = {
        { "shuffled_int",               shuffled_int                },
        { "shuffled_16_values_int",     shuffled_16_values_int      },
        { "all_equal_int",              all_equal_int               },
        { "ascending_int",              ascending_int               },
        { "descending_int",             descending_int              },
        { "pipe_organ_int",             pipe_organ_int              },
        { "push_front_int",             push_front_int              },
        { "push_middle_int",            push_middle_int             },
        { "ascending_sawtooth_int",     ascending_sawtooth_int      },
        { "descending_sawtooth_int",    descending_sawtooth_int     },
        { "alternating_int",            alternating_int             },
        { "alternating_16_values_int",  alternating_16_values_int   }
    };

    std::pair<std::string, sort_f> sorts[] = {
        { "heapsort",   cppsort::heap_sorter()      },
        { "introsort",  cppsort::std_sorter()       },
        { "pdqsort",    cppsort::pdq_sorter()       },
        { "vergesort",  cppsort::verge_sorter()     },
        { "timsort",    cppsort::tim_sorter()       },
        { "spreadsort", cppsort::spread_sorter()    }
    };

    int sizes[] = { 1'000'000 };

    for (auto& distribution : distributions) {
        for (auto& sort : sorts) {
            el.seed(seed);

            for (auto size : sizes) {
                std::chrono::time_point<std::chrono::high_resolution_clock> total_start, total_end;
                std::vector<uint64_t> cycles;

                total_start = std::chrono::high_resolution_clock::now();
                total_end = std::chrono::high_resolution_clock::now();
                while (std::chrono::duration_cast<std::chrono::milliseconds>(total_end - total_start).count() < 10000) {
                    std::vector<int> vec = distribution.second(size, el);
                    uint64_t start = rdtsc();
                    sort.second(vec);
                    uint64_t end = rdtsc();
                    assert(std::is_sorted(vec.begin(), vec.end()));
                    cycles.push_back(double(end - start) / size + 0.5);
                    total_end = std::chrono::high_resolution_clock::now();
                }

                std::sort(cycles.begin(), cycles.end());

                std::cerr << size << " " << distribution.first << " " << sort.first << "\n";
                std::cout << size << " " << distribution.first << " " << sort.first << " ";
                for (uint64_t cycle : cycles) std::cout << cycle << " ";
                std::cout << "\n";
            }
        }
    }

    return 0;
}
<|endoftext|>


<commit_before>/*************************************************************************/
/*  javascript_main.cpp                                                  */
/*************************************************************************/
/*                       This file is part of:                           */
/*                           GODOT ENGINE                                */
/*                      https://godotengine.org                          */
/*************************************************************************/
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur.                 */
/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md)    */
/*                                                                       */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the       */
/* "Software"), to deal in the Software without restriction, including   */
/* without limitation the rights to use, copy, modify, merge, publish,   */
/* distribute, sublicense, and/or sell copies of the Software, and to    */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions:                                             */
/*                                                                       */
/* The above copyright notice and this permission notice shall be        */
/* included in all copies or substantial portions of the Software.       */
/*                                                                       */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
/*************************************************************************/

#include "emscripten.h"
#include "io/resource_loader.h"
#include "main/main.h"
#include "os_javascript.h"

OS_JavaScript *os = NULL;

static void main_loop() {

	os->main_loop_iterate();
}

extern "C" EMSCRIPTEN_KEEPALIVE void main_after_fs_sync(char *p_idbfs_err) {

	String idbfs_err = String::utf8(p_idbfs_err);
	if (!idbfs_err.empty()) {
		print_line("IndexedDB not available: " + idbfs_err);
	}
	os->set_idbfs_available(idbfs_err.empty());
	// Ease up compatibility
	ResourceLoader::set_abort_on_missing_resources(false);
	Main::start();
	os->main_loop_begin();
	emscripten_set_main_loop(main_loop, 0, false);
}

int main(int argc, char *argv[]) {

	printf("let it go dude!\n");

	// sync from persistent state into memory and then
	// run the 'main_after_fs_sync' function
	/* clang-format off */
	EM_ASM(
		FS.mkdir('/userfs');
		FS.mount(IDBFS, {}, '/userfs');
		FS.syncfs(true, function(err) {
			ccall('main_after_fs_sync', null, ['string'], [err ? err.message : ""])
		});
	);
	/* clang-format on */

	os = new OS_JavaScript(argv[0], NULL);
	Error err = Main::setup(argv[0], argc - 1, &argv[1]);

	return 0;
	// continued async in main_after_fs_sync() from syncfs() callback
}
<commit_msg>Javascript: Remove weird log<commit_after>/*************************************************************************/
/*  javascript_main.cpp                                                  */
/*************************************************************************/
/*                       This file is part of:                           */
/*                           GODOT ENGINE                                */
/*                      https://godotengine.org                          */
/*************************************************************************/
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur.                 */
/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md)    */
/*                                                                       */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the       */
/* "Software"), to deal in the Software without restriction, including   */
/* without limitation the rights to use, copy, modify, merge, publish,   */
/* distribute, sublicense, and/or sell copies of the Software, and to    */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions:                                             */
/*                                                                       */
/* The above copyright notice and this permission notice shall be        */
/* included in all copies or substantial portions of the Software.       */
/*                                                                       */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
/*************************************************************************/

#include "emscripten.h"
#include "io/resource_loader.h"
#include "main/main.h"
#include "os_javascript.h"

OS_JavaScript *os = NULL;

static void main_loop() {

	os->main_loop_iterate();
}

extern "C" EMSCRIPTEN_KEEPALIVE void main_after_fs_sync(char *p_idbfs_err) {

	String idbfs_err = String::utf8(p_idbfs_err);
	if (!idbfs_err.empty()) {
		print_line("IndexedDB not available: " + idbfs_err);
	}
	os->set_idbfs_available(idbfs_err.empty());
	// Ease up compatibility
	ResourceLoader::set_abort_on_missing_resources(false);
	Main::start();
	os->main_loop_begin();
	emscripten_set_main_loop(main_loop, 0, false);
}

int main(int argc, char *argv[]) {

	// sync from persistent state into memory and then
	// run the 'main_after_fs_sync' function
	/* clang-format off */
	EM_ASM(
		FS.mkdir('/userfs');
		FS.mount(IDBFS, {}, '/userfs');
		FS.syncfs(true, function(err) {
			ccall('main_after_fs_sync', null, ['string'], [err ? err.message : ""])
		});
	);
	/* clang-format on */

	os = new OS_JavaScript(argv[0], NULL);
	Error err = Main::setup(argv[0], argc - 1, &argv[1]);

	return 0;
	// continued async in main_after_fs_sync() from syncfs() callback
}
<|endoftext|>


<commit_before>/*

Copyright 2015-2019 Igor Petrovic

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

*/

#include "board/Board.h"
#include "board/common/constants/DigitalIn.h"
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include "board/common/digital/Input.h"
#include "board/common/Map.h"
#include "core/src/general/BitManipulation.h"
#include "Pins.h"

namespace
{
    volatile uint8_t digitalInBuffer[DIGITAL_IN_BUFFER_SIZE][DIGITAL_IN_ARRAY_SIZE];
    uint8_t          digitalInBufferReadOnly[DIGITAL_IN_ARRAY_SIZE];

#ifdef NUMBER_OF_BUTTON_COLUMNS
    volatile uint8_t activeInColumn;
#endif

    volatile uint8_t dIn_head;
    volatile uint8_t dIn_tail;
    volatile uint8_t dIn_count;
}    // namespace

namespace Board
{
    namespace interface
    {
        namespace digital
        {
            namespace input
            {
                bool getButtonState(uint8_t buttonID)
                {
#ifdef NUMBER_OF_BUTTON_COLUMNS
                    uint8_t row = buttonID / NUMBER_OF_BUTTON_COLUMNS;
                    uint8_t column = buttonID % NUMBER_OF_BUTTON_COLUMNS;

                    return BIT_READ(digitalInBufferReadOnly[column], row);
#else
                    uint8_t arrayIndex = buttonID / 8;
                    uint8_t buttonIndex = buttonID - 8 * arrayIndex;

                    return BIT_READ(digitalInBufferReadOnly[arrayIndex], buttonIndex);
#endif
                }

                uint8_t getEncoderPair(uint8_t buttonID)
                {
#ifdef NUMBER_OF_BUTTON_COLUMNS
                    uint8_t row = buttonID / NUMBER_OF_BUTTON_COLUMNS;
                    uint8_t column = buttonID % NUMBER_OF_BUTTON_COLUMNS;

                    if (row % 2)
                        row -= 1;    //uneven row, get info from previous (even) row

                    return (row * NUMBER_OF_BUTTON_COLUMNS) / 2 + column;
#else
                    return buttonID / 2;
#endif
                }

                uint8_t getEncoderPairState(uint8_t encoderID)
                {
#ifdef NUMBER_OF_BUTTON_COLUMNS
                    uint8_t column = encoderID % NUMBER_OF_BUTTON_COLUMNS;
                    uint8_t row = (encoderID / NUMBER_OF_BUTTON_COLUMNS) * 2;
                    uint8_t pairState = (digitalInBufferReadOnly[column] >> row) & 0x03;
#else
                    uint8_t buttonID = encoderID * 2;

                    uint8_t pairState = getButtonState(buttonID);
                    pairState <<= 1;
                    pairState |= getButtonState(buttonID + 1);
#endif

                    return pairState;
                }

                bool isDataAvailable()
                {
                    if (dIn_count)
                    {
#ifdef __AVR__
                        ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
#endif
                        {
                            if (++dIn_tail == DIGITAL_IN_BUFFER_SIZE)
                                dIn_tail = 0;

                            for (int i = 0; i < DIGITAL_IN_ARRAY_SIZE; i++)
                                digitalInBufferReadOnly[i] = digitalInBuffer[dIn_tail][i];

                            dIn_count--;
                        }

                        return true;
                    }

                    return false;
                }

                namespace detail
                {
#if defined(SR_DIN_CLK_PORT) && defined(SR_DIN_LATCH_PORT) && defined(SR_DIN_DATA_PORT) && !defined(NUMBER_OF_BUTTON_COLUMNS) && !defined(NUMBER_OF_BUTTON_ROWS)
                    inline void storeDigitalIn()
                    {
                        CORE_AVR_PIN_SET_LOW(SR_DIN_CLK_PORT, SR_DIN_CLK_PIN);
                        CORE_AVR_PIN_SET_LOW(SR_DIN_LATCH_PORT, SR_DIN_LATCH_PIN);
                        _NOP();

                        CORE_AVR_PIN_SET_HIGH(SR_DIN_LATCH_PORT, SR_DIN_LATCH_PIN);

                        for (int j = 0; j < NUMBER_OF_IN_SR; j++)
                        {
                            for (int i = 0; i < NUMBER_OF_IN_SR_INPUTS; i++)
                            {
                                CORE_AVR_PIN_SET_LOW(SR_DIN_CLK_PORT, SR_DIN_CLK_PIN);
                                _NOP();
                                BIT_WRITE(digitalInBuffer[dIn_head][0], 7 - i, !CORE_AVR_PIN_READ(SR_DIN_DATA_PORT, SR_DIN_DATA_PIN));
                                CORE_AVR_PIN_SET_HIGH(SR_DIN_CLK_PORT, SR_DIN_CLK_PIN);
                            }
                        }
                    }
#elif defined(NUMBER_OF_BUTTON_COLUMNS) && defined(NUMBER_OF_BUTTON_ROWS)
                    inline void activateInputColumn()
                    {
                        BIT_READ(Board::map::inMatrixColumn(activeInColumn), 0) ? CORE_AVR_PIN_SET_HIGH(DEC_DM_A0_PORT, DEC_DM_A0_PIN) : CORE_AVR_PIN_SET_LOW(DEC_DM_A0_PORT, DEC_DM_A0_PIN);
                        BIT_READ(Board::map::inMatrixColumn(activeInColumn), 1) ? CORE_AVR_PIN_SET_HIGH(DEC_DM_A1_PORT, DEC_DM_A1_PIN) : CORE_AVR_PIN_SET_LOW(DEC_DM_A1_PORT, DEC_DM_A1_PIN);
                        BIT_READ(Board::map::inMatrixColumn(activeInColumn), 2) ? CORE_AVR_PIN_SET_HIGH(DEC_DM_A2_PORT, DEC_DM_A2_PIN) : CORE_AVR_PIN_SET_LOW(DEC_DM_A2_PORT, DEC_DM_A2_PIN);

                        if (++activeInColumn == NUMBER_OF_BUTTON_COLUMNS)
                            activeInColumn = 0;
                    }

                    ///
                    /// Acquires data for all buttons connected in currently active button matrix column by
                    /// reading inputs from shift register.
                    ///
                    inline void storeDigitalIn()
                    {
                        for (int i = 0; i < NUMBER_OF_BUTTON_COLUMNS; i++)
                        {
                            activateInputColumn();
                            _NOP();

                            CORE_AVR_PIN_SET_LOW(SR_DIN_CLK_PORT, SR_DIN_CLK_PIN);
                            CORE_AVR_PIN_SET_LOW(SR_DIN_LATCH_PORT, SR_DIN_LATCH_PIN);
                            _NOP();

                            CORE_AVR_PIN_SET_HIGH(SR_DIN_LATCH_PORT, SR_DIN_LATCH_PIN);

                            for (int j = 0; j < NUMBER_OF_BUTTON_ROWS; j++)
                            {
                                CORE_AVR_PIN_SET_LOW(SR_DIN_CLK_PORT, SR_DIN_CLK_PIN);
                                _NOP();
                                BIT_WRITE(digitalInBuffer[dIn_head][i], Board::map::inMatrixRow(j), !CORE_AVR_PIN_READ(SR_DIN_DATA_PORT, SR_DIN_DATA_PIN));
                                CORE_AVR_PIN_SET_HIGH(SR_DIN_CLK_PORT, SR_DIN_CLK_PIN);
                            }
                        }
                    }
#else
                    namespace
                    {
                        core::CORE_ARCH::pins::mcuPin_t pin;
                    }

                    inline void storeDigitalIn()
                    {
                        for (int i = 0; i < DIGITAL_IN_ARRAY_SIZE; i++)
                        {
                            for (int j = 0; j < 8; j++)
                            {
                                uint8_t buttonIndex = i * 8 + j;

                                if (buttonIndex >= MAX_NUMBER_OF_BUTTONS)
                                    break;    //done

                                pin = Board::map::button(buttonIndex);

                                BIT_WRITE(digitalInBuffer[dIn_head][i], j, !CORE_AVR_PIN_READ(*pin.port, pin.pin));
                            }
                        }
                    }
#endif

                    void checkDigitalInputs()
                    {
                        if (dIn_count < DIGITAL_IN_BUFFER_SIZE)
                        {
                            if (++dIn_head == DIGITAL_IN_BUFFER_SIZE)
                                dIn_head = 0;

                            storeDigitalIn();

                            dIn_count++;
                        }
                    }
                }    // namespace detail
            }        // namespace input
        }            // namespace digital
    }                // namespace interface
}    // namespace Board<commit_msg>fix handling of 74HC165 in daisy chain configuration<commit_after>/*

Copyright 2015-2019 Igor Petrovic

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

*/

#include "board/Board.h"
#include "board/common/constants/DigitalIn.h"
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include "board/common/digital/Input.h"
#include "board/common/Map.h"
#include "core/src/general/BitManipulation.h"
#include "Pins.h"

namespace
{
    volatile uint8_t digitalInBuffer[DIGITAL_IN_BUFFER_SIZE][DIGITAL_IN_ARRAY_SIZE];
    uint8_t          digitalInBufferReadOnly[DIGITAL_IN_ARRAY_SIZE];

#ifdef NUMBER_OF_BUTTON_COLUMNS
    volatile uint8_t activeInColumn;
#endif

    volatile uint8_t dIn_head;
    volatile uint8_t dIn_tail;
    volatile uint8_t dIn_count;
}    // namespace

namespace Board
{
    namespace interface
    {
        namespace digital
        {
            namespace input
            {
                bool getButtonState(uint8_t buttonID)
                {
#ifdef NUMBER_OF_BUTTON_COLUMNS
                    uint8_t row = buttonID / NUMBER_OF_BUTTON_COLUMNS;
                    uint8_t column = buttonID % NUMBER_OF_BUTTON_COLUMNS;

                    return BIT_READ(digitalInBufferReadOnly[column], row);
#else
                    uint8_t arrayIndex = buttonID / 8;
                    uint8_t buttonIndex = buttonID - 8 * arrayIndex;

                    return BIT_READ(digitalInBufferReadOnly[arrayIndex], buttonIndex);
#endif
                }

                uint8_t getEncoderPair(uint8_t buttonID)
                {
#ifdef NUMBER_OF_BUTTON_COLUMNS
                    uint8_t row = buttonID / NUMBER_OF_BUTTON_COLUMNS;
                    uint8_t column = buttonID % NUMBER_OF_BUTTON_COLUMNS;

                    if (row % 2)
                        row -= 1;    //uneven row, get info from previous (even) row

                    return (row * NUMBER_OF_BUTTON_COLUMNS) / 2 + column;
#else
                    return buttonID / 2;
#endif
                }

                uint8_t getEncoderPairState(uint8_t encoderID)
                {
#ifdef NUMBER_OF_BUTTON_COLUMNS
                    uint8_t column = encoderID % NUMBER_OF_BUTTON_COLUMNS;
                    uint8_t row = (encoderID / NUMBER_OF_BUTTON_COLUMNS) * 2;
                    uint8_t pairState = (digitalInBufferReadOnly[column] >> row) & 0x03;
#else
                    uint8_t buttonID = encoderID * 2;

                    uint8_t pairState = getButtonState(buttonID);
                    pairState <<= 1;
                    pairState |= getButtonState(buttonID + 1);
#endif

                    return pairState;
                }

                bool isDataAvailable()
                {
                    if (dIn_count)
                    {
#ifdef __AVR__
                        ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
#endif
                        {
                            if (++dIn_tail == DIGITAL_IN_BUFFER_SIZE)
                                dIn_tail = 0;

                            for (int i = 0; i < DIGITAL_IN_ARRAY_SIZE; i++)
                                digitalInBufferReadOnly[i] = digitalInBuffer[dIn_tail][i];

                            dIn_count--;
                        }

                        return true;
                    }

                    return false;
                }

                namespace detail
                {
#if defined(SR_DIN_CLK_PORT) && defined(SR_DIN_LATCH_PORT) && defined(SR_DIN_DATA_PORT) && !defined(NUMBER_OF_BUTTON_COLUMNS) && !defined(NUMBER_OF_BUTTON_ROWS)
                    inline void storeDigitalIn()
                    {
                        CORE_AVR_PIN_SET_LOW(SR_DIN_CLK_PORT, SR_DIN_CLK_PIN);
                        CORE_AVR_PIN_SET_LOW(SR_DIN_LATCH_PORT, SR_DIN_LATCH_PIN);
                        _NOP();

                        CORE_AVR_PIN_SET_HIGH(SR_DIN_LATCH_PORT, SR_DIN_LATCH_PIN);

                        for (int j = 0; j < NUMBER_OF_IN_SR; j++)
                        {
                            for (int i = 0; i < NUMBER_OF_IN_SR_INPUTS; i++)
                            {
                                CORE_AVR_PIN_SET_LOW(SR_DIN_CLK_PORT, SR_DIN_CLK_PIN);
                                _NOP();
                                BIT_WRITE(digitalInBuffer[dIn_head][j], 7 - i, !CORE_AVR_PIN_READ(SR_DIN_DATA_PORT, SR_DIN_DATA_PIN));
                                CORE_AVR_PIN_SET_HIGH(SR_DIN_CLK_PORT, SR_DIN_CLK_PIN);
                            }
                        }
                    }
#elif defined(NUMBER_OF_BUTTON_COLUMNS) && defined(NUMBER_OF_BUTTON_ROWS)
                    inline void activateInputColumn()
                    {
                        BIT_READ(Board::map::inMatrixColumn(activeInColumn), 0) ? CORE_AVR_PIN_SET_HIGH(DEC_DM_A0_PORT, DEC_DM_A0_PIN) : CORE_AVR_PIN_SET_LOW(DEC_DM_A0_PORT, DEC_DM_A0_PIN);
                        BIT_READ(Board::map::inMatrixColumn(activeInColumn), 1) ? CORE_AVR_PIN_SET_HIGH(DEC_DM_A1_PORT, DEC_DM_A1_PIN) : CORE_AVR_PIN_SET_LOW(DEC_DM_A1_PORT, DEC_DM_A1_PIN);
                        BIT_READ(Board::map::inMatrixColumn(activeInColumn), 2) ? CORE_AVR_PIN_SET_HIGH(DEC_DM_A2_PORT, DEC_DM_A2_PIN) : CORE_AVR_PIN_SET_LOW(DEC_DM_A2_PORT, DEC_DM_A2_PIN);

                        if (++activeInColumn == NUMBER_OF_BUTTON_COLUMNS)
                            activeInColumn = 0;
                    }

                    ///
                    /// Acquires data for all buttons connected in currently active button matrix column by
                    /// reading inputs from shift register.
                    ///
                    inline void storeDigitalIn()
                    {
                        for (int i = 0; i < NUMBER_OF_BUTTON_COLUMNS; i++)
                        {
                            activateInputColumn();
                            _NOP();

                            CORE_AVR_PIN_SET_LOW(SR_DIN_CLK_PORT, SR_DIN_CLK_PIN);
                            CORE_AVR_PIN_SET_LOW(SR_DIN_LATCH_PORT, SR_DIN_LATCH_PIN);
                            _NOP();

                            CORE_AVR_PIN_SET_HIGH(SR_DIN_LATCH_PORT, SR_DIN_LATCH_PIN);

                            for (int j = 0; j < NUMBER_OF_BUTTON_ROWS; j++)
                            {
                                CORE_AVR_PIN_SET_LOW(SR_DIN_CLK_PORT, SR_DIN_CLK_PIN);
                                _NOP();
                                BIT_WRITE(digitalInBuffer[dIn_head][i], Board::map::inMatrixRow(j), !CORE_AVR_PIN_READ(SR_DIN_DATA_PORT, SR_DIN_DATA_PIN));
                                CORE_AVR_PIN_SET_HIGH(SR_DIN_CLK_PORT, SR_DIN_CLK_PIN);
                            }
                        }
                    }
#else
                    namespace
                    {
                        core::CORE_ARCH::pins::mcuPin_t pin;
                    }

                    inline void storeDigitalIn()
                    {
                        for (int i = 0; i < DIGITAL_IN_ARRAY_SIZE; i++)
                        {
                            for (int j = 0; j < 8; j++)
                            {
                                uint8_t buttonIndex = i * 8 + j;

                                if (buttonIndex >= MAX_NUMBER_OF_BUTTONS)
                                    break;    //done

                                pin = Board::map::button(buttonIndex);

                                BIT_WRITE(digitalInBuffer[dIn_head][i], j, !CORE_AVR_PIN_READ(*pin.port, pin.pin));
                            }
                        }
                    }
#endif

                    void checkDigitalInputs()
                    {
                        if (dIn_count < DIGITAL_IN_BUFFER_SIZE)
                        {
                            if (++dIn_head == DIGITAL_IN_BUFFER_SIZE)
                                dIn_head = 0;

                            storeDigitalIn();

                            dIn_count++;
                        }
                    }
                }    // namespace detail
            }        // namespace input
        }            // namespace digital
    }                // namespace interface
}    // namespace Board<|endoftext|>