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

#ifndef INCLUDED_I18NPOOL_LANG_H
#include <i18npool/lang.h>
#endif
#include <list>

class SwTxtNode;
class Point;
class MultiSelection;
typedef std::list< xub_StrLen > PositionList;

#define SPACING_PRECISION_FACTOR 100

/*************************************************************************
 *                class SwScanner
 * Hilfsklasse, die beim Spellen die Worte im gewuenschten Bereich
 * nacheinander zur Verfuegung stellt.
 *************************************************************************/

class SwScanner
{
    XubString aWord;
    const SwTxtNode& rNode;
    xub_StrLen nStartPos;
    xub_StrLen nEndPos;
    xub_StrLen nBegin;
    xub_StrLen nLen;
    LanguageType aCurrLang;
    USHORT nWordType;
    BOOL bClip;

public:
    SwScanner( const SwTxtNode& rNd, USHORT nWordType,
               xub_StrLen nStart, xub_StrLen nEnde, BOOL bClip = FALSE );

    // This next word function tries to find the language for the next word
    // It should currently _not_ be used for spell checking, and works only for
    // ! bReverse
    BOOL NextWord();

    const XubString& GetWord() const    { return aWord; }

    xub_StrLen GetBegin() const         { return nBegin; }
    xub_StrLen GetEnd() const           { return nBegin + nLen; }
    xub_StrLen GetLen() const           { return nLen; }

    LanguageType GetCurrentLanguage() const {return aCurrLang;}
};

/*************************************************************************
 *                      class SwScriptInfo
 *
 * encapsultes information about script changes
 *************************************************************************/

class SwScriptInfo
{
private:
    SvXub_StrLens aScriptChg;
    SvBytes aScriptType;
    SvXub_StrLens aDirChg;
    SvBytes aDirType;
    SvXub_StrLens aKashida;
    SvXub_StrLens aCompChg;
    SvXub_StrLens aCompLen;
    SvXub_StrLens aHiddenChg;
    SvBytes aCompType;
    xub_StrLen nInvalidityPos;
    BYTE nDefaultDir;

    void UpdateBidiInfo( const String& rTxt );

public:
    enum CompType { KANA, SPECIAL_LEFT, SPECIAL_RIGHT, NONE };

    SwScriptInfo();
    ~SwScriptInfo();

    // determines script changes
    void InitScriptInfo( const SwTxtNode& rNode, sal_Bool bRTL );
    void InitScriptInfo( const SwTxtNode& rNode );

    // set/get position from which data is invalid
    inline void SetInvalidity( const xub_StrLen nPos );
    inline xub_StrLen GetInvalidity() const { return nInvalidityPos; };

    // get default direction for paragraph
    inline BYTE GetDefaultDir() const { return nDefaultDir; };

    // array operations, nCnt refers to array position
    inline USHORT CountScriptChg() const;
    inline xub_StrLen GetScriptChg( const USHORT nCnt ) const;
    inline BYTE GetScriptType( const USHORT nCnt ) const;

    inline USHORT CountDirChg() const;
    inline xub_StrLen GetDirChg( const USHORT nCnt ) const;
    inline BYTE GetDirType( const USHORT nCnt ) const;

    inline USHORT CountKashida() const;
    inline xub_StrLen GetKashida( const USHORT nCnt ) const;

    inline USHORT CountCompChg() const;
    inline xub_StrLen GetCompStart( const USHORT nCnt ) const;
    inline xub_StrLen GetCompLen( const USHORT nCnt ) const;
    inline BYTE GetCompType( const USHORT nCnt ) const;

    inline USHORT CountHiddenChg() const;
    inline xub_StrLen GetHiddenChg( const USHORT nCnt ) const;
    static void CalcHiddenRanges( const SwTxtNode& rNode,
                                                MultiSelection& rHiddenMulti );

    // "high" level operations, nPos refers to string position
    xub_StrLen NextScriptChg( const xub_StrLen nPos ) const;
    BYTE ScriptType( const xub_StrLen nPos ) const;

    // Returns the position of the next direction level change.
    // If bLevel is set, the position of the next level which is smaller
    // than the level at position nPos is returned. This is required to
    // obtain the end of a SwBidiPortion
    xub_StrLen NextDirChg( const xub_StrLen nPos,
                           const BYTE* pLevel = 0 ) const;
    BYTE DirType( const xub_StrLen nPos ) const;

#if OSL_DEBUG_LEVEL > 1
    BYTE CompType( const xub_StrLen nPos ) const;
#endif

    //
    // HIDDEN TEXT STUFF START
    //

/** Hidden text range information - static and non-version

    @descr  Determines if a given position is inside a hidden text range. The
            static version tries to obtain a valid SwScriptInfo object
            via the SwTxtNode, otherwise it calculates the values from scratch.
            The non-static version uses the internally cached informatio
            for the calculation.

    @param  rNode
                The text node.
    @param  nPos
                The given position that should be checked.
    @param  rnStartPos
                Return parameter for the start position of the hidden range.
                STRING_LEN if nPos is not inside a hidden range.
    @param  rnEndPos
                Return parameter for the end position of the hidden range.
                0 if nPos is not inside a hidden range.
    @param  rnEndPos
                Return parameter that contains all the hidden text ranges. Optional.
    @return
            returns true if there are any hidden characters in this paragraph.

*/
    static bool GetBoundsOfHiddenRange( const SwTxtNode& rNode, xub_StrLen nPos,
                                        xub_StrLen& rnStartPos, xub_StrLen& rnEndPos,
                                        PositionList* pList = 0 );
    bool GetBoundsOfHiddenRange(  xub_StrLen nPos, xub_StrLen& rnStartPos,
                                  xub_StrLen& rnEndPos, PositionList* pList = 0 ) const;

    static bool IsInHiddenRange( const SwTxtNode& rNode, xub_StrLen nPos );

/** Hidden text attribute handling

    @descr  Takes a string and either deletes the hidden ranges or sets
            a given character in place of the hidden characters.

    @param  rNode
                The text node.
    @param  nPos
                The string to modify.
    @param  cChar
                The character that should replace the hidden characters.
    @param  bDel
                If set, the hidden ranges will be deleted from the text node.
 */
    static USHORT MaskHiddenRanges( const SwTxtNode& rNode, XubString& rText,
                                    const xub_StrLen nStt, const xub_StrLen nEnd,
                                    const xub_Unicode cChar );

/** Hidden text attribute handling

    @descr  Takes a SwTxtNode and deletes the hidden ranges from the node.

    @param  rNode
                The text node.
 */
    static void DeleteHiddenRanges( SwTxtNode& rNode );

    //
    // HIDDEN TEXT STUFF END
    //

    // examines the range [ nStart, nStart + nEnd ] if there are kanas
    // returns start index of kana entry in array, otherwise USHRT_MAX
    USHORT HasKana( xub_StrLen nStart, const xub_StrLen nEnd ) const;

    // modifies the kerning array according to a given compress value
    long Compress( sal_Int32* pKernArray, xub_StrLen nIdx, xub_StrLen nLen,
                   const USHORT nCompress, const USHORT nFontHeight,
                   Point* pPoint = NULL ) const;

/** Performes a kashida justification on the kerning array

    @descr  Add some extra space for kashida justification to the
            positions in the kerning array.
    @param  pKernArray
                The printers kerning array. Optional.
    @param  pScrArray
                The screen kerning array. Optional.
    @param  nIdx
                Start referring to the paragraph.
    @param  nLen
                The number of characters to be considered.
    @param  nSpaceAdd
                The value which has to be added to a kashida opportunity.
    @return The number of kashida opportunities in the given range
*/
    USHORT KashidaJustify( sal_Int32* pKernArray ,sal_Int32* pScrArray,
                           xub_StrLen nIdx, xub_StrLen nLen,
                           long nSpaceAdd = 0 ) const;

/** Checks if language is one of the 16 Arabic languages

    @descr  Checks if language is one of the 16 Arabic languages
    @param  aLang
                The language which has to be checked.
    @return Returns if the language is an Arabic language
*/
    static BOOL IsArabicLanguage( LanguageType aLang );

/** Performes a thai justification on the kerning array

    @descr  Add some extra space for thai justification to the
            positions in the kerning array.
    @param  rTxt
                The String
    @param  pKernArray
                The printers kerning array. Optional.
    @param  pScrArray
                The screen kerning array. Optional.
    @param  nIdx
                Start referring to the paragraph.
    @param  nLen
                The number of characters to be considered.
    @param  nSpaceAdd
                The value which has to be added to the cells.
    @return The number of extra spaces in the given range
*/
    static USHORT ThaiJustify( const XubString& rTxt, sal_Int32* pKernArray,
                               sal_Int32* pScrArray, xub_StrLen nIdx,
                               xub_StrLen nLen, xub_StrLen nNumberOfBlanks = 0,
                               long nSpaceAdd = 0 );

    static SwScriptInfo* GetScriptInfo( const SwTxtNode& rNode,
                                        sal_Bool bAllowInvalid = sal_False );

    static BYTE WhichFont( xub_StrLen nIdx, const String* pTxt, const SwScriptInfo* pSI );
};

inline void SwScriptInfo::SetInvalidity( const xub_StrLen nPos )
{
    if ( nPos < nInvalidityPos )
        nInvalidityPos = nPos;
};
inline USHORT SwScriptInfo::CountScriptChg() const { return aScriptChg.Count(); }
inline xub_StrLen SwScriptInfo::GetScriptChg( const USHORT nCnt ) const
{
    ASSERT( nCnt < aScriptChg.Count(),"No ScriptChange today!");
    return aScriptChg[ nCnt ];
}
inline BYTE SwScriptInfo::GetScriptType( const xub_StrLen nCnt ) const
{
    ASSERT( nCnt < aScriptChg.Count(),"No ScriptType today!");
    return aScriptType[ nCnt ];
}

inline USHORT SwScriptInfo::CountDirChg() const { return aDirChg.Count(); }
inline xub_StrLen SwScriptInfo::GetDirChg( const USHORT nCnt ) const
{
    ASSERT( nCnt < aDirChg.Count(),"No DirChange today!");
    return aDirChg[ nCnt ];
}
inline BYTE SwScriptInfo::GetDirType( const xub_StrLen nCnt ) const
{
    ASSERT( nCnt < aDirChg.Count(),"No DirType today!");
    return aDirType[ nCnt ];
}

inline USHORT SwScriptInfo::CountKashida() const { return aKashida.Count(); }
inline xub_StrLen SwScriptInfo::GetKashida( const USHORT nCnt ) const
{
    ASSERT( nCnt < aKashida.Count(),"No Kashidas today!");
    return aKashida[ nCnt ];
}

inline USHORT SwScriptInfo::CountCompChg() const { return aCompChg.Count(); };
inline xub_StrLen SwScriptInfo::GetCompStart( const USHORT nCnt ) const
{
    ASSERT( nCnt < aCompChg.Count(),"No CompressionStart today!");
    return aCompChg[ nCnt ];
}
inline xub_StrLen SwScriptInfo::GetCompLen( const USHORT nCnt ) const
{
    ASSERT( nCnt < aCompChg.Count(),"No CompressionLen today!");
    return aCompLen[ nCnt ];
}

inline BYTE SwScriptInfo::GetCompType( const USHORT nCnt ) const
{
    ASSERT( nCnt < aCompChg.Count(),"No CompressionType today!");
    return aCompType[ nCnt ];
}

inline USHORT SwScriptInfo::CountHiddenChg() const { return aHiddenChg.Count(); };
inline xub_StrLen SwScriptInfo::GetHiddenChg( const USHORT nCnt ) const
{
    ASSERT( nCnt < aHiddenChg.Count(),"No HiddenChg today!");
    return aHiddenChg[ nCnt ];
}

#endif
<commit_msg>INTEGRATION: CWS swwarnings (1.18.162); FILE MERGED 2007/02/22 15:06:32 tl 1.18.162.1: #i69287# warning-free code<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: scriptinfo.hxx,v $
 *
 *  $Revision: 1.19 $
 *
 *  last change: $Author: hr $ $Date: 2007-09-27 08:58:02 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#ifndef _SCRIPTINFO_HXX
#define _SCRIPTINFO_HXX
#ifndef _SVSTDARR_HXX
#define _SVSTDARR_SHORTS
#define _SVSTDARR_BYTES
#define _SVSTDARR_USHORTS
#define _SVSTDARR_XUB_STRLEN
#include <svtools/svstdarr.hxx>
#endif

#ifndef INCLUDED_I18NPOOL_LANG_H
#include <i18npool/lang.h>
#endif
#include <list>

#include <errhdl.hxx>

class SwTxtNode;
class Point;
class MultiSelection;
typedef std::list< xub_StrLen > PositionList;

#define SPACING_PRECISION_FACTOR 100

/*************************************************************************
 *                class SwScanner
 * Hilfsklasse, die beim Spellen die Worte im gewuenschten Bereich
 * nacheinander zur Verfuegung stellt.
 *************************************************************************/

class SwScanner
{
    XubString aWord;
    const SwTxtNode& rNode;
    xub_StrLen nStartPos;
    xub_StrLen nEndPos;
    xub_StrLen nBegin;
    xub_StrLen nLen;
    LanguageType aCurrLang;
    USHORT nWordType;
    BOOL bClip;

public:
    SwScanner( const SwTxtNode& rNd, USHORT nWordType,
               xub_StrLen nStart, xub_StrLen nEnde, BOOL bClip = FALSE );

    // This next word function tries to find the language for the next word
    // It should currently _not_ be used for spell checking, and works only for
    // ! bReverse
    BOOL NextWord();

    const XubString& GetWord() const    { return aWord; }

    xub_StrLen GetBegin() const         { return nBegin; }
    xub_StrLen GetEnd() const           { return nBegin + nLen; }
    xub_StrLen GetLen() const           { return nLen; }

    LanguageType GetCurrentLanguage() const {return aCurrLang;}
};

/*************************************************************************
 *                      class SwScriptInfo
 *
 * encapsultes information about script changes
 *************************************************************************/

class SwScriptInfo
{
private:
    SvXub_StrLens aScriptChg;
    SvBytes aScriptType;
    SvXub_StrLens aDirChg;
    SvBytes aDirType;
    SvXub_StrLens aKashida;
    SvXub_StrLens aCompChg;
    SvXub_StrLens aCompLen;
    SvXub_StrLens aHiddenChg;
    SvBytes aCompType;
    xub_StrLen nInvalidityPos;
    BYTE nDefaultDir;

    void UpdateBidiInfo( const String& rTxt );

public:
    enum CompType { KANA, SPECIAL_LEFT, SPECIAL_RIGHT, NONE };

    SwScriptInfo();
    ~SwScriptInfo();

    // determines script changes
    void InitScriptInfo( const SwTxtNode& rNode, sal_Bool bRTL );
    void InitScriptInfo( const SwTxtNode& rNode );

    // set/get position from which data is invalid
    inline void SetInvalidity( const xub_StrLen nPos );
    inline xub_StrLen GetInvalidity() const { return nInvalidityPos; };

    // get default direction for paragraph
    inline BYTE GetDefaultDir() const { return nDefaultDir; };

    // array operations, nCnt refers to array position
    inline USHORT CountScriptChg() const;
    inline xub_StrLen GetScriptChg( const USHORT nCnt ) const;
    inline BYTE GetScriptType( const USHORT nCnt ) const;

    inline USHORT CountDirChg() const;
    inline xub_StrLen GetDirChg( const USHORT nCnt ) const;
    inline BYTE GetDirType( const USHORT nCnt ) const;

    inline USHORT CountKashida() const;
    inline xub_StrLen GetKashida( const USHORT nCnt ) const;

    inline USHORT CountCompChg() const;
    inline xub_StrLen GetCompStart( const USHORT nCnt ) const;
    inline xub_StrLen GetCompLen( const USHORT nCnt ) const;
    inline BYTE GetCompType( const USHORT nCnt ) const;

    inline USHORT CountHiddenChg() const;
    inline xub_StrLen GetHiddenChg( const USHORT nCnt ) const;
    static void CalcHiddenRanges( const SwTxtNode& rNode,
                                                MultiSelection& rHiddenMulti );

    // "high" level operations, nPos refers to string position
    xub_StrLen NextScriptChg( const xub_StrLen nPos ) const;
    BYTE ScriptType( const xub_StrLen nPos ) const;

    // Returns the position of the next direction level change.
    // If bLevel is set, the position of the next level which is smaller
    // than the level at position nPos is returned. This is required to
    // obtain the end of a SwBidiPortion
    xub_StrLen NextDirChg( const xub_StrLen nPos,
                           const BYTE* pLevel = 0 ) const;
    BYTE DirType( const xub_StrLen nPos ) const;

#if OSL_DEBUG_LEVEL > 1
    BYTE CompType( const xub_StrLen nPos ) const;
#endif

    //
    // HIDDEN TEXT STUFF START
    //

/** Hidden text range information - static and non-version

    @descr  Determines if a given position is inside a hidden text range. The
            static version tries to obtain a valid SwScriptInfo object
            via the SwTxtNode, otherwise it calculates the values from scratch.
            The non-static version uses the internally cached informatio
            for the calculation.

    @param  rNode
                The text node.
    @param  nPos
                The given position that should be checked.
    @param  rnStartPos
                Return parameter for the start position of the hidden range.
                STRING_LEN if nPos is not inside a hidden range.
    @param  rnEndPos
                Return parameter for the end position of the hidden range.
                0 if nPos is not inside a hidden range.
    @param  rnEndPos
                Return parameter that contains all the hidden text ranges. Optional.
    @return
            returns true if there are any hidden characters in this paragraph.

*/
    static bool GetBoundsOfHiddenRange( const SwTxtNode& rNode, xub_StrLen nPos,
                                        xub_StrLen& rnStartPos, xub_StrLen& rnEndPos,
                                        PositionList* pList = 0 );
    bool GetBoundsOfHiddenRange(  xub_StrLen nPos, xub_StrLen& rnStartPos,
                                  xub_StrLen& rnEndPos, PositionList* pList = 0 ) const;

    static bool IsInHiddenRange( const SwTxtNode& rNode, xub_StrLen nPos );

/** Hidden text attribute handling

    @descr  Takes a string and either deletes the hidden ranges or sets
            a given character in place of the hidden characters.

    @param  rNode
                The text node.
    @param  nPos
                The string to modify.
    @param  cChar
                The character that should replace the hidden characters.
    @param  bDel
                If set, the hidden ranges will be deleted from the text node.
 */
    static USHORT MaskHiddenRanges( const SwTxtNode& rNode, XubString& rText,
                                    const xub_StrLen nStt, const xub_StrLen nEnd,
                                    const xub_Unicode cChar );

/** Hidden text attribute handling

    @descr  Takes a SwTxtNode and deletes the hidden ranges from the node.

    @param  rNode
                The text node.
 */
    static void DeleteHiddenRanges( SwTxtNode& rNode );

    //
    // HIDDEN TEXT STUFF END
    //

    // examines the range [ nStart, nStart + nEnd ] if there are kanas
    // returns start index of kana entry in array, otherwise USHRT_MAX
    USHORT HasKana( xub_StrLen nStart, const xub_StrLen nEnd ) const;

    // modifies the kerning array according to a given compress value
    long Compress( sal_Int32* pKernArray, xub_StrLen nIdx, xub_StrLen nLen,
                   const USHORT nCompress, const USHORT nFontHeight,
                   Point* pPoint = NULL ) const;

/** Performes a kashida justification on the kerning array

    @descr  Add some extra space for kashida justification to the
            positions in the kerning array.
    @param  pKernArray
                The printers kerning array. Optional.
    @param  pScrArray
                The screen kerning array. Optional.
    @param  nIdx
                Start referring to the paragraph.
    @param  nLen
                The number of characters to be considered.
    @param  nSpaceAdd
                The value which has to be added to a kashida opportunity.
    @return The number of kashida opportunities in the given range
*/
    USHORT KashidaJustify( sal_Int32* pKernArray ,sal_Int32* pScrArray,
                           xub_StrLen nIdx, xub_StrLen nLen,
                           long nSpaceAdd = 0 ) const;

/** Checks if language is one of the 16 Arabic languages

    @descr  Checks if language is one of the 16 Arabic languages
    @param  aLang
                The language which has to be checked.
    @return Returns if the language is an Arabic language
*/
    static BOOL IsArabicLanguage( LanguageType aLang );

/** Performes a thai justification on the kerning array

    @descr  Add some extra space for thai justification to the
            positions in the kerning array.
    @param  rTxt
                The String
    @param  pKernArray
                The printers kerning array. Optional.
    @param  pScrArray
                The screen kerning array. Optional.
    @param  nIdx
                Start referring to the paragraph.
    @param  nLen
                The number of characters to be considered.
    @param  nSpaceAdd
                The value which has to be added to the cells.
    @return The number of extra spaces in the given range
*/
    static USHORT ThaiJustify( const XubString& rTxt, sal_Int32* pKernArray,
                               sal_Int32* pScrArray, xub_StrLen nIdx,
                               xub_StrLen nLen, xub_StrLen nNumberOfBlanks = 0,
                               long nSpaceAdd = 0 );

    static SwScriptInfo* GetScriptInfo( const SwTxtNode& rNode,
                                        sal_Bool bAllowInvalid = sal_False );

    static BYTE WhichFont( xub_StrLen nIdx, const String* pTxt, const SwScriptInfo* pSI );
};

inline void SwScriptInfo::SetInvalidity( const xub_StrLen nPos )
{
    if ( nPos < nInvalidityPos )
        nInvalidityPos = nPos;
};
inline USHORT SwScriptInfo::CountScriptChg() const { return aScriptChg.Count(); }
inline xub_StrLen SwScriptInfo::GetScriptChg( const USHORT nCnt ) const
{
    ASSERT( nCnt < aScriptChg.Count(),"No ScriptChange today!");
    return aScriptChg[ nCnt ];
}
inline BYTE SwScriptInfo::GetScriptType( const xub_StrLen nCnt ) const
{
    ASSERT( nCnt < aScriptChg.Count(),"No ScriptType today!");
    return aScriptType[ nCnt ];
}

inline USHORT SwScriptInfo::CountDirChg() const { return aDirChg.Count(); }
inline xub_StrLen SwScriptInfo::GetDirChg( const USHORT nCnt ) const
{
    ASSERT( nCnt < aDirChg.Count(),"No DirChange today!");
    return aDirChg[ nCnt ];
}
inline BYTE SwScriptInfo::GetDirType( const xub_StrLen nCnt ) const
{
    ASSERT( nCnt < aDirChg.Count(),"No DirType today!");
    return aDirType[ nCnt ];
}

inline USHORT SwScriptInfo::CountKashida() const { return aKashida.Count(); }
inline xub_StrLen SwScriptInfo::GetKashida( const USHORT nCnt ) const
{
    ASSERT( nCnt < aKashida.Count(),"No Kashidas today!");
    return aKashida[ nCnt ];
}

inline USHORT SwScriptInfo::CountCompChg() const { return aCompChg.Count(); };
inline xub_StrLen SwScriptInfo::GetCompStart( const USHORT nCnt ) const
{
    ASSERT( nCnt < aCompChg.Count(),"No CompressionStart today!");
    return aCompChg[ nCnt ];
}
inline xub_StrLen SwScriptInfo::GetCompLen( const USHORT nCnt ) const
{
    ASSERT( nCnt < aCompChg.Count(),"No CompressionLen today!");
    return aCompLen[ nCnt ];
}

inline BYTE SwScriptInfo::GetCompType( const USHORT nCnt ) const
{
    ASSERT( nCnt < aCompChg.Count(),"No CompressionType today!");
    return aCompType[ nCnt ];
}

inline USHORT SwScriptInfo::CountHiddenChg() const { return aHiddenChg.Count(); };
inline xub_StrLen SwScriptInfo::GetHiddenChg( const USHORT nCnt ) const
{
    ASSERT( nCnt < aHiddenChg.Count(),"No HiddenChg today!");
    return aHiddenChg[ nCnt ];
}

#endif
<|endoftext|>


<commit_before><commit_msg>sw: missing nullptr check<commit_after><|endoftext|>


<commit_before><commit_msg>translate some german<commit_after><|endoftext|>


<commit_before><commit_msg>tdf#89705 hyperlink clickable in writer (not in impress, yet)<commit_after><|endoftext|>


<commit_before>// REQUIRES: x86-registered-target
// RUN: c-index-test -write-pch %t_linux.ast -target i686-pc-linux-gnu %s
// RUN: c-index-test -test-print-mangle %t_linux.ast | FileCheck %s --check-prefix=ITANIUM

// RUN: c-index-test -write-pch %t_macho.ast -arch x86_64 -mmacosx-version-min=10.6 %s
// RUN: c-index-test -test-print-mangle %t_macho.ast | FileCheck %s --check-prefix=MACHO

// RUN: c-index-test -write-pch %t_msft.ast -target i686-pc-win32 %s
// RUN: c-index-test -test-print-mangle %t_msft.ast | FileCheck %s --check-prefix=MICROSOFT

int foo(int, int);
// ITANIUM: mangled=_Z3fooii
// MACHO: mangled=__Z3fooii
// MICROSOFT: mangled=?foo@@YAHHH

int foo(float, int);
// ITANIUM: mangled=_Z3foofi
// MACHO: mangled=__Z3foofi
// MICROSOFT: mangled=?foo@@YAHMH

struct S {
  int x, y;
};
// ITANIUM: StructDecl{{.*}}mangled=]
// MACHO: StructDecl{{.*}}mangled=]
// MICROSOFT: StructDecl{{.*}}mangled=]

int foo(S, S&);
// ITANIUM: mangled=_Z3foo1SRS_
// MACHO: mangled=__Z3foo1SRS_
// MICROSOFT: mangled=?foo@@YAHUS
<commit_msg>[test] Another attempt to fix the test.<commit_after>// REQUIRES: x86-registered-target
// RUN: c-index-test -write-pch %t_linux.ast -target i686-pc-linux-gnu %s
// RUN: c-index-test -test-print-mangle %t_linux.ast | FileCheck %s --check-prefix=ITANIUM

// RUN: c-index-test -write-pch %t_macho.ast -target x86_64-apple-darwin %s
// RUN: c-index-test -test-print-mangle %t_macho.ast | FileCheck %s --check-prefix=MACHO

// RUN: c-index-test -write-pch %t_msft.ast -target i686-pc-win32 %s
// RUN: c-index-test -test-print-mangle %t_msft.ast | FileCheck %s --check-prefix=MICROSOFT

int foo(int, int);
// ITANIUM: mangled=_Z3fooii
// MACHO: mangled=__Z3fooii
// MICROSOFT: mangled=?foo@@YAHHH

int foo(float, int);
// ITANIUM: mangled=_Z3foofi
// MACHO: mangled=__Z3foofi
// MICROSOFT: mangled=?foo@@YAHMH

struct S {
  int x, y;
};
// ITANIUM: StructDecl{{.*}}mangled=]
// MACHO: StructDecl{{.*}}mangled=]
// MICROSOFT: StructDecl{{.*}}mangled=]

int foo(S, S&);
// ITANIUM: mangled=_Z3foo1SRS_
// MACHO: mangled=__Z3foo1SRS_
// MICROSOFT: mangled=?foo@@YAHUS
<|endoftext|>


<commit_before>// This file is part of the dune-gdt project:
//   https://github.com/dune-community/dune-gdt
// Copyright 2010-2018 dune-gdt developers and contributors. All rights reserved.
// License: Dual licensed as BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)
//      or  GPL-2.0+ (http://opensource.org/licenses/gpl-license)
//          with "runtime exception" (http://www.dune-project.org/license.html)
// Authors:
//   Felix Schindler (2017 - 2018)
//   René Fritze     (2018)
//   Tobias Leibner  (2018)

#ifndef PYTHON_DUNE_GDT_DISCRETEFUNCTION_DEFAULT_BINDINGS_HH
#define PYTHON_DUNE_GDT_DISCRETEFUNCTION_DEFAULT_BINDINGS_HH

#include <dune/pybindxi/pybind11.h>

#include <dune/xt/common/python.hh>
#include <dune/xt/common/string.hh>
#include <dune/xt/functions/interfaces/grid-function.hh>
#include <dune/xt/grid/type_traits.hh>
#include <dune/xt/la/container.hh>
#include <python/dune/xt/common/exceptions.bindings.hh>
#include <python/dune/xt/functions/gridfunction-interface.hh>
#include <python/dune/xt/grid/grids.bindings.hh>
#include <python/dune/xt/grid/traits.hh>
#include <python/dune/xt/la/container.bindings.hh>

#include <dune/gdt/discretefunction/default.hh>

namespace Dune {
namespace GDT {
namespace bindings {

template <class V, class MatchingVectorTag, class GV, size_t r = 1, size_t rC = 1, class R = double>
class DiscreteFunction
{
  using type = GDT::DiscreteFunction<V, GV, r, rC, R>;
  using base_type = XT::Functions::GridFunctionInterface<XT::Grid::extract_entity_t<GV>, r, rC, R>;
  using G = typename GV::Grid;
  using S = typename type::SpaceType;

public:
  using bound_type = pybind11::class_<type, base_type>;

  static bound_type bind(pybind11::module& m,
                         const std::string& layer_id = "",
                         const std::string& grid_id = XT::Grid::bindings::grid_name<G>::value(),
                         const std::string& class_id = "discrete_function")
  {
    namespace py = pybind11;
    using namespace pybind11::literals;

    std::string class_name = class_id + "_" + grid_id;
    if (!layer_id.empty())
      class_name += "_" + layer_id;
    if (r > 1)
      class_name += "_to_" + XT::Common::to_string(r) + "d";
    if (rC > 1)
      class_name += "x" + XT::Common::to_string(rC) + "d";
    class_name += "_" + XT::LA::bindings::container_name<V>::value();
    const auto ClassName = XT::Common::to_camel_case(class_name);
    const std::string default_name = "dune.gdt.discretefunction";
    bound_type c(m, ClassName.c_str(), ClassName.c_str());

    c.def(py::init<const S&, V&, const std::string&>(),
          "space"_a,
          "vector"_a,
          "name"_a = default_name,
          py::keep_alive<1, 2>(),
          py::keep_alive<1, 3>());
    c.def(py::init<const S&, const std::string&>(), "space"_a, "name"_a = default_name, py::keep_alive<1, 2>());

    c.def_property_readonly("space", &type::space);
    c.def_property("dofs", // doing this so complicated to get an actual reference instead of a copy
                   (typename type::DofVectorType & (type::*)()) & type::dofs,
                   (typename type::DofVectorType & (type::*)()) & type::dofs);
    c.def_property_readonly("name", &type::name);

    c.def("visualize",
          [](type& self, const std::string& filename) { return self.visualize(filename, VTK::appendedraw); },
          "filename"_a);

    m.def(
        XT::Common::to_camel_case(class_id).c_str(),
        [](const S& space, V& vector, const std::string& name) { return make_discrete_function(space, vector, name); },
        "space"_a,
        "vector"_a,
        "name"_a = default_name,
        py::keep_alive<0, 1>(),
        py::keep_alive<0, 2>());
    m.def(XT::Common::to_camel_case(class_id).c_str(),
          [](const S& space, const MatchingVectorTag&, const std::string& name) {
            return make_discrete_function(space, name);
          },
          "space"_a,
          "vector_type"_a,
          "name"_a = default_name,
          py::keep_alive<0, 1>());
    if (std::is_same<MatchingVectorTag, XT::LA::bindings::Istl>::value)
      m.def(XT::Common::to_camel_case(class_id).c_str(),
            [](const S& space, const std::string& name, const MatchingVectorTag&) {
              return make_discrete_function(space, name);
            },
            "space"_a,
            "name"_a = default_name,
            "vector_type"_a = XT::LA::bindings::Istl(),
            py::keep_alive<0, 1>());
    return c;
  } // ... bind(...)
}; // class DiscreteFunction

} // namespace bindings
} // namespace GDT
} // namespace Dune

#endif // PYTHON_DUNE_GDT_DISCRETEFUNCTION_DEFAULT_BINDINGS_HH
<commit_msg>[P|discretefunction] export dims as function and gridfunction<commit_after>// This file is part of the dune-gdt project:
//   https://github.com/dune-community/dune-gdt
// Copyright 2010-2018 dune-gdt developers and contributors. All rights reserved.
// License: Dual licensed as BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)
//      or  GPL-2.0+ (http://opensource.org/licenses/gpl-license)
//          with "runtime exception" (http://www.dune-project.org/license.html)
// Authors:
//   Felix Schindler (2017 - 2018)
//   René Fritze     (2018)
//   Tobias Leibner  (2018)

#ifndef PYTHON_DUNE_GDT_DISCRETEFUNCTION_DEFAULT_BINDINGS_HH
#define PYTHON_DUNE_GDT_DISCRETEFUNCTION_DEFAULT_BINDINGS_HH

#include <dune/pybindxi/pybind11.h>

#include <dune/xt/common/python.hh>
#include <dune/xt/common/string.hh>
#include <dune/xt/functions/interfaces/grid-function.hh>
#include <dune/xt/grid/type_traits.hh>
#include <dune/xt/la/container.hh>
#include <python/dune/xt/common/exceptions.bindings.hh>
#include <python/dune/xt/functions/gridfunction-interface.hh>
#include <python/dune/xt/grid/grids.bindings.hh>
#include <python/dune/xt/grid/traits.hh>
#include <python/dune/xt/la/container.bindings.hh>

#include <dune/gdt/discretefunction/default.hh>

namespace Dune {
namespace GDT {
namespace bindings {

template <class V, class MatchingVectorTag, class GV, size_t r = 1, size_t rC = 1, class R = double>
class DiscreteFunction
{
  using type = GDT::DiscreteFunction<V, GV, r, rC, R>;
  using base_type = XT::Functions::GridFunctionInterface<XT::Grid::extract_entity_t<GV>, r, rC, R>;
  using G = typename GV::Grid;
  using S = typename type::SpaceType;

public:
  using bound_type = pybind11::class_<type, base_type>;

  static bound_type bind(pybind11::module& m,
                         const std::string& layer_id = "",
                         const std::string& grid_id = XT::Grid::bindings::grid_name<G>::value(),
                         const std::string& class_id = "discrete_function")
  {
    namespace py = pybind11;
    using namespace pybind11::literals;

    std::string class_name = class_id + "_" + grid_id;
    if (!layer_id.empty())
      class_name += "_" + layer_id;
    if (r > 1)
      class_name += "_to_" + XT::Common::to_string(r) + "d";
    if (rC > 1)
      class_name += "x" + XT::Common::to_string(rC) + "d";
    class_name += "_" + XT::LA::bindings::container_name<V>::value();
    const auto ClassName = XT::Common::to_camel_case(class_name);
    const std::string default_name = "dune.gdt.discretefunction";
    bound_type c(m, ClassName.c_str(), ClassName.c_str());

    c.def(py::init<const S&, V&, const std::string&>(),
          "space"_a,
          "vector"_a,
          "name"_a = default_name,
          py::keep_alive<1, 2>(),
          py::keep_alive<1, 3>());
    c.def(py::init<const S&, const std::string&>(), "space"_a, "name"_a = default_name, py::keep_alive<1, 2>());

    c.def_property_readonly("dim_domain", [](const type&) { return size_t(base_type::d); });
    if (rC == 1)
      c.def_property_readonly("dim_range", [](const type&) { return size_t(r); });
    else
      c.def_property_readonly("dim_range", [](const type&) { return std::make_pair(size_t(r), size_t(rC)); });
    c.def_property_readonly("space", &type::space);
    c.def_property("dofs", // doing this so complicated to get an actual reference instead of a copy
                   (typename type::DofVectorType & (type::*)()) & type::dofs,
                   (typename type::DofVectorType & (type::*)()) & type::dofs);
    c.def_property_readonly("name", &type::name);

    c.def(
        "visualize",
        [](type& self, const std::string& filename) { return self.visualize(filename, VTK::appendedraw); },
        "filename"_a);

    m.def(
        XT::Common::to_camel_case(class_id).c_str(),
        [](const S& space, V& vector, const std::string& name) { return make_discrete_function(space, vector, name); },
        "space"_a,
        "vector"_a,
        "name"_a = default_name,
        py::keep_alive<0, 1>(),
        py::keep_alive<0, 2>());
    m.def(
        XT::Common::to_camel_case(class_id).c_str(),
        [](const S& space, const MatchingVectorTag&, const std::string& name) {
          return make_discrete_function(space, name);
        },
        "space"_a,
        "vector_type"_a,
        "name"_a = default_name,
        py::keep_alive<0, 1>());
    if (std::is_same<MatchingVectorTag, XT::LA::bindings::Istl>::value)
      m.def(
          XT::Common::to_camel_case(class_id).c_str(),
          [](const S& space, const std::string& name, const MatchingVectorTag&) {
            return make_discrete_function(space, name);
          },
          "space"_a,
          "name"_a = default_name,
          "vector_type"_a = XT::LA::bindings::Istl(),
          py::keep_alive<0, 1>());
    return c;
  } // ... bind(...)
}; // class DiscreteFunction

} // namespace bindings
} // namespace GDT
} // namespace Dune

#endif // PYTHON_DUNE_GDT_DISCRETEFUNCTION_DEFAULT_BINDINGS_HH
<|endoftext|>


<commit_before>/**
 * This file is part of the CernVM File System.
 */
#include "garbage_collector.h"

#include <dirent.h>
#include <errno.h>
#include <stdio.h>

#include <map>
#include <string>

#include "helpers.h"
#include "logging.h"
#include "shrinkwrap/fs_traversal.h"
#include "smalloc.h"
#include "util/posix.h"

/**
 * Initializes garbage collection by setting up the corresponding hash map
 * in the fs_traversal_posix_context
 * The initialization uses the data stored in the file at
 * [data directory] + POSIX_GARBAGE_DIR + POSIX_GARBAGE_FLAGGED_FILE
 *
 * This file contains a fixed length concatenation of
 * inodes (type ino_t) which should be checked
 * and deleted upon garbage collection
 */
void InitializeGarbageCollection(struct fs_traversal_context *ctx) {
  struct fs_traversal_posix_context *posix_ctx
    = reinterpret_cast<struct fs_traversal_posix_context *>(ctx->ctx);
  int res2 = mkdir((std::string(ctx->data)+POSIX_GARBAGE_DIR).c_str(), 0700);
    assert(res2 == 0 || errno == EEXIST);
  std::string gc_path = std::string(ctx->data)
      + POSIX_GARBAGE_DIR + POSIX_GARBAGE_FLAGGED_FILE;
  if (FileExists(gc_path)) {
    FILE *gc_flagged_file = fopen(gc_path.c_str(), "r");
    assert(gc_flagged_file != NULL);
    while (true) {
      ino_t cur_ino;
      size_t read = fread(&cur_ino, sizeof(ino_t), 1, gc_flagged_file);
      if (read == 1) {
        posix_ctx->gc_flagged[cur_ino] = true;
      } else {
        assert(feof(gc_flagged_file) != 0);
        break;
      }
    }
    int res = fclose(gc_flagged_file);
    assert(res == 0);
  }
}

/**
 * Finalizes the garbage collection
 * Stores the content of the garbage collection hash map in the file at
 * [data directory] + POSIX_GARBAGE_DIR + POSIX_GARBAGE_FLAGGED_FILE
 *
 */
void FinalizeGarbageCollection(struct fs_traversal_context *ctx) {
  struct fs_traversal_posix_context *posix_ctx
    =  reinterpret_cast<struct fs_traversal_posix_context*>(ctx->ctx);
  std::string gc_path = std::string(ctx->data)
      + POSIX_GARBAGE_DIR + POSIX_GARBAGE_FLAGGED_FILE;
  FILE *gc_flagged_file = fopen(gc_path.c_str(), "w");
  for (
    std::map<ino_t, bool>::const_iterator it = posix_ctx->gc_flagged.begin();
    it != posix_ctx->gc_flagged.end();
    it++) {
    if (it->second) {
      fwrite(&(it->first), sizeof(ino_t), 1, gc_flagged_file);
    }
  }
  fclose(gc_flagged_file);
}

/**
 * Main Worker of the Posix Garbage Collector
 * Iterates over a calculated set of directories and check for inodes that can
 * be deleted.
 * For the thread with thread number j the thread starts with the top level data
 * directory /j/ and iterates over the contained files. Afterwards it continues
 * with /j+i*n/ where n is the number of total threads and i is an arbitrary
 * integer.
 */
void *PosixGcMainWorker(void *data) {
  struct posix_gc_thread *thread_context
    = reinterpret_cast<struct posix_gc_thread *>(data);
  struct fs_traversal_posix_context *posix_ctx
    = reinterpret_cast<struct fs_traversal_posix_context *>(
      thread_context->ctx->ctx);
  int64_t files_removed = 0;
  int64_t bytes_removed = 0;
  // Build path array
  int offset = strlen(thread_context->ctx->data)+1;
  // used for both path building and stat calls (therefore +257)
  char dir_path[offset+kDigitsPerDirLevel*kDirLevels+kDirLevels+257];
  snprintf(dir_path, offset, thread_context->ctx->data);
  dir_path[offset-1]='/';
  dir_path[offset+kDigitsPerDirLevel*kDirLevels+kDirLevels+257] = '\0';
  char dir_name_template[6];
  snprintf(dir_name_template,
    sizeof(dir_name_template),
    "%%%02ux/",
    kDigitsPerDirLevel);
  const unsigned directory_mask = (1 << (kDigitsPerDirLevel*4)) -1;
  const unsigned max_dir_name = (1 << kDigitsPerDirLevel*4);
  const unsigned max_val = (1 << (kDirLevels*kDigitsPerDirLevel*4));
  for (unsigned i = thread_context->thread_num*max_dir_name*(kDirLevels-1);
    i < max_val;
    i+=thread_context->thread_total*+(max_val/max_dir_name)) {
    // Iterate over paths of current subdirectory...
    for (unsigned j = i; j < i+(max_val/max_dir_name); j++) {
      // For every subdirectory chain (described by j)
      unsigned path_pos = offset;
      for (int level = kDirLevels-1;
        level >= 0;
        level--) {
        const unsigned cur_dir
          = (j >> (level*kDigitsPerDirLevel*4)) & directory_mask;
        snprintf(dir_path+path_pos,
          kDigitsPerDirLevel+2, dir_name_template, cur_dir);
        path_pos+=kDigitsPerDirLevel+1;
      }
      dir_path[path_pos]='\0';
      // Calculated path - now garbage collection...
      DIR *cur_dir_ent = opendir(dir_path);
      assert(cur_dir_ent != NULL);
      struct stat stat_buf;
      struct dirent *de;
      while ((de = readdir(cur_dir_ent)) != NULL) {
        if (posix_ctx->gc_flagged.count(de->d_ino) > 0
          && posix_ctx->gc_flagged[de->d_ino]) {
          snprintf(dir_path+path_pos, sizeof(dir_path)-path_pos, de->d_name);
          stat(dir_path, &stat_buf);
          if (stat_buf.st_nlink == 1) {
            files_removed++;
            bytes_removed+=stat_buf.st_size;
            int res = unlink(dir_path);
            assert(res == 0);
            posix_ctx->gc_flagged.erase(de->d_ino);
          }
        }
      }
      closedir(cur_dir_ent);
    }
  }
  thread_context->stat
    ->Lookup(POSIX_GC_STAT_FILES_REMOVED)->Xadd(files_removed);
  thread_context->stat
    ->Lookup(POSIX_GC_STAT_BYTES_REMOVED)->Xadd(bytes_removed);
  return NULL;
}

/**
 * Method which runs the garbage collection.
 * Will start posix_ctx->num_threads in parallel for the task.
 * For posix_ctx->num_threads <= 1 there is a fallback to a sequential version.
 */
int RunGarbageCollection(struct fs_traversal_context *ctx) {
  struct fs_traversal_posix_context *posix_ctx
    = reinterpret_cast<struct fs_traversal_posix_context *>(ctx->ctx);

  int thread_total = posix_ctx->num_threads;
  struct posix_gc_thread *thread_contexts
      = reinterpret_cast<struct posix_gc_thread *>(
        smalloc(sizeof(struct posix_gc_thread) * thread_total));

  perf::Statistics *gc_statistics = new perf::Statistics();
  gc_statistics->Register(POSIX_GC_STAT_FILES_REMOVED,
    "Number of deduplicated files removed by Garbage Collector");
  gc_statistics->Register(POSIX_GC_STAT_BYTES_REMOVED,
    "Sum of sizes of removed files");

  if (thread_total > 1) {
    pthread_t *workers
    = reinterpret_cast<pthread_t *>(smalloc(sizeof(pthread_t) * thread_total));
    for (int i = 0; i < thread_total; i++) {
      thread_contexts[i].thread_total = thread_total;
      thread_contexts[i].thread_num = i;
      thread_contexts[i].ctx = ctx;
      thread_contexts[i].stat = gc_statistics;
      int retval = pthread_create(&workers[i], NULL,
        PosixGcMainWorker, &thread_contexts[i]);
      assert(retval == 0);
    }

    for (int i = 0; i < thread_total; i++) {
      pthread_join(workers[i], NULL);
    }
    free(workers);
  } else {
    thread_contexts[0].thread_total = thread_total;
    thread_contexts[0].thread_num = 0;
    thread_contexts[0].ctx = ctx;
    thread_contexts[0].stat = gc_statistics;
    PosixGcMainWorker(thread_contexts);
  }
  LogCvmfs(kLogCvmfs, kLogStdout,
      "%s", gc_statistics->PrintList(perf::Statistics::kPrintHeader).c_str());
  free(thread_contexts);
  delete gc_statistics;
  return 0;
}
<commit_msg>fix use of snprintf<commit_after>/**
 * This file is part of the CernVM File System.
 */
#include "garbage_collector.h"

#include <dirent.h>
#include <errno.h>
#include <stdio.h>

#include <map>
#include <string>

#include "helpers.h"
#include "logging.h"
#include "shrinkwrap/fs_traversal.h"
#include "smalloc.h"
#include "util/posix.h"

/**
 * Initializes garbage collection by setting up the corresponding hash map
 * in the fs_traversal_posix_context
 * The initialization uses the data stored in the file at
 * [data directory] + POSIX_GARBAGE_DIR + POSIX_GARBAGE_FLAGGED_FILE
 *
 * This file contains a fixed length concatenation of
 * inodes (type ino_t) which should be checked
 * and deleted upon garbage collection
 */
void InitializeGarbageCollection(struct fs_traversal_context *ctx) {
  struct fs_traversal_posix_context *posix_ctx
    = reinterpret_cast<struct fs_traversal_posix_context *>(ctx->ctx);
  int res2 = mkdir((std::string(ctx->data)+POSIX_GARBAGE_DIR).c_str(), 0700);
    assert(res2 == 0 || errno == EEXIST);
  std::string gc_path = std::string(ctx->data)
      + POSIX_GARBAGE_DIR + POSIX_GARBAGE_FLAGGED_FILE;
  if (FileExists(gc_path)) {
    FILE *gc_flagged_file = fopen(gc_path.c_str(), "r");
    assert(gc_flagged_file != NULL);
    while (true) {
      ino_t cur_ino;
      size_t read = fread(&cur_ino, sizeof(ino_t), 1, gc_flagged_file);
      if (read == 1) {
        posix_ctx->gc_flagged[cur_ino] = true;
      } else {
        assert(feof(gc_flagged_file) != 0);
        break;
      }
    }
    int res = fclose(gc_flagged_file);
    assert(res == 0);
  }
}

/**
 * Finalizes the garbage collection
 * Stores the content of the garbage collection hash map in the file at
 * [data directory] + POSIX_GARBAGE_DIR + POSIX_GARBAGE_FLAGGED_FILE
 *
 */
void FinalizeGarbageCollection(struct fs_traversal_context *ctx) {
  struct fs_traversal_posix_context *posix_ctx
    =  reinterpret_cast<struct fs_traversal_posix_context*>(ctx->ctx);
  std::string gc_path = std::string(ctx->data)
      + POSIX_GARBAGE_DIR + POSIX_GARBAGE_FLAGGED_FILE;
  FILE *gc_flagged_file = fopen(gc_path.c_str(), "w");
  for (
    std::map<ino_t, bool>::const_iterator it = posix_ctx->gc_flagged.begin();
    it != posix_ctx->gc_flagged.end();
    it++) {
    if (it->second) {
      fwrite(&(it->first), sizeof(ino_t), 1, gc_flagged_file);
    }
  }
  fclose(gc_flagged_file);
}

/**
 * Main Worker of the Posix Garbage Collector
 * Iterates over a calculated set of directories and check for inodes that can
 * be deleted.
 * For the thread with thread number j the thread starts with the top level data
 * directory /j/ and iterates over the contained files. Afterwards it continues
 * with /j+i*n/ where n is the number of total threads and i is an arbitrary
 * integer.
 */
void *PosixGcMainWorker(void *data) {
  struct posix_gc_thread *thread_context
    = reinterpret_cast<struct posix_gc_thread *>(data);
  struct fs_traversal_posix_context *posix_ctx
    = reinterpret_cast<struct fs_traversal_posix_context *>(
      thread_context->ctx->ctx);
  int64_t files_removed = 0;
  int64_t bytes_removed = 0;
  // Build path array
  int offset = strlen(thread_context->ctx->data)+1;
  // used for both path building and stat calls (therefore +257)
  char dir_path[offset+kDigitsPerDirLevel*kDirLevels+kDirLevels+257];
  snprintf(dir_path, offset, "%s", thread_context->ctx->data);
  dir_path[offset-1]='/';
  dir_path[offset+kDigitsPerDirLevel*kDirLevels+kDirLevels+257] = '\0';
  char dir_name_template[6];
  snprintf(dir_name_template,
    sizeof(dir_name_template),
    "%%%02ux/",
    kDigitsPerDirLevel);
  const unsigned directory_mask = (1 << (kDigitsPerDirLevel*4)) -1;
  const unsigned max_dir_name = (1 << kDigitsPerDirLevel*4);
  const unsigned max_val = (1 << (kDirLevels*kDigitsPerDirLevel*4));
  for (unsigned i = thread_context->thread_num*max_dir_name*(kDirLevels-1);
    i < max_val;
    i+=thread_context->thread_total*+(max_val/max_dir_name)) {
    // Iterate over paths of current subdirectory...
    for (unsigned j = i; j < i+(max_val/max_dir_name); j++) {
      // For every subdirectory chain (described by j)
      unsigned path_pos = offset;
      for (int level = kDirLevels-1;
        level >= 0;
        level--) {
        const unsigned cur_dir
          = (j >> (level*kDigitsPerDirLevel*4)) & directory_mask;
        snprintf(dir_path+path_pos,
          kDigitsPerDirLevel+2, dir_name_template, cur_dir);
        path_pos+=kDigitsPerDirLevel+1;
      }
      dir_path[path_pos]='\0';
      // Calculated path - now garbage collection...
      DIR *cur_dir_ent = opendir(dir_path);
      assert(cur_dir_ent != NULL);
      struct stat stat_buf;
      struct dirent *de;
      while ((de = readdir(cur_dir_ent)) != NULL) {
        if (posix_ctx->gc_flagged.count(de->d_ino) > 0
          && posix_ctx->gc_flagged[de->d_ino]) {
          snprintf(dir_path+path_pos, sizeof(dir_path)-path_pos, "%s",
                   de->d_name);
          stat(dir_path, &stat_buf);
          if (stat_buf.st_nlink == 1) {
            files_removed++;
            bytes_removed+=stat_buf.st_size;
            int res = unlink(dir_path);
            assert(res == 0);
            posix_ctx->gc_flagged.erase(de->d_ino);
          }
        }
      }
      closedir(cur_dir_ent);
    }
  }
  thread_context->stat
    ->Lookup(POSIX_GC_STAT_FILES_REMOVED)->Xadd(files_removed);
  thread_context->stat
    ->Lookup(POSIX_GC_STAT_BYTES_REMOVED)->Xadd(bytes_removed);
  return NULL;
}

/**
 * Method which runs the garbage collection.
 * Will start posix_ctx->num_threads in parallel for the task.
 * For posix_ctx->num_threads <= 1 there is a fallback to a sequential version.
 */
int RunGarbageCollection(struct fs_traversal_context *ctx) {
  struct fs_traversal_posix_context *posix_ctx
    = reinterpret_cast<struct fs_traversal_posix_context *>(ctx->ctx);

  int thread_total = posix_ctx->num_threads;
  struct posix_gc_thread *thread_contexts
      = reinterpret_cast<struct posix_gc_thread *>(
        smalloc(sizeof(struct posix_gc_thread) * thread_total));

  perf::Statistics *gc_statistics = new perf::Statistics();
  gc_statistics->Register(POSIX_GC_STAT_FILES_REMOVED,
    "Number of deduplicated files removed by Garbage Collector");
  gc_statistics->Register(POSIX_GC_STAT_BYTES_REMOVED,
    "Sum of sizes of removed files");

  if (thread_total > 1) {
    pthread_t *workers
    = reinterpret_cast<pthread_t *>(smalloc(sizeof(pthread_t) * thread_total));
    for (int i = 0; i < thread_total; i++) {
      thread_contexts[i].thread_total = thread_total;
      thread_contexts[i].thread_num = i;
      thread_contexts[i].ctx = ctx;
      thread_contexts[i].stat = gc_statistics;
      int retval = pthread_create(&workers[i], NULL,
        PosixGcMainWorker, &thread_contexts[i]);
      assert(retval == 0);
    }

    for (int i = 0; i < thread_total; i++) {
      pthread_join(workers[i], NULL);
    }
    free(workers);
  } else {
    thread_contexts[0].thread_total = thread_total;
    thread_contexts[0].thread_num = 0;
    thread_contexts[0].ctx = ctx;
    thread_contexts[0].stat = gc_statistics;
    PosixGcMainWorker(thread_contexts);
  }
  LogCvmfs(kLogCvmfs, kLogStdout,
      "%s", gc_statistics->PrintList(perf::Statistics::kPrintHeader).c_str());
  free(thread_contexts);
  delete gc_statistics;
  return 0;
}
<|endoftext|>


<commit_before>// Copyright (c) 2014, Sailing Lab
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// 3. Neither the name of the <ORGANIZATION> nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
// Author: Dai Wei (wdai@cs.cmu.edu)
// Date: 2014.03.25

#include "lda_engine.hpp"
#include "context.hpp"
#include <petuum_ps_common/include/petuum_ps.hpp>
#include <gflags/gflags.h>
#include <glog/logging.h>
#include <thread>
#include <vector>

// Petuum Parameters
//DEFINE_string(hostfile, "", "Path to file containing server ip:port.");
//DEFINE_int32(num_clients, 1, "Total number of clients");
DEFINE_int32(num_worker_threads, 1, "Number of app threads in this client");
//DEFINE_int32(client_id, 0, "Client ID");
DEFINE_int32(word_topic_table_process_cache_capacity, -1,
    "Word topic table process cache capacity. -1 uses FLAGS_num_vocabs.");
//DEFINE_int32(ps_row_in_memory_limit, 50000, "Single-machine version only: "
//"max # rows word-topic table that can be held in memory");

// LDA Parameters
DEFINE_string(doc_file, "",
    "File containing document in LibSVM format. Each document is a line.");
DEFINE_double(alpha, 1, "Dirichlet prior on document-topic vectors.");
DEFINE_double(beta, 0.1, "Dirichlet prior on vocab-topic vectors.");
DEFINE_int32(num_topics, 100, "Number of topics.");
DEFINE_int32(num_work_units, 1, "Number of work units. A work unit can be less "
    "or more than one epoch (sweep over dataset), determined by "
    "FLAGS_num_iters_per_work_unit");
DEFINE_int32(compute_ll_interval, 1,
    "Copmute log likelihood over local dataset on every compute_ll_interval "
    "work units");

// Misc
DEFINE_int32(word_topic_table_staleness, 0, "staleness for word-topic table.");
DEFINE_int32(summary_table_staleness, 0,
    "staleness for table containing summary row.");
DEFINE_string(output_file_prefix, "", "LDA results.");
DEFINE_bool(disk_stream, false,
    "Turn it on when memory isn't enough for the dataset.");
DEFINE_int32(disk_stream_batch_size, 1000,
    "Each worker thread gets disk_stream_batch_size docs at a time.");
DEFINE_bool(output_topic_word, false, "Output phi to output_file_prefix.phi. "
    "Each row is a topic.");
DEFINE_bool(output_doc_topic, false, "Output theta to "
    "output_file_prefix.theta.X, X is the client ID");

// No need to change the following.
DEFINE_int32(word_topic_table_id, 1, "ID within Petuum-PS");
DEFINE_int32(summary_table_id, 2, "ID within Petuum-PS");
DEFINE_int32(llh_table_id, 3, "ID within Petuum-PS");
DEFINE_bool(aggressive_cpu, false, "Aggressive usage of CPU");
DEFINE_int32(num_vocabs, -1, "Number of vocabs. This is read from meta-data file.");
DEFINE_int32(max_vocab_id, -1, "Maximum word index, which could be different "
    "from num_vocabs if there are unused vocab indices. "
    "This is read from meta-data file.");

//DEFINE_string(stats_path, "", "Statistics output file");

//DEFINE_string(consistency_model, "SSPPush", "SSP or SSPPush or ...");

//DEFINE_int32(num_bg_threads, 1, "number of background threads");
DEFINE_int32(num_server_threads, 1, "number of server threads");

DEFINE_int32(num_iters_per_work_unit, 1, "number of iterations per work unit");
DEFINE_int32(num_clocks_per_work_unit, 1, "number of clocks per work unit");

int main(int argc, char *argv[]) {
  google::ParseCommandLineFlags(&argc, &argv, true);
  google::InitGoogleLogging(argv[0]);

  lda::LDAEngine ldaengine;
  ldaengine.Run(FLAGS_num_worker_threads);
  return 0;
}
<commit_msg>fix lda bug<commit_after>// Copyright (c) 2014, Sailing Lab
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// 3. Neither the name of the <ORGANIZATION> nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
// Author: Dai Wei (wdai@cs.cmu.edu)
// Date: 2014.03.25

#include "lda_engine.hpp"
#include "context.hpp"
#include <petuum_ps_common/include/petuum_ps.hpp>
#include <gflags/gflags.h>
#include <glog/logging.h>
#include <thread>
#include <vector>

// Petuum Parameters
//DEFINE_string(hostfile, "", "Path to file containing server ip:port.");
//DEFINE_int32(num_clients, 1, "Total number of clients");
DEFINE_int32(num_worker_threads, 1, "Number of app threads in this client");
//DEFINE_int32(client_id, 0, "Client ID");
DEFINE_int32(word_topic_table_process_cache_capacity, -1,
    "Word topic table process cache capacity. -1 uses FLAGS_num_vocabs.");
DEFINE_int32(ps_row_in_memory_limit, 50000, "Single-machine version only: "
    "max # rows word-topic table that can be held in memory");

// LDA Parameters
DEFINE_string(doc_file, "",
    "File containing document in LibSVM format. Each document is a line.");
DEFINE_double(alpha, 1, "Dirichlet prior on document-topic vectors.");
DEFINE_double(beta, 0.1, "Dirichlet prior on vocab-topic vectors.");
DEFINE_int32(num_topics, 100, "Number of topics.");
DEFINE_int32(num_work_units, 1, "Number of work units. A work unit can be less "
    "or more than one epoch (sweep over dataset), determined by "
    "FLAGS_num_iters_per_work_unit");
DEFINE_int32(compute_ll_interval, 1,
    "Copmute log likelihood over local dataset on every compute_ll_interval "
    "work units");

// Misc
DEFINE_int32(word_topic_table_staleness, 0, "staleness for word-topic table.");
DEFINE_int32(summary_table_staleness, 0,
    "staleness for table containing summary row.");
DEFINE_string(output_file_prefix, "", "LDA results.");
DEFINE_bool(disk_stream, false,
    "Turn it on when memory isn't enough for the dataset.");
DEFINE_int32(disk_stream_batch_size, 1000,
    "Each worker thread gets disk_stream_batch_size docs at a time.");
DEFINE_bool(output_topic_word, false, "Output phi to output_file_prefix.phi. "
    "Each row is a topic.");
DEFINE_bool(output_doc_topic, false, "Output theta to "
    "output_file_prefix.theta.X, X is the client ID");

// No need to change the following.
DEFINE_int32(word_topic_table_id, 1, "ID within Petuum-PS");
DEFINE_int32(summary_table_id, 2, "ID within Petuum-PS");
DEFINE_int32(llh_table_id, 3, "ID within Petuum-PS");
DEFINE_bool(aggressive_cpu, false, "Aggressive usage of CPU");
DEFINE_int32(num_vocabs, -1, "Number of vocabs. This is read from meta-data file.");
DEFINE_int32(max_vocab_id, -1, "Maximum word index, which could be different "
    "from num_vocabs if there are unused vocab indices. "
    "This is read from meta-data file.");

//DEFINE_string(stats_path, "", "Statistics output file");

//DEFINE_string(consistency_model, "SSPPush", "SSP or SSPPush or ...");

//DEFINE_int32(num_bg_threads, 1, "number of background threads");
DEFINE_int32(num_server_threads, 1, "number of server threads");

DEFINE_int32(num_iters_per_work_unit, 1, "number of iterations per work unit");
DEFINE_int32(num_clocks_per_work_unit, 1, "number of clocks per work unit");

int main(int argc, char *argv[]) {
  google::ParseCommandLineFlags(&argc, &argv, true);
  google::InitGoogleLogging(argv[0]);

  lda::LDAEngine ldaengine;
  ldaengine.Run(FLAGS_num_worker_threads);
  return 0;
}
<|endoftext|>


<commit_before>#include <mcl/bn256.hpp>

using namespace mcl::bn256;

const char *aa = "12723517038133731887338407189719511622662176727675373276651903807414909099441";
const char *ab = "4168783608814932154536427934509895782246573715297911553964171371032945126671";
const char *ba = "13891744915211034074451795021214165905772212241412891944830863846330766296736";
const char *bb = "7937318970632701341203597196594272556916396164729705624521405069090520231616";

void minimum_sample(const G1& P, const G2& Q)
{
	const mpz_class a = 123;
	const mpz_class b = 456;
	Fp12 e1, e2;
	BN::pairing(e1, P, Q);
	G2 aQ;
	G1 bP;
	G2::mul(aQ, Q, a);
	G1::mul(bP, P, b);
	BN::pairing(e2, bP, aQ);
	Fp12::pow(e1, e1, a * b);
	printf("%s\n", e1 == e2 ? "ok" : "ng");
}

void miller_and_finel_exp(const G1& P, const G2& Q)
{
	Fp12 e1, e2;
	BN::pairing(e1, P, Q);

	BN::millerLoop(e2, P, Q);
	BN::finalExp(e2, e2);
	printf("%s\n", e1 == e2 ? "ok" : "ng");
}

void precomputed(const G1& P, const G2& Q)
{
	Fp12 e1, e2;
	BN::pairing(e1, P, Q);
	std::vector<Fp6> Qcoeff;
	BN::precomputeG2(Qcoeff, Q);
	BN::precomputedMillerLoop(e2, P, Qcoeff);
	BN::finalExp(e2, e2);
	printf("%s\n", e1 == e2 ? "ok" : "ng");
}

int main()
{
	bn256init();
	G2 Q(Fp2(aa, ab), Fp2(ba, bb));
	G1 P(-1, 1);

	minimum_sample(P, Q);
	miller_and_finel_exp(P, Q);
	precomputed(P, Q);
}

<commit_msg>remove warning of vc15<commit_after>#include <mcl/bn256.hpp>

using namespace mcl::bn256;

void minimum_sample(const G1& P, const G2& Q)
{
	const mpz_class a = 123;
	const mpz_class b = 456;
	Fp12 e1, e2;
	BN::pairing(e1, P, Q);
	G2 aQ;
	G1 bP;
	G2::mul(aQ, Q, a);
	G1::mul(bP, P, b);
	BN::pairing(e2, bP, aQ);
	Fp12::pow(e1, e1, a * b);
	printf("%s\n", e1 == e2 ? "ok" : "ng");
}

void miller_and_finel_exp(const G1& P, const G2& Q)
{
	Fp12 e1, e2;
	BN::pairing(e1, P, Q);

	BN::millerLoop(e2, P, Q);
	BN::finalExp(e2, e2);
	printf("%s\n", e1 == e2 ? "ok" : "ng");
}

void precomputed(const G1& P, const G2& Q)
{
	Fp12 e1, e2;
	BN::pairing(e1, P, Q);
	std::vector<Fp6> Qcoeff;
	BN::precomputeG2(Qcoeff, Q);
	BN::precomputedMillerLoop(e2, P, Qcoeff);
	BN::finalExp(e2, e2);
	printf("%s\n", e1 == e2 ? "ok" : "ng");
}

int main()
{
	const char *aa = "12723517038133731887338407189719511622662176727675373276651903807414909099441";
	const char *ab = "4168783608814932154536427934509895782246573715297911553964171371032945126671";
	const char *ba = "13891744915211034074451795021214165905772212241412891944830863846330766296736";
	const char *bb = "7937318970632701341203597196594272556916396164729705624521405069090520231616";

	bn256init();
	G2 Q(Fp2(aa, ab), Fp2(ba, bb));
	G1 P(-1, 1);

	minimum_sample(P, Q);
	miller_and_finel_exp(P, Q);
	precomputed(P, Q);
}

<|endoftext|>


<commit_before><commit_msg>Changed ColourTo to assert if asked to style backwards. In release builds this is ignored instead.<commit_after><|endoftext|>


<commit_before>#include "shaderrenderwidget.h"

#include <QDebug>
#include <QMatrix4x4>
#include <QMouseEvent>

#define LogGlError \
{\
	const auto err = glGetError();	\
	if (err != GL_NO_ERROR)	\
		qDebug() << "GL error" << err << "at" << __FUNCTION__ << __LINE__;	\
}

ShaderRenderWidget::ShaderRenderWidget(QWidget *parent) : QOpenGLWidget(parent)
{
}

ShaderRenderWidget::~ShaderRenderWidget()
{
}

QString ShaderRenderWidget::setFragmentShader(const QString& shaderSource)
{
	QMutexLocker locker(&_shaderProgramMutex);

	if (_program)
	{
		_program->release();
		_program->removeAllShaders();
	}

	_program = std::make_unique<QOpenGLShaderProgram>();
	_fragmentShader = std::make_unique<QOpenGLShader>(QOpenGLShader::Fragment);

	if (!_fragmentShader->compileSourceCode(shaderSource))
		return _fragmentShader->log();

	if (!_program->addShader(_fragmentShader.get()))
		qDebug() << "Failed to add fragment shader:\n" << _program->log();

	// Compile vertex shader
	if (!_program->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/resources/default_vertex_shader.vsh"))
		qDebug() << "Failed to add vertex shader:\n" << _program->log();

	if (!_program->link())
		qDebug() << "Failed to link the program\n:" << _program->log();

	if (!_program->bind())
		qDebug() << "Failed to bind the program\n:" << _program->log();

	return _program->log();
}

void ShaderRenderWidget::showEvent(QShowEvent *event)
{
	QOpenGLWidget::showEvent(event);
	_totalRunTime.start();
	_timeSinceLastFrame.start();
}

void ShaderRenderWidget::initializeGL()
{
	initializeOpenGLFunctions();

	glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
	LogGlError;

	connect(&timer, &QTimer::timeout, this, [this](){update();});
	timer.start(10);
}

void ShaderRenderWidget::resizeGL(int w, int h)
{
	// TODO: manually calling glViewport() has no effect in QOpenGLWidget?
//	const auto scale = devicePixelRatio();
//	glViewport(0, 0, scale * w, scale * h);
}

void ShaderRenderWidget::paintGL()
{
	QMutexLocker locker(&_shaderProgramMutex);

	if (!_program || !_program->isLinked())
		return;

	glClear(GL_COLOR_BUFFER_BIT);

	const float w = (float)width(), h = (float)height();
	const GLfloat vertices[2 * 3 * 3] = {
		0.0f, 0.0f, 0.0f,
		0.0f, h, 0.0f,
		w, h, 0.0f,
		w, h, 0.0f,
		w, 0.0f, 0.0f,
		0.0f, 0.0f, 0.0f
	};

	QMatrix4x4 pmvMatrix;
	pmvMatrix.ortho(rect());

	_program->enableAttributeArray("vertexPosition");
	LogGlError;

	_program->setAttributeArray("vertexPosition", vertices, 3);
	LogGlError;
	_program->setUniformValue("matrix", pmvMatrix);
	LogGlError;
	_program->setUniformValue("screenSize", size());
	LogGlError;
	_program->setUniformValue("mousePosition", mapFromGlobal(QCursor::pos()));
	LogGlError;

	_timeSinceLastFrame.start();
	_program->setUniformValue("frameTime", (uint32_t)_timeSinceLastFrame.elapsed());
	LogGlError;
	_program->setUniformValue("totalTime", (uint32_t)_totalRunTime.elapsed());
	LogGlError;

	glDrawArrays(GL_TRIANGLES, 0, 6);
	LogGlError;

	_program->disableAttributeArray("vertexPosition");
	LogGlError;
}
<commit_msg>Live editing fragment shader code fixed<commit_after>#include "shaderrenderwidget.h"

#include <QDebug>
#include <QMatrix4x4>
#include <QMouseEvent>

#define LogGlError \
{\
	const auto err = glGetError();	\
	if (err != GL_NO_ERROR)	\
		qDebug() << "GL error" << err << "at" << __FUNCTION__ << __LINE__;	\
}

ShaderRenderWidget::ShaderRenderWidget(QWidget *parent) : QOpenGLWidget(parent)
{
}

ShaderRenderWidget::~ShaderRenderWidget()
{
}

QString ShaderRenderWidget::setFragmentShader(const QString& shaderSource)
{
	QMutexLocker locker(&_shaderProgramMutex);

	if (_program && _program->isLinked())
	{
		_program->release();
		_program->removeAllShaders();
	}

	_program = std::make_unique<QOpenGLShaderProgram>();
	_fragmentShader = std::make_unique<QOpenGLShader>(QOpenGLShader::Fragment);

	if (!_fragmentShader->compileSourceCode(shaderSource))
		return _fragmentShader->log();

	if (!_program->addShader(_fragmentShader.get()))
		qDebug() << "Failed to add fragment shader:\n" << _program->log();

	// Compile vertex shader
	if (!_program->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/resources/default_vertex_shader.vsh"))
		qDebug() << "Failed to add vertex shader:\n" << _program->log();

	if (!_program->link())
		qDebug() << "Failed to link the program\n:" << _program->log();

	return _program->log();
}

void ShaderRenderWidget::showEvent(QShowEvent *event)
{
	QOpenGLWidget::showEvent(event);
	_totalRunTime.start();
	_timeSinceLastFrame.start();
}

void ShaderRenderWidget::initializeGL()
{
	initializeOpenGLFunctions();

	glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
	LogGlError;

	connect(&timer, &QTimer::timeout, this, [this](){update();});
	timer.start(10);
}

void ShaderRenderWidget::resizeGL(int w, int h)
{
	// TODO: manually calling glViewport() has no effect in QOpenGLWidget?
//	const auto scale = devicePixelRatio();
//	glViewport(0, 0, scale * w, scale * h);
}

void ShaderRenderWidget::paintGL()
{
	QMutexLocker locker(&_shaderProgramMutex);

	if (!_program || !_program->isLinked())
		return;

	if (!_program->bind())
		qDebug() << "Failed to bind the program\n:" << _program->log();

	glClear(GL_COLOR_BUFFER_BIT);

	const float w = (float)width(), h = (float)height();
	const GLfloat vertices[2 * 3 * 3] = {
		0.0f, 0.0f, 0.0f,
		0.0f, h, 0.0f,
		w, h, 0.0f,
		w, h, 0.0f,
		w, 0.0f, 0.0f,
		0.0f, 0.0f, 0.0f
	};

	QMatrix4x4 pmvMatrix;
	pmvMatrix.ortho(rect());

	_program->enableAttributeArray("vertexPosition");
	LogGlError;

	_program->setAttributeArray("vertexPosition", vertices, 3);
	LogGlError;
	_program->setUniformValue("matrix", pmvMatrix);
	LogGlError;
	_program->setUniformValue("screenSize", size());
	LogGlError;
	_program->setUniformValue("mousePosition", mapFromGlobal(QCursor::pos()));
	LogGlError;

	_timeSinceLastFrame.start();
	_program->setUniformValue("frameTime", (uint32_t)_timeSinceLastFrame.elapsed());
	LogGlError;
	_program->setUniformValue("totalTime", (uint32_t)_totalRunTime.elapsed());
	LogGlError;

	glDrawArrays(GL_TRIANGLES, 0, 6);
	LogGlError;

	_program->disableAttributeArray("vertexPosition");
	LogGlError;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <stdio.h>
#include <fstream>
#include <vector>
//#include <map>
//#include <set>
#include <unordered_set>
//#include <unordered_map>
#include <cmath>
#include <algorithm>

// #include <gnuplot-iostream.h>
#include <assert.h>
#include <boost/program_options.hpp>
#include <boost/filesystem.hpp>

#include "vector3d.hpp"
#include "swiss_to_lat_lon.hpp"
#include "height_map.hpp"

const int horizon_angles = 360;
const int tile_size = 40;

namespace po = boost::program_options;

struct pos_hoz {
    vector3d pos;
    vector3d norm;
    short elevation_angles[horizon_angles];
    pos_hoz() : pos(0,0,0), norm(0,0,0) {
        memset(elevation_angles, 0, sizeof(short) * horizon_angles);
    }
};

bool EQ_DBL(double a, double b){
    return std::abs(a-b)<EPS_DBL;
}

int main(int ac, char** av) {

    bool test = false;
    //Variables to be assigned by program options
    double height_map_resolution;
    double north_bound;
    double south_bound;
    double east_bound;
    double west_bound;

    std::string input_file;
    std::string output_dir;
    bool verbose = false;

    // Declare the supported options.
    po::options_description op_desc("Allowed options");
    op_desc.add_options()
    ("help", "print options table")
    ("input-file,i", po::value<std::string>(&input_file), "File containing height map data in x<space>y<space>z<newline> swiss coordinates format")
    ("output-dir,o", po::value<std::string>(&output_dir), "Directory for output files (default data_out_<date_time>)")
    ("resolution,R", po::value<double>(&height_map_resolution)->default_value(25.0), "resolution of data (default: 25.0)")
    ("nmax",po::value<double>(&north_bound)->default_value(1e100), "maximum north coordinate to be treated (default 1e100)")
    ("nmin",po::value<double>(&south_bound)->default_value(-1e100), "minimum north coordinate to be treated (default -1e100)")
    ("emax",po::value<double>(&east_bound)->default_value(1e100), "maximum east coordinate to be treated (default 1e100)")
    ("emin",po::value<double>(&west_bound)->default_value(-1e100), "minimum east coordinate to be treated (default -1e100)")
    ("verbose, v", "Verbose: output lots of text")
    ;

    po::positional_options_description pd;
    pd.add("input-file", 1).add("output-file", 1);

    po::variables_map vm;
    po::store(po::parse_command_line(ac, av, op_desc), vm);
    po::notify(vm);

    if (vm.count("help")) {
        std::cout <<"ComputeHorizons [options] [input file] [output base]"<<std::endl<< op_desc << std::endl;
        return 1;
    }

    if (vm.count("verbose")){
        verbose = true;
    }
    if(!vm.count("input-file")){
        std::cout << "Input file must be specified" << std::endl;
        exit(255);
    }
    if(!vm.count("output-dir")){
        std::time_t now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
        std::string time_string(30, 0);
        std::strftime(&time_string[0], time_string.size(), "%Yx%mx%dT%Hx%Mx%S", std::localtime(&now));
        output_dir = std::string("hoz_out_")+time_string;
        std::cout << "Output directory will be: "+output_dir << std::endl;
    }

    //create output directory
    boost::filesystem::path dir(output_dir);
    if(!boost::filesystem::create_directory(dir)) {
        std::cout << "Failed to creat output directory" << "\n";
        exit(255);
    }
    std::ifstream ifs(input_file);
    if (!ifs.is_open())
        throw std::runtime_error("could not open file : " + std::string(input_file));

    height_map grid_points(ifs, south_bound, north_bound, east_bound, west_bound);

    //grid_points is a height_map, an unordered_set of all points in bounding box with
    //the maximum and minimum x,y,h of all values stored.

    std::pair<double,double> NE = swiss_to_lat_lon(grid_points.xmax()+height_map_resolution/2.0, grid_points.ymax()+height_map_resolution/2.0);
    std::pair<double,double> SW = swiss_to_lat_lon(grid_points.xmin()-height_map_resolution/2.0, grid_points.ymin()-height_map_resolution/2.0);

    std::cout << "NE: " << grid_points.xmax() <<", " << grid_points.ymax() << " SW: "<< grid_points.xmin() << " , " << grid_points.ymin() <<  std::endl;
    std::cout  << "NE: " << NE.first <<", " << NE.second << " SW: "<< SW.first << ", " << SW.second <<  std::endl;
    std::cout << "Maximum height: " << grid_points.hmax() << std::endl;
    std::cout << "Number of points in dataset: " << grid_points.size() << std::endl;

    if(test){
        double y_test = height_map_resolution*floor(601430.0/height_map_resolution);
        double x_test = height_map_resolution*floor(126243.0/height_map_resolution);
        auto it_v = grid_points.find_point(vector3d(x_test,y_test,0));      //get the gridpoint from the set
        std::cout << "Test point: " << x_test <<" "<< y_test << std::endl;
        std::cout << "Resolution: " << height_map_resolution << ", tile size: "<< tile_size << std::endl;
        vector3d v = *it_v;
        double elevation_angles[360];
        int theta_start = 0;
        int theta_end = 360;

        //        time_t start_time  = time(NULL);
        clock_t t = clock();
        for(int theta = theta_start;theta<theta_end;theta++){
            elevation_angles[theta] = grid_points.compute_elevation_angle(v, theta, height_map_resolution, 1.0);
        }
        double run_time = ((double)(clock()-t))/CLOCKS_PER_SEC;
        //        double run_time = difftime(time(NULL), start_time);
        std::cout << "phi = [";
        for(int theta = theta_start;theta<theta_end;theta++){
            std::cout << elevation_angles[theta] << ";";
        }
        std::cout << "];" << std::endl;
        std::cout << "runtime test point: " << run_time << std::endl;
        std::cout << "estimated runtime all points: " << run_time*grid_points.size() << std::endl;

        return 0;
    }

    std::string file_name;
    std::ofstream ofs;

    time_t start_time  = time(NULL);
    int N=0;
    int NT=0;

    int first_tile_y = (int) (grid_points.ymin()+10.0*height_map_resolution);
    int first_tile_x = (int) (grid_points.xmin()+10.0*height_map_resolution);
    int N_tiles_x = (int) ceil((grid_points.xmax()-grid_points.xmin()-20.0*height_map_resolution)/tile_size);
    int N_tiles_y = (int) ceil((grid_points.ymax()-grid_points.ymin()-20.0*height_map_resolution)/tile_size);

    pos_hoz tile_points[tile_size*tile_size];

    for(int x_tile = 0;x_tile<N_tiles_x; x_tile++){
# pragma omp parallal for
        for(int y_tile = 0; y_tile<N_tiles_y;y_tile++){
            double coord_x = (first_tile_x + height_map_resolution*tile_size*x_tile);
            double coord_x_end = coord_x+height_map_resolution*tile_size;
            int tile_point = 0;
            bool tile_empty = true;
            while(coord_x < coord_x_end){
                double coord_y = (first_tile_y + height_map_resolution*tile_size*y_tile);
                double coord_y_end = coord_y+height_map_resolution*tile_size;
                while(coord_y < coord_y_end){

                    //get point and points to the north, west, south and east
                    vector3d v(coord_x, coord_y, 0.0);
                    vector3d vN(v.x+height_map_resolution,v.y,0);
                    vector3d vW(v.x,v.y+height_map_resolution,0);
                    vector3d vS(v.x-height_map_resolution,v.y,0);
                    vector3d vE(v.x,v.y-height_map_resolution,0);

                    auto itv=grid_points.find_point(v);
                    auto itE=grid_points.find_point(vE);
                    auto itN=grid_points.find_point(vN);
                    auto itW=grid_points.find_point(vW);
                    auto itS=grid_points.find_point(vS);

                    if (grid_points.is_end(itv) ||grid_points.is_end(itE) || grid_points.is_end(itN) || grid_points.is_end(itW) || grid_points.is_end(itS)){
                        coord_y = coord_y + height_map_resolution;
                        //tile_points[tile_point].pos = vector3d(0,0,0);
                        //tile_point++;
                        continue;
                        //if one of the neighboring points are not found we continue with the next point
                    }
                    v = *itv;
                    vE = *itE;
                    vN = *itN;
                    vW = *itW;
                    vS = *itS;
                    tile_points[tile_point].pos = v;

                    vector3d Normal = ((((vE-v)^(vN-v))+((vW-v)^(vS-v)))/2).norm();       //normal is the crossproduct of two prependicular differences. Avgd.

                    tile_points[tile_point].norm = Normal;

                    for(int theta=0;theta<horizon_angles;theta++){
                        double phi = grid_points.compute_elevation_angle(v,theta, height_map_resolution, 360.0/horizon_angles);
                        tile_points[tile_point].elevation_angles[theta] = (short)((phi / M_PI_2) * std::numeric_limits<short>::max());
                    }
                    tile_empty = false;
                    N++;
                    coord_y = coord_y + height_map_resolution;
                    tile_point++;
                    if (N%40==0) {
                        double run_time = difftime(time(NULL), start_time);
                        int rdays = (int)floor(run_time/86400.0);
                        int rhours = (int)floor((run_time-rdays*86400)/3600.0);
                        int rminutes = (int)floor((run_time-rdays*86400.0-rhours*3600.0)/60.0);
                        int rseconds = (int)floor(run_time-rdays*86400.0-rhours*3600.0-rminutes*60.0);
                        double remaining_time = ((grid_points.size() - N)*1.0)*run_time/(N*1.0);
                        int days = (int)floor(remaining_time/86400.0);
                        int hours = (int)floor((remaining_time-days*86400)/3600.0);
                        int minutes = (int)floor((remaining_time-days*86400-hours*3600.0)/60.0);
                        int seconds = (int)floor(remaining_time-days*86400-hours*3600.0-minutes*60.0);
                        double progress = round(1000.0*100.0*(N*1.0)/(grid_points.size()*1.0))/1000.0;
                        if(N > 0){
                            std::cout <<"   Progress: "<< progress <<" %  ("<<N<<", "<<NT<<")  time: "<<rdays<<"d"<<rhours<<":"<<rminutes<<":"<<rseconds<<" time left: "<<days<<"d"<<hours<<":"<<minutes<<":"<<seconds<<"      \r";
                            std::cout.flush();
                        }
                    }

                }
                coord_x = coord_x + height_map_resolution;
            }
            if(!tile_empty){
                std::string tile_name;
                int tile_x = (first_tile_x + height_map_resolution*tile_size*x_tile);
                int tile_y = (first_tile_y + height_map_resolution*tile_size*y_tile);
                tile_name = output_dir + std::string("/tile_") + std::to_string(tile_x) + std::string("_") + std::to_string(tile_y) + std::string(".hoz");
                //            std::cout << std::endl << "tile_name " << tile_name << std::endl;
                ofs.open(tile_name, std::iostream::out | std::iostream::binary);
                //            std::cout << "first point" << tile_points[0].pos << "norm: " << tile_points[0].norm<< std::endl;
                //open output file
                if (!ofs.is_open()){
                    std::cout << "Can't open output file " << tile_name << std::endl;
                }
                ofs.write((char*)&tile_points[0], sizeof(pos_hoz)*tile_point);
                ofs.flush();
                ofs.close();
                NT++;
            }

        }
    }
    return 0;
}

<commit_msg>no more parallal<commit_after>#include <iostream>
#include <stdio.h>
#include <fstream>
#include <vector>
//#include <map>
//#include <set>
#include <unordered_set>
//#include <unordered_map>
#include <cmath>
#include <algorithm>

// #include <gnuplot-iostream.h>
#include <assert.h>
#include <boost/program_options.hpp>
#include <boost/filesystem.hpp>

#include "vector3d.hpp"
#include "swiss_to_lat_lon.hpp"
#include "height_map.hpp"

const int horizon_angles = 360;
const int tile_size = 40;

namespace po = boost::program_options;

struct pos_hoz {
    vector3d pos;
    vector3d norm;
    short elevation_angles[horizon_angles];
    pos_hoz() : pos(0,0,0), norm(0,0,0) {
        memset(elevation_angles, 0, sizeof(short) * horizon_angles);
    }
};

bool EQ_DBL(double a, double b){
    return std::abs(a-b)<EPS_DBL;
}

int main(int ac, char** av) {

    bool test = false;
    //Variables to be assigned by program options
    double height_map_resolution;
    double north_bound;
    double south_bound;
    double east_bound;
    double west_bound;

    std::string input_file;
    std::string output_dir;
    bool verbose = false;

    // Declare the supported options.
    po::options_description op_desc("Allowed options");
    op_desc.add_options()
    ("help", "print options table")
    ("input-file,i", po::value<std::string>(&input_file), "File containing height map data in x<space>y<space>z<newline> swiss coordinates format")
    ("output-dir,o", po::value<std::string>(&output_dir), "Directory for output files (default data_out_<date_time>)")
    ("resolution,R", po::value<double>(&height_map_resolution)->default_value(25.0), "resolution of data (default: 25.0)")
    ("nmax",po::value<double>(&north_bound)->default_value(1e100), "maximum north coordinate to be treated (default 1e100)")
    ("nmin",po::value<double>(&south_bound)->default_value(-1e100), "minimum north coordinate to be treated (default -1e100)")
    ("emax",po::value<double>(&east_bound)->default_value(1e100), "maximum east coordinate to be treated (default 1e100)")
    ("emin",po::value<double>(&west_bound)->default_value(-1e100), "minimum east coordinate to be treated (default -1e100)")
    ("verbose, v", "Verbose: output lots of text")
    ;

    po::positional_options_description pd;
    pd.add("input-file", 1).add("output-file", 1);

    po::variables_map vm;
    po::store(po::parse_command_line(ac, av, op_desc), vm);
    po::notify(vm);

    if (vm.count("help")) {
        std::cout <<"ComputeHorizons [options] [input file] [output base]"<<std::endl<< op_desc << std::endl;
        return 1;
    }

    if (vm.count("verbose")){
        verbose = true;
    }
    if(!vm.count("input-file")){
        std::cout << "Input file must be specified" << std::endl;
        exit(255);
    }
    if(!vm.count("output-dir")){
        std::time_t now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
        std::string time_string(30, 0);
        std::strftime(&time_string[0], time_string.size(), "%Yx%mx%dT%Hx%Mx%S", std::localtime(&now));
        output_dir = std::string("hoz_out_")+time_string;
        std::cout << "Output directory will be: "+output_dir << std::endl;
    }

    //create output directory
    boost::filesystem::path dir(output_dir);
    if(!boost::filesystem::create_directory(dir)) {
        std::cout << "Failed to creat output directory" << "\n";
        exit(255);
    }
    std::ifstream ifs(input_file);
    if (!ifs.is_open())
        throw std::runtime_error("could not open file : " + std::string(input_file));

    height_map grid_points(ifs, south_bound, north_bound, east_bound, west_bound);

    //grid_points is a height_map, an unordered_set of all points in bounding box with
    //the maximum and minimum x,y,h of all values stored.

    std::pair<double,double> NE = swiss_to_lat_lon(grid_points.xmax()+height_map_resolution/2.0, grid_points.ymax()+height_map_resolution/2.0);
    std::pair<double,double> SW = swiss_to_lat_lon(grid_points.xmin()-height_map_resolution/2.0, grid_points.ymin()-height_map_resolution/2.0);

    std::cout << "NE: " << grid_points.xmax() <<", " << grid_points.ymax() << " SW: "<< grid_points.xmin() << " , " << grid_points.ymin() <<  std::endl;
    std::cout  << "NE: " << NE.first <<", " << NE.second << " SW: "<< SW.first << ", " << SW.second <<  std::endl;
    std::cout << "Maximum height: " << grid_points.hmax() << std::endl;
    std::cout << "Number of points in dataset: " << grid_points.size() << std::endl;

    if(test){
        double y_test = height_map_resolution*floor(601430.0/height_map_resolution);
        double x_test = height_map_resolution*floor(126243.0/height_map_resolution);
        auto it_v = grid_points.find_point(vector3d(x_test,y_test,0));      //get the gridpoint from the set
        std::cout << "Test point: " << x_test <<" "<< y_test << std::endl;
        std::cout << "Resolution: " << height_map_resolution << ", tile size: "<< tile_size << std::endl;
        vector3d v = *it_v;
        double elevation_angles[360];
        int theta_start = 0;
        int theta_end = 360;

        //        time_t start_time  = time(NULL);
        clock_t t = clock();
        for(int theta = theta_start;theta<theta_end;theta++){
            elevation_angles[theta] = grid_points.compute_elevation_angle(v, theta, height_map_resolution, 1.0);
        }
        double run_time = ((double)(clock()-t))/CLOCKS_PER_SEC;
        //        double run_time = difftime(time(NULL), start_time);
        std::cout << "phi = [";
        for(int theta = theta_start;theta<theta_end;theta++){
            std::cout << elevation_angles[theta] << ";";
        }
        std::cout << "];" << std::endl;
        std::cout << "runtime test point: " << run_time << std::endl;
        std::cout << "estimated runtime all points: " << run_time*grid_points.size() << std::endl;

        return 0;
    }

    std::string file_name;
    std::ofstream ofs;

    time_t start_time  = time(NULL);
    int N=0;
    int NT=0;

    int first_tile_y = (int) (grid_points.ymin()+10.0*height_map_resolution);
    int first_tile_x = (int) (grid_points.xmin()+10.0*height_map_resolution);
    int N_tiles_x = (int) ceil((grid_points.xmax()-grid_points.xmin()-20.0*height_map_resolution)/tile_size);
    int N_tiles_y = (int) ceil((grid_points.ymax()-grid_points.ymin()-20.0*height_map_resolution)/tile_size);

    pos_hoz tile_points[tile_size*tile_size];

    for(int x_tile = 0;x_tile<N_tiles_x; x_tile++){
 #pragma omp parallel for
        for(int y_tile = 0; y_tile<N_tiles_y;y_tile++){
            double coord_x = (first_tile_x + height_map_resolution*tile_size*x_tile);
            double coord_x_end = coord_x+height_map_resolution*tile_size;
            int tile_point = 0;
            bool tile_empty = true;
            while(coord_x < coord_x_end){
                double coord_y = (first_tile_y + height_map_resolution*tile_size*y_tile);
                double coord_y_end = coord_y+height_map_resolution*tile_size;
                while(coord_y < coord_y_end){

                    //get point and points to the north, west, south and east
                    vector3d v(coord_x, coord_y, 0.0);
                    vector3d vN(v.x+height_map_resolution,v.y,0);
                    vector3d vW(v.x,v.y+height_map_resolution,0);
                    vector3d vS(v.x-height_map_resolution,v.y,0);
                    vector3d vE(v.x,v.y-height_map_resolution,0);

                    auto itv=grid_points.find_point(v);
                    auto itE=grid_points.find_point(vE);
                    auto itN=grid_points.find_point(vN);
                    auto itW=grid_points.find_point(vW);
                    auto itS=grid_points.find_point(vS);

                    if (grid_points.is_end(itv) ||grid_points.is_end(itE) || grid_points.is_end(itN) || grid_points.is_end(itW) || grid_points.is_end(itS)){
                        coord_y = coord_y + height_map_resolution;
                        //tile_points[tile_point].pos = vector3d(0,0,0);
                        //tile_point++;
                        continue;
                        //if one of the neighboring points are not found we continue with the next point
                    }
                    v = *itv;
                    vE = *itE;
                    vN = *itN;
                    vW = *itW;
                    vS = *itS;
                    tile_points[tile_point].pos = v;

                    vector3d Normal = ((((vE-v)^(vN-v))+((vW-v)^(vS-v)))/2).norm();       //normal is the crossproduct of two prependicular differences. Avgd.

                    tile_points[tile_point].norm = Normal;

                    for(int theta=0;theta<horizon_angles;theta++){
                        double phi = grid_points.compute_elevation_angle(v,theta, height_map_resolution, 360.0/horizon_angles);
                        tile_points[tile_point].elevation_angles[theta] = (short)((phi / M_PI_2) * std::numeric_limits<short>::max());
                    }
                    tile_empty = false;
                    N++;
                    coord_y = coord_y + height_map_resolution;
                    tile_point++;
                    if (N%40==0) {
                        double run_time = difftime(time(NULL), start_time);
                        int rdays = (int)floor(run_time/86400.0);
                        int rhours = (int)floor((run_time-rdays*86400)/3600.0);
                        int rminutes = (int)floor((run_time-rdays*86400.0-rhours*3600.0)/60.0);
                        int rseconds = (int)floor(run_time-rdays*86400.0-rhours*3600.0-rminutes*60.0);
                        double remaining_time = ((grid_points.size() - N)*1.0)*run_time/(N*1.0);
                        int days = (int)floor(remaining_time/86400.0);
                        int hours = (int)floor((remaining_time-days*86400)/3600.0);
                        int minutes = (int)floor((remaining_time-days*86400-hours*3600.0)/60.0);
                        int seconds = (int)floor(remaining_time-days*86400-hours*3600.0-minutes*60.0);
                        double progress = round(1000.0*100.0*(N*1.0)/(grid_points.size()*1.0))/1000.0;
                        if(N > 0){
                            std::cout <<"   Progress: "<< progress <<" %  ("<<N<<", "<<NT<<")  time: "<<rdays<<"d"<<rhours<<":"<<rminutes<<":"<<rseconds<<" time left: "<<days<<"d"<<hours<<":"<<minutes<<":"<<seconds<<"      \r";
                            std::cout.flush();
                        }
                    }

                }
                coord_x = coord_x + height_map_resolution;
            }
            if(!tile_empty){
                std::string tile_name;
                int tile_x = (first_tile_x + height_map_resolution*tile_size*x_tile);
                int tile_y = (first_tile_y + height_map_resolution*tile_size*y_tile);
                tile_name = output_dir + std::string("/tile_") + std::to_string(tile_x) + std::string("_") + std::to_string(tile_y) + std::string(".hoz");
                //            std::cout << std::endl << "tile_name " << tile_name << std::endl;
                ofs.open(tile_name, std::iostream::out | std::iostream::binary);
                //            std::cout << "first point" << tile_points[0].pos << "norm: " << tile_points[0].norm<< std::endl;
                //open output file
                if (!ofs.is_open()){
                    std::cout << "Can't open output file " << tile_name << std::endl;
                }
                ofs.write((char*)&tile_points[0], sizeof(pos_hoz)*tile_point);
                ofs.flush();
                ofs.close();
                NT++;
            }

        }
    }
    return 0;
}

<|endoftext|>