<commit_before>/*******************************************************
 * Copyright (c) 2014, ArrayFire
 * All rights reserved.
 *
 * This file is distributed under 3-clause BSD license.
 * The complete license agreement can be obtained at:
 * http://arrayfire.com/licenses/BSD-3-Clause
 ********************************************************/

#include <limits>
#include <numeric>
#include <cmath>
#include <vector>
#include <af/dim4.hpp>
#include <ArrayInfo.hpp>
#include <err_common.hpp>

namespace af
{

using std::vector;
using std::numeric_limits;
using std::abs;

dim4::dim4()
{
    dims[0] = 0;
    dims[1] = 0;
    dims[2] = 0;
    dims[3] = 0;
}

dim4::dim4( dim_type first,
            dim_type second,
            dim_type third,
            dim_type fourth)
{
    dims[0] = first;
    dims[1] = second;
    dims[2] = third;
    dims[3] = fourth;
}

dim4::dim4(const dim4& other)
{
    dims[0] = other.dims[0];
    dims[1] = other.dims[1];
    dims[2] = other.dims[2];
    dims[3] = other.dims[3];
}

dim4::dim4(const unsigned ndims_, const dim_type * const dims_)
{
    for (unsigned i = 0; i < 4; i++) {
        dims[i] = ndims_ > i ? dims_[i] : 1;
    }
}

dim_type
dim4::elements() const
{
    return dims[0] * dims[1] * dims[2] * dims[3];
}

dim_type
dim4::elements()
{
    return static_cast<const dim4&>(*this).elements();
}

dim_type
dim4::ndims() const
{
    int num = elements();
    if (num == 0) return 0;
    if (num == 1) return 1;

    if (dims[3] != 1) return 4;
    if (dims[2] != 1) return 3;
    if (dims[1] != 1) return 2;

    return 1;
}

dim_type
dim4::ndims()
{
    return static_cast<const dim4&>(*this).ndims();
}

const dim_type&
dim4::operator[](const unsigned dim) const
{
    return dims[dim];
}

dim_type &
dim4::operator[](const unsigned dim)
{
    return const_cast<dim_type&>(static_cast<const dim4&>((*this))[dim]);
}

bool
dim4::operator==(const dim4 &other) const
{
    bool ret = true;
    for(unsigned i = 0; i < 4 && ret; i++) {
        ret = (*this)[i] == other[i];
    }
    return ret;
}

bool
dim4::operator!=(const dim4 &other) const
{
    return !((*this) == other);
}

dim4&
dim4::operator*=(const dim4 &other)
{
    for(unsigned i = 0; i < 4; i++) {
        (*this)[i] *= other[i];
    }
    return *this;
}

dim4&
dim4::operator+=(const dim4 &other)
{
    for(unsigned i = 0; i < 4; i++) {
        (*this)[i] = (*this)[i] + other[i];
    }
    return *this;
}

dim4&
dim4::operator-=(const dim4 &other)
{
    for(unsigned i = 0; i < 4; i++) {
        (*this)[i] = (*this)[i] - other[i];
    }
    return *this;
}

dim4 operator+(const dim4& first, const dim4& second)
{
    dim4 dims;
    for(unsigned i = 0; i < 4; i++) {
        dims[i] = first[i] + second[i];
    }
    return dims;
}

dim4 operator-(const dim4& first, const dim4& second)
{
    dim4 dims;
    for(unsigned i = 0; i < 4; i++) {
        dims[i] = first[i] - second[i];
    }
    return dims;
}

dim4 operator*(const dim4& first, const dim4& second)
{
    dim4 dims;
    for(unsigned i = 0; i < 4; i++) {
        dims[i] = first[i] * second[i];
    }
    return dims;
}

bool
isEnd(const af_seq &seq)    { return (seq.end <= -1); }

bool
isSpan(const af_seq &seq)   { return (seq.step == 0 && seq.begin == 1 && seq.end == 1); }

size_t
seqElements(const af_seq &seq) {
    size_t out = 0;
    if      (seq.step > 0)  { out = ((seq.end - seq.begin) / abs(seq.step)) + 1;    }
    else if (seq.step < 0)  { out = ((seq.begin - seq.end) / abs(seq.step)) + 1;    }
    else                    { out = numeric_limits<size_t>::max();                  }

    return out;
}

dim4
toDims(const vector<af_seq>& seqs, dim4 parentDims)
{
    dim4 outDims(1, 1, 1, 1);
    for(unsigned i = 0; i < seqs.size(); i++ ) {
        if  (isSpan(seqs[i])) {
            outDims[i] = parentDims[i];
        } else if (isEnd(seqs[i])) {
            if(seqs[i].begin == -1) {   // only end is passed as seq
                outDims[i] = 1;
            } else if (seqs[i].begin < 0) {
                af_seq temp = {parentDims[i] + seqs[i].begin,
                               parentDims[i] + seqs[i].end,
                               seqs[i].step};
                outDims[i] = seqElements(temp);
            } else {    // end is passed as a part of seq
                af_seq temp = {seqs[i].begin, parentDims[i] + seqs[i].end, seqs[i].step};
                outDims[i] = seqElements(temp);
            }
        } else {
            DIM_ASSERT(1, seqs[i].begin >= 0 && seqs[i].begin < parentDims[i]);
            DIM_ASSERT(1, seqs[i].end < parentDims[i]);
            outDims[i] = seqElements(seqs[i]);
        }

        if (outDims[i] > parentDims[i])
            AF_ERROR("Size mismatch between input and output", AF_ERR_SIZE);
    }

    return outDims;
}

dim4
toOffset(const vector<af_seq>& seqs, dim4 parentDims)
{
    dim4 outOffsets(0, 0, 0, 0);
    for(unsigned i = 0; i < seqs.size(); i++ ) {
        if (seqs[i].step !=0 && seqs[i].begin >= 0) {
            outOffsets[i] = seqs[i].begin;
        } else if (seqs[i].begin <= -1) {
            outOffsets[i] = parentDims[i] + seqs[i].begin;
        } else {
            outOffsets[i] = 0;
        }

        if (outOffsets[i] >= parentDims[i])
            AF_ERROR("Index out of range", AF_ERR_SIZE);
    }
    return outOffsets;
}

dim4
toStride(const vector<af_seq>& seqs, af::dim4 parentDims)
{
    dim4 out(calcStrides(parentDims));
    for(unsigned i = 0; i < seqs.size(); i++ ) {
        if  (seqs[i].step != 0) {   out[i] *= seqs[i].step; }
    }
    return out;
}
}
<commit_msg>Fixed faulty float comparison<commit_after>/*******************************************************
 * Copyright (c) 2014, ArrayFire
 * All rights reserved.
 *
 * This file is distributed under 3-clause BSD license.
 * The complete license agreement can be obtained at:
 * http://arrayfire.com/licenses/BSD-3-Clause
 ********************************************************/

#include <limits>
#include <numeric>
#include <cmath>
#include <cfloat>
#include <vector>
#include <af/dim4.hpp>
#include <ArrayInfo.hpp>
#include <err_common.hpp>

namespace af
{

using std::vector;
using std::numeric_limits;
using std::abs;

dim4::dim4()
{
    dims[0] = 0;
    dims[1] = 0;
    dims[2] = 0;
    dims[3] = 0;
}

dim4::dim4( dim_type first,
            dim_type second,
            dim_type third,
            dim_type fourth)
{
    dims[0] = first;
    dims[1] = second;
    dims[2] = third;
    dims[3] = fourth;
}

dim4::dim4(const dim4& other)
{
    dims[0] = other.dims[0];
    dims[1] = other.dims[1];
    dims[2] = other.dims[2];
    dims[3] = other.dims[3];
}

dim4::dim4(const unsigned ndims_, const dim_type * const dims_)
{
    for (unsigned i = 0; i < 4; i++) {
        dims[i] = ndims_ > i ? dims_[i] : 1;
    }
}

dim_type
dim4::elements() const
{
    return dims[0] * dims[1] * dims[2] * dims[3];
}

dim_type
dim4::elements()
{
    return static_cast<const dim4&>(*this).elements();
}

dim_type
dim4::ndims() const
{
    int num = elements();
    if (num == 0) return 0;
    if (num == 1) return 1;

    if (dims[3] != 1) return 4;
    if (dims[2] != 1) return 3;
    if (dims[1] != 1) return 2;

    return 1;
}

dim_type
dim4::ndims()
{
    return static_cast<const dim4&>(*this).ndims();
}

const dim_type&
dim4::operator[](const unsigned dim) const
{
    return dims[dim];
}

dim_type &
dim4::operator[](const unsigned dim)
{
    return const_cast<dim_type&>(static_cast<const dim4&>((*this))[dim]);
}

bool
dim4::operator==(const dim4 &other) const
{
    bool ret = true;
    for(unsigned i = 0; i < 4 && ret; i++) {
        ret = (*this)[i] == other[i];
    }
    return ret;
}

bool
dim4::operator!=(const dim4 &other) const
{
    return !((*this) == other);
}

dim4&
dim4::operator*=(const dim4 &other)
{
    for(unsigned i = 0; i < 4; i++) {
        (*this)[i] *= other[i];
    }
    return *this;
}

dim4&
dim4::operator+=(const dim4 &other)
{
    for(unsigned i = 0; i < 4; i++) {
        (*this)[i] = (*this)[i] + other[i];
    }
    return *this;
}

dim4&
dim4::operator-=(const dim4 &other)
{
    for(unsigned i = 0; i < 4; i++) {
        (*this)[i] = (*this)[i] - other[i];
    }
    return *this;
}

dim4 operator+(const dim4& first, const dim4& second)
{
    dim4 dims;
    for(unsigned i = 0; i < 4; i++) {
        dims[i] = first[i] + second[i];
    }
    return dims;
}

dim4 operator-(const dim4& first, const dim4& second)
{
    dim4 dims;
    for(unsigned i = 0; i < 4; i++) {
        dims[i] = first[i] - second[i];
    }
    return dims;
}

dim4 operator*(const dim4& first, const dim4& second)
{
    dim4 dims;
    for(unsigned i = 0; i < 4; i++) {
        dims[i] = first[i] * second[i];
    }
    return dims;
}

bool
isEnd(const af_seq &seq)    { return (seq.end <= -1); }

bool
isSpan(const af_seq &seq)   { return (seq.step == 0 && seq.begin == 1 && seq.end == 1); }

size_t
seqElements(const af_seq &seq) {
    size_t out = 0;
    if      (seq.step > DBL_MIN)    { out = ((seq.end - seq.begin) / abs(seq.step)) + 1;    }
    else if (seq.step < -DBL_MIN)   { out = ((seq.begin - seq.end) / abs(seq.step)) + 1;    }
    else                            { out = numeric_limits<size_t>::max();                  }

    return out;
}

dim4
toDims(const vector<af_seq>& seqs, dim4 parentDims)
{
    dim4 outDims(1, 1, 1, 1);
    for(unsigned i = 0; i < seqs.size(); i++ ) {
        if  (isSpan(seqs[i])) {
            outDims[i] = parentDims[i];
        } else if (isEnd(seqs[i])) {
            if(seqs[i].begin == -1) {   // only end is passed as seq
                outDims[i] = 1;
            } else if (seqs[i].begin < 0) {
                af_seq temp = {parentDims[i] + seqs[i].begin,
                               parentDims[i] + seqs[i].end,
                               seqs[i].step};
                outDims[i] = seqElements(temp);
            } else {    // end is passed as a part of seq
                af_seq temp = {seqs[i].begin, parentDims[i] + seqs[i].end, seqs[i].step};
                outDims[i] = seqElements(temp);
            }
        } else {
            DIM_ASSERT(1, seqs[i].begin >= 0 && seqs[i].begin < parentDims[i]);
            DIM_ASSERT(1, seqs[i].end < parentDims[i]);
            outDims[i] = seqElements(seqs[i]);
        }

        if (outDims[i] > parentDims[i])
            AF_ERROR("Size mismatch between input and output", AF_ERR_SIZE);
    }

    return outDims;
}

dim4
toOffset(const vector<af_seq>& seqs, dim4 parentDims)
{
    dim4 outOffsets(0, 0, 0, 0);
    for(unsigned i = 0; i < seqs.size(); i++ ) {
        if (seqs[i].step !=0 && seqs[i].begin >= 0) {
            outOffsets[i] = seqs[i].begin;
        } else if (seqs[i].begin <= -1) {
            outOffsets[i] = parentDims[i] + seqs[i].begin;
        } else {
            outOffsets[i] = 0;
        }

        if (outOffsets[i] >= parentDims[i])
            AF_ERROR("Index out of range", AF_ERR_SIZE);
    }
    return outOffsets;
}

dim4
toStride(const vector<af_seq>& seqs, af::dim4 parentDims)
{
    dim4 out(calcStrides(parentDims));
    for(unsigned i = 0; i < seqs.size(); i++ ) {
        if  (seqs[i].step != 0) {   out[i] *= seqs[i].step; }
    }
    return out;
}
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2003-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders 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
 * OWNER 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.
 *
 * Authors: Steve Reinhardt
 *          Nathan Binkert
 */

#ifndef __BASE_BITFIELD_HH__
#define __BASE_BITFIELD_HH__

#include <inttypes.h>

/**
 * Generate a 64-bit mask of 'nbits' 1s, right justified.
 */
inline uint64_t
mask(int nbits)
{
    return (nbits == 64) ? (uint64_t)-1LL : (1ULL << nbits) - 1;
}

/**
 * Extract the bitfield from position 'first' to 'last' (inclusive)
 * from 'val' and right justify it.  MSB is numbered 63, LSB is 0.
 */
template <class T>
inline
T
bits(T val, int first, int last)
{
    int nbits = first - last + 1;
    return (val >> last) & mask(nbits);
}

/**
 * Mask off the given bits in place like bits() but without shifting.
 * msb = 63, lsb = 0
 */
template <class T>
inline
T
mbits(T val, int first, int last)
{
    return val & (mask(first+1) & ~mask(last));
}

inline uint64_t
mask(int first, int last)
{
    return mbits((uint64_t)-1LL, first, last);
}

/**
 * Sign-extend an N-bit value to 64 bits.
 */
template <int N>
inline
int64_t
sext(uint64_t val)
{
    int sign_bit = bits(val, N-1, N-1);
    return sign_bit ? (val | ~mask(N)) : val;
}

/**
 * Return val with bits first to last set to bit_val
 */
template <class T, class B>
inline
T
insertBits(T val, int first, int last, B bit_val)
{
    T bmask = mask(first - last + 1) << last;
    return ((bit_val << last) & bmask) | (val & ~bmask);
}

/**
 * A convenience function to replace bits first to last of val with bit_val
 * in place.
 */
template <class T, class B>
inline
void
replaceBits(T& val, int first, int last, B bit_val)
{
    val = insertBits(val, first, last, bit_val);
}

/**
 * Returns the bit position of the MSB that is set in the input
 */
inline
int
findMsbSet(uint64_t val) {
    int msb = 0;
    if (!val)
        return 0;
    if (bits(val, 63,32)) { msb += 32; val >>= 32; }
    if (bits(val, 31,16)) { msb += 16; val >>= 16; }
    if (bits(val, 15,8))  { msb += 8;  val >>= 8;  }
    if (bits(val, 7,4))   { msb += 4;  val >>= 4;  }
    if (bits(val, 3,2))   { msb += 2;  val >>= 2;  }
    if (bits(val, 1,1))   { msb += 1; }
    return msb;
}

//	The following implements the BitUnion system of defining bitfields
//on top of an underlying class. This is done through the pervasive use of
//both named and unnamed unions which all contain the same actual storage.
//Since they're unioned with each other, all of these storage locations
//overlap. This allows all of the bitfields to manipulate the same data
//without having to have access to each other. More details are provided with the
//individual components.

//This namespace is for classes which implement the backend of the BitUnion
//stuff. Don't use any of these directly, except for the Bitfield classes in
//the *BitfieldTypes class(es).
namespace BitfieldBackend
{
    //A base class for all bitfields. It instantiates the actual storage,
    //and provides getBits and setBits functions for manipulating it. The
    //Data template parameter is type of the underlying storage.
    template<class Data>
    class BitfieldBase
    {
      protected:
        Data __data;

        //This function returns a range of bits from the underlying storage.
        //It relies on the "bits" function above. It's the user's
        //responsibility to make sure that there is a properly overloaded
        //version of this function for whatever type they want to overlay.
        inline uint64_t
        getBits(int first, int last) const
        {
            return bits(__data, first, last);
        }

        //Similar to the above, but for settings bits with replaceBits.
        inline void
        setBits(int first, int last, uint64_t val)
        {
            replaceBits(__data, first, last, val);
        }
    };

    //This class contains all the "regular" bitfield classes. It is inherited
    //by all BitUnions which give them access to those types.
    template<class Type>
    class RegularBitfieldTypes
    {
      protected:
        //This class implements ordinary bitfields, that is a span of bits
        //who's msb is "first", and who's lsb is "last".
        template<int first, int last=first>
        class Bitfield : public BitfieldBase<Type>
        {
          public:
            operator uint64_t () const
            {
                return this->getBits(first, last);
            }

            uint64_t
            operator=(const uint64_t _data)
            {
                this->setBits(first, last, _data);
                return _data;
            }
        };

        //A class which specializes the above so that it can only be read
        //from. This is accomplished explicitly making sure the assignment
        //operator is blocked. The conversion operator is carried through
        //inheritance. This will unfortunately need to be copied into each
        //bitfield type due to limitations with how templates work
        template<int first, int last=first>
        class BitfieldRO : public Bitfield<first, last>
        {
          private:
            uint64_t
            operator=(const uint64_t _data);
        };

        //Similar to the above, but only allows writing.
        template<int first, int last=first>
        class BitfieldWO : public Bitfield<first, last>
        {
          private:
            operator uint64_t () const;

          public:
            using Bitfield<first, last>::operator=;
        };
    };

    //This class contains all the "regular" bitfield classes. It is inherited
    //by all BitUnions which give them access to those types.
    template<class Type>
    class SignedBitfieldTypes
    {
      protected:
        //This class implements ordinary bitfields, that is a span of bits
        //who's msb is "first", and who's lsb is "last".
        template<int first, int last=first>
        class SignedBitfield : public BitfieldBase<Type>
        {
          public:
            operator int64_t () const
            {
                return sext<first - last + 1>(this->getBits(first, last));
            }

            int64_t
            operator=(const int64_t _data)
            {
                this->setBits(first, last, _data);
                return _data;
            }
        };

        //A class which specializes the above so that it can only be read
        //from. This is accomplished explicitly making sure the assignment
        //operator is blocked. The conversion operator is carried through
        //inheritance. This will unfortunately need to be copied into each
        //bitfield type due to limitations with how templates work
        template<int first, int last=first>
        class SignedBitfieldRO : public SignedBitfield<first, last>
        {
          private:
            int64_t
            operator=(const int64_t _data);
        };

        //Similar to the above, but only allows writing.
        template<int first, int last=first>
        class SignedBitfieldWO : public SignedBitfield<first, last>
        {
          private:
            operator int64_t () const;

          public:
            int64_t operator=(const int64_t _data)
            {
                *((SignedBitfield<first, last> *)this) = _data;
                return _data;
            }
        };
    };

    template<class Type>
    class BitfieldTypes : public RegularBitfieldTypes<Type>,
                          public SignedBitfieldTypes<Type>
    {};

    //When a BitUnion is set up, an underlying class is created which holds
    //the actual union. This class then inherits from it, and provids the
    //implementations for various operators. Setting things up this way
    //prevents having to redefine these functions in every different BitUnion
    //type. More operators could be implemented in the future, as the need
    //arises.
    template <class Type, class Base>
    class BitUnionOperators : public Base
    {
      public:
        operator Type () const
        {
            return Base::__data;
        }

        Type
        operator=(const Type & _data)
        {
            Base::__data = _data;
            return _data;
        }

        bool
        operator<(const Base & base) const
        {
            return Base::__data < base.__data;
        }

        bool
        operator==(const Base & base) const
        {
            return Base::__data == base.__data;
        }
    };
}

//This macro is a backend for other macros that specialize it slightly.
//First, it creates/extends a namespace "BitfieldUnderlyingClasses" and
//sticks the class which has the actual union in it, which
//BitfieldOperators above inherits from. Putting these classes in a special
//namespace ensures that there will be no collisions with other names as long
//as the BitUnion names themselves are all distinct and nothing else uses
//the BitfieldUnderlyingClasses namespace, which is unlikely. The class itself
//creates a typedef of the "type" parameter called __DataType. This allows
//the type to propagate outside of the macro itself in a controlled way.
//Finally, the base storage is defined which BitfieldOperators will refer to
//in the operators it defines. This macro is intended to be followed by
//bitfield definitions which will end up inside it's union. As explained
//above, these is overlayed the __data member in its entirety by each of the
//bitfields which are defined in the union, creating shared storage with no
//overhead.
#define __BitUnion(type, name) \
    namespace BitfieldUnderlyingClasses \
    { \
        class name; \
    } \
    class BitfieldUnderlyingClasses::name : \
        public BitfieldBackend::BitfieldTypes<type> \
    { \
      public: \
        typedef type __DataType; \
        union { \
            type __data;\

//This closes off the class and union started by the above macro. It is
//followed by a typedef which makes "name" refer to a BitfieldOperator
//class inheriting from the class and union just defined, which completes
//building up the type for the user.
#define EndBitUnion(name) \
        }; \
    }; \
    typedef BitfieldBackend::BitUnionOperators< \
        BitfieldUnderlyingClasses::name::__DataType, \
        BitfieldUnderlyingClasses::name> name;

//This sets up a bitfield which has other bitfields nested inside of it. The
//__data member functions like the "underlying storage" of the top level
//BitUnion. Like everything else, it overlays with the top level storage, so
//making it a regular bitfield type makes the entire thing function as a
//regular bitfield when referred to by itself.
#define __SubBitUnion(fieldType, first, last, name) \
    class : public BitfieldBackend::BitfieldTypes<__DataType> \
    { \
      public: \
        union { \
            fieldType<first, last> __data;

//This closes off the union created above and gives it a name. Unlike the top
//level BitUnion, we're interested in creating an object instead of a type.
//The operators are defined in the macro itself instead of a class for
//technical reasons. If someone determines a way to move them to one, please
//do so.
#define EndSubBitUnion(name) \
        }; \
        inline operator const __DataType () \
        { return __data; } \
        \
        inline const __DataType operator = (const __DataType & _data) \
        { __data = _data; } \
    } name;

//Regular bitfields
//These define macros for read/write regular bitfield based subbitfields.
#define SubBitUnion(name, first, last) \
    __SubBitUnion(Bitfield, first, last, name)

//Regular bitfields
//These define macros for read/write regular bitfield based subbitfields.
#define SignedSubBitUnion(name, first, last) \
    __SubBitUnion(SignedBitfield, first, last, name)

//Use this to define an arbitrary type overlayed with bitfields.
#define BitUnion(type, name) __BitUnion(type, name)

//Use this to define conveniently sized values overlayed with bitfields.
#define BitUnion64(name) __BitUnion(uint64_t, name)
#define BitUnion32(name) __BitUnion(uint32_t, name)
#define BitUnion16(name) __BitUnion(uint16_t, name)
#define BitUnion8(name) __BitUnion(uint8_t, name)

#endif // __BASE_BITFIELD_HH__
<commit_msg>Fix insertBits so it doesn't shift things into oblivion<commit_after>/*
 * Copyright (c) 2003-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders 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
 * OWNER 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.
 *
 * Authors: Steve Reinhardt
 *          Nathan Binkert
 */

#ifndef __BASE_BITFIELD_HH__
#define __BASE_BITFIELD_HH__

#include <inttypes.h>

/**
 * Generate a 64-bit mask of 'nbits' 1s, right justified.
 */
inline uint64_t
mask(int nbits)
{
    return (nbits == 64) ? (uint64_t)-1LL : (1ULL << nbits) - 1;
}

/**
 * Extract the bitfield from position 'first' to 'last' (inclusive)
 * from 'val' and right justify it.  MSB is numbered 63, LSB is 0.
 */
template <class T>
inline
T
bits(T val, int first, int last)
{
    int nbits = first - last + 1;
    return (val >> last) & mask(nbits);
}

/**
 * Mask off the given bits in place like bits() but without shifting.
 * msb = 63, lsb = 0
 */
template <class T>
inline
T
mbits(T val, int first, int last)
{
    return val & (mask(first+1) & ~mask(last));
}

inline uint64_t
mask(int first, int last)
{
    return mbits((uint64_t)-1LL, first, last);
}

/**
 * Sign-extend an N-bit value to 64 bits.
 */
template <int N>
inline
int64_t
sext(uint64_t val)
{
    int sign_bit = bits(val, N-1, N-1);
    return sign_bit ? (val | ~mask(N)) : val;
}

/**
 * Return val with bits first to last set to bit_val
 */
template <class T, class B>
inline
T
insertBits(T val, int first, int last, B bit_val)
{
    T t_bit_val = bit_val;
    T bmask = mask(first - last + 1) << last;
    return ((t_bit_val << last) & bmask) | (val & ~bmask);
}

/**
 * A convenience function to replace bits first to last of val with bit_val
 * in place.
 */
template <class T, class B>
inline
void
replaceBits(T& val, int first, int last, B bit_val)
{
    val = insertBits(val, first, last, bit_val);
}

/**
 * Returns the bit position of the MSB that is set in the input
 */
inline
int
findMsbSet(uint64_t val) {
    int msb = 0;
    if (!val)
        return 0;
    if (bits(val, 63,32)) { msb += 32; val >>= 32; }
    if (bits(val, 31,16)) { msb += 16; val >>= 16; }
    if (bits(val, 15,8))  { msb += 8;  val >>= 8;  }
    if (bits(val, 7,4))   { msb += 4;  val >>= 4;  }
    if (bits(val, 3,2))   { msb += 2;  val >>= 2;  }
    if (bits(val, 1,1))   { msb += 1; }
    return msb;
}

//	The following implements the BitUnion system of defining bitfields
//on top of an underlying class. This is done through the pervasive use of
//both named and unnamed unions which all contain the same actual storage.
//Since they're unioned with each other, all of these storage locations
//overlap. This allows all of the bitfields to manipulate the same data
//without having to have access to each other. More details are provided with the
//individual components.

//This namespace is for classes which implement the backend of the BitUnion
//stuff. Don't use any of these directly, except for the Bitfield classes in
//the *BitfieldTypes class(es).
namespace BitfieldBackend
{
    //A base class for all bitfields. It instantiates the actual storage,
    //and provides getBits and setBits functions for manipulating it. The
    //Data template parameter is type of the underlying storage.
    template<class Data>
    class BitfieldBase
    {
      protected:
        Data __data;

        //This function returns a range of bits from the underlying storage.
        //It relies on the "bits" function above. It's the user's
        //responsibility to make sure that there is a properly overloaded
        //version of this function for whatever type they want to overlay.
        inline uint64_t
        getBits(int first, int last) const
        {
            return bits(__data, first, last);
        }

        //Similar to the above, but for settings bits with replaceBits.
        inline void
        setBits(int first, int last, uint64_t val)
        {
            replaceBits(__data, first, last, val);
        }
    };

    //This class contains all the "regular" bitfield classes. It is inherited
    //by all BitUnions which give them access to those types.
    template<class Type>
    class RegularBitfieldTypes
    {
      protected:
        //This class implements ordinary bitfields, that is a span of bits
        //who's msb is "first", and who's lsb is "last".
        template<int first, int last=first>
        class Bitfield : public BitfieldBase<Type>
        {
          public:
            operator uint64_t () const
            {
                return this->getBits(first, last);
            }

            uint64_t
            operator=(const uint64_t _data)
            {
                this->setBits(first, last, _data);
                return _data;
            }
        };

        //A class which specializes the above so that it can only be read
        //from. This is accomplished explicitly making sure the assignment
        //operator is blocked. The conversion operator is carried through
        //inheritance. This will unfortunately need to be copied into each
        //bitfield type due to limitations with how templates work
        template<int first, int last=first>
        class BitfieldRO : public Bitfield<first, last>
        {
          private:
            uint64_t
            operator=(const uint64_t _data);
        };

        //Similar to the above, but only allows writing.
        template<int first, int last=first>
        class BitfieldWO : public Bitfield<first, last>
        {
          private:
            operator uint64_t () const;

          public:
            using Bitfield<first, last>::operator=;
        };
    };

    //This class contains all the "regular" bitfield classes. It is inherited
    //by all BitUnions which give them access to those types.
    template<class Type>
    class SignedBitfieldTypes
    {
      protected:
        //This class implements ordinary bitfields, that is a span of bits
        //who's msb is "first", and who's lsb is "last".
        template<int first, int last=first>
        class SignedBitfield : public BitfieldBase<Type>
        {
          public:
            operator int64_t () const
            {
                return sext<first - last + 1>(this->getBits(first, last));
            }

            int64_t
            operator=(const int64_t _data)
            {
                this->setBits(first, last, _data);
                return _data;
            }
        };

        //A class which specializes the above so that it can only be read
        //from. This is accomplished explicitly making sure the assignment
        //operator is blocked. The conversion operator is carried through
        //inheritance. This will unfortunately need to be copied into each
        //bitfield type due to limitations with how templates work
        template<int first, int last=first>
        class SignedBitfieldRO : public SignedBitfield<first, last>
        {
          private:
            int64_t
            operator=(const int64_t _data);
        };

        //Similar to the above, but only allows writing.
        template<int first, int last=first>
        class SignedBitfieldWO : public SignedBitfield<first, last>
        {
          private:
            operator int64_t () const;

          public:
            int64_t operator=(const int64_t _data)
            {
                *((SignedBitfield<first, last> *)this) = _data;
                return _data;
            }
        };
    };

    template<class Type>
    class BitfieldTypes : public RegularBitfieldTypes<Type>,
                          public SignedBitfieldTypes<Type>
    {};

    //When a BitUnion is set up, an underlying class is created which holds
    //the actual union. This class then inherits from it, and provids the
    //implementations for various operators. Setting things up this way
    //prevents having to redefine these functions in every different BitUnion
    //type. More operators could be implemented in the future, as the need
    //arises.
    template <class Type, class Base>
    class BitUnionOperators : public Base
    {
      public:
        operator Type () const
        {
            return Base::__data;
        }

        Type
        operator=(const Type & _data)
        {
            Base::__data = _data;
            return _data;
        }

        bool
        operator<(const Base & base) const
        {
            return Base::__data < base.__data;
        }

        bool
        operator==(const Base & base) const
        {
            return Base::__data == base.__data;
        }
    };
}

//This macro is a backend for other macros that specialize it slightly.
//First, it creates/extends a namespace "BitfieldUnderlyingClasses" and
//sticks the class which has the actual union in it, which
//BitfieldOperators above inherits from. Putting these classes in a special
//namespace ensures that there will be no collisions with other names as long
//as the BitUnion names themselves are all distinct and nothing else uses
//the BitfieldUnderlyingClasses namespace, which is unlikely. The class itself
//creates a typedef of the "type" parameter called __DataType. This allows
//the type to propagate outside of the macro itself in a controlled way.
//Finally, the base storage is defined which BitfieldOperators will refer to
//in the operators it defines. This macro is intended to be followed by
//bitfield definitions which will end up inside it's union. As explained
//above, these is overlayed the __data member in its entirety by each of the
//bitfields which are defined in the union, creating shared storage with no
//overhead.
#define __BitUnion(type, name) \
    namespace BitfieldUnderlyingClasses \
    { \
        class name; \
    } \
    class BitfieldUnderlyingClasses::name : \
        public BitfieldBackend::BitfieldTypes<type> \
    { \
      public: \
        typedef type __DataType; \
        union { \
            type __data;\

//This closes off the class and union started by the above macro. It is
//followed by a typedef which makes "name" refer to a BitfieldOperator
//class inheriting from the class and union just defined, which completes
//building up the type for the user.
#define EndBitUnion(name) \
        }; \
    }; \
    typedef BitfieldBackend::BitUnionOperators< \
        BitfieldUnderlyingClasses::name::__DataType, \
        BitfieldUnderlyingClasses::name> name;

//This sets up a bitfield which has other bitfields nested inside of it. The
//__data member functions like the "underlying storage" of the top level
//BitUnion. Like everything else, it overlays with the top level storage, so
//making it a regular bitfield type makes the entire thing function as a
//regular bitfield when referred to by itself.
#define __SubBitUnion(fieldType, first, last, name) \
    class : public BitfieldBackend::BitfieldTypes<__DataType> \
    { \
      public: \
        union { \
            fieldType<first, last> __data;

//This closes off the union created above and gives it a name. Unlike the top
//level BitUnion, we're interested in creating an object instead of a type.
//The operators are defined in the macro itself instead of a class for
//technical reasons. If someone determines a way to move them to one, please
//do so.
#define EndSubBitUnion(name) \
        }; \
        inline operator const __DataType () \
        { return __data; } \
        \
        inline const __DataType operator = (const __DataType & _data) \
        { __data = _data; } \
    } name;

//Regular bitfields
//These define macros for read/write regular bitfield based subbitfields.
#define SubBitUnion(name, first, last) \
    __SubBitUnion(Bitfield, first, last, name)

//Regular bitfields
//These define macros for read/write regular bitfield based subbitfields.
#define SignedSubBitUnion(name, first, last) \
    __SubBitUnion(SignedBitfield, first, last, name)

//Use this to define an arbitrary type overlayed with bitfields.
#define BitUnion(type, name) __BitUnion(type, name)

//Use this to define conveniently sized values overlayed with bitfields.
#define BitUnion64(name) __BitUnion(uint64_t, name)
#define BitUnion32(name) __BitUnion(uint32_t, name)
#define BitUnion16(name) __BitUnion(uint16_t, name)
#define BitUnion8(name) __BitUnion(uint8_t, name)

#endif // __BASE_BITFIELD_HH__
<|endoftext|>


<commit_before><commit_msg>Limit display length of back/forward menu page titles to 700px.<commit_after><|endoftext|>


<commit_before><commit_msg>arraysize doesn't accept a type defined inside a function.  In these rare  cases, I have to use the unsafe ARRAYSIZE_UNSAFE() macro<commit_after><|endoftext|>


<commit_before><commit_msg>Make texture shader demo start working.<commit_after><|endoftext|>


<commit_before>/*
 * ty, a collection of GUI and command-line tools to manage Teensy devices
 *
 * Distributed under the MIT license (see LICENSE.txt or http://opensource.org/licenses/MIT)
 * Copyright (c) 2015 Niels Martignène <niels.martignene@gmail.com>
 */

#ifdef _WIN32
    #include <windows.h>
#endif
#include <QCoreApplication>
#include <QFile>
#include <QSaveFile>
#include <QTextStream>

#include "arduino_install.hh"
#include "tyqt.hh"

using namespace std;

ArduinoInstallation::ArduinoInstallation(const QString &path)
{
    setPath(path);
}

void ArduinoInstallation::setPath(const QString &path)
{
    dir_.setPath(path);
    update();
}

void ArduinoInstallation::update()
{
    updateState();
    emit changed();
}

bool ArduinoInstallation::integrate()
{
    if (arduino_legacy_)
        return integrateLegacy();

    emit log(tr("Integrate TyQt to '%1'").arg(QDir::toNativeSeparators(dir_.path())));

    auto filename = arduinoPath("hardware/teensy/avr/platform.txt");
    emit log(tr("Rewrite '%1' (to temporary file)").arg(nicePath(filename)));

    QFile src(filename);
    QSaveFile dest(filename);

    if (!src.open(QIODevice::ReadOnly | QIODevice::Text))
        return reportFileError(src);
    if (!dest.open(QIODevice::WriteOnly | QIODevice::Text))
        return reportFileError(dest);

    QTextStream in(&src), out(&dest);
    bool integrated = false;
    for (unsigned int i = 1; !in.atEnd(); i++) {
        auto line = in.readLine();

        if (line.contains("TyQt", Qt::CaseInsensitive)) {
            emit error(tr("This installation is already patched"));
            return false;
        }

        if (line.startsWith("tools.teensyloader") || line.contains("teensy_post_compile")) {
            emit log(tr(" + Comment out line %1 '%2...'").arg(i).arg(line.left(22)));
            out << "#";
        }
        out << line << "\n";

        if (line.startsWith("tools.teensyloader.upload.pattern") && !integrated) {
            emit log(tr(" + Integrate TyQt instructions after line %1").arg(i));
            out << QString("\n## TyQt\n"
                           "tools.teensyloader.cmd.path=%1\n").arg(QDir::toNativeSeparators(tyQt->clientFilePath()));
            out << "tools.teensyloader.upload.params.quiet=--quiet\n"
                   "tools.teensyloader.upload.params.verbose=\n"
                   "tools.teensyloader.upload.pattern=\"{cmd.path}\" upload --autostart --wait"
                   " \"{build.path}/{build.project_name}.hex\"\n";
            integrated = true;
        }
    }
    if (!integrated) {
        emit error(tr("Failed to add TyQt instructions"));
        return false;
    }

    if (src.error())
        return reportFileError(src);
    src.close();

    if (dest.error())
        return reportFileError(dest);
    if (!dest.flush())
        return reportFileError(dest);

    emit log(tr("Backup '%1' to '%2'").arg(nicePath(filename), nicePath(filename + ".notyqt")));
    if (!safeCopy(filename, filename + ".notyqt"))
        return false;

    emit log(tr("Commit changes to '%1'").arg(nicePath(filename)));
    if (!dest.commit())
        return reportFileError(dest);

    update();
    return true;
}

bool ArduinoInstallation::restore()
{
    emit log(tr("Remove TyQt integration from '%1'").arg(QDir::toNativeSeparators(dir_.path())));

    QString filename;
    if (arduino_legacy_) {
        filename = arduinoPath("hardware/teensy/boards.txt");
    } else {
        filename = arduinoPath("hardware/teensy/avr/platform.txt");
    }
    if (!findMarker(filename, "TyQt")) {
        emit error(tr("This installation is not using TyQt"));
        return false;
    }

    emit log(tr("Copy '%1' to '%2'").arg(nicePath(filename + ".notyqt"), nicePath(filename)));
    if (!safeCopy(filename + ".notyqt", filename))
        return false;

    if (arduino_legacy_) {
#ifdef _WIN32
        emit log(tr("Remove avrdude script '%1'").arg("hardware/tools/tyqt_avrdude.bat"));
        QFile::remove(arduinoPath("hardware/tools/tyqt_avrdude.bat"));
#else
        emit log(tr("Remove avrdude script '%1'").arg("hardware/tools/tyqt_avrdude.sh"));
        QFile::remove(arduinoPath("hardware/tools/tyqt_avrdude.sh"));
#endif
    }

    update();
    return true;
}

bool ArduinoInstallation::integrateLegacy()
{
    emit log(tr("Integrate TyQt to '%1' (legacy)").arg(QDir::toNativeSeparators(dir_.path())));

    auto filename = arduinoPath("hardware/teensy/boards.txt");
    emit log(tr("Rewrite '%1' (to temporary file)").arg(nicePath(filename)));

    QFile src(filename);
    QSaveFile dest(filename);

    if (!src.open(QIODevice::ReadOnly | QIODevice::Text))
        return reportFileError(src);
    if (!dest.open(QIODevice::WriteOnly | QIODevice::Text))
        return reportFileError(dest);

    QTextStream in(&src), out(&dest);
    QStringList models;
    for (unsigned int i = 1; !in.atEnd(); i++) {
        auto line = in.readLine();

        if (line.contains("TyQt", Qt::CaseInsensitive)) {
            emit error(tr("This installation is already patched"));
            return false;
        }

        if (line.startsWith("teensy") && line.contains("upload.avrdude_wrapper")) {
            models.append(line.section('.', 0, 0));

            emit log(tr(" + Comment out line %1 '%2...'").arg(i).arg(line.left(22)));
            out << "#";
        } else if (line.contains("teensy_post_compile")) {
            emit log(tr(" + Comment out line %1 '%2...'").arg(i).arg(line.left(22)));
            out << "#";
        }
        out << line << "\n";
    }
    if (models.isEmpty()) {
        emit error(tr("Failed to add TyQt instructions"));
        return false;
    }

    out << "\n## TyQt (legacy Arduino)\n";
    for (auto &model: models) {
        emit log(tr(" + Add TyQt instructions for '%1'").arg(model));
#ifdef _WIN32
        out << QString("%1.upload.avrdude_wrapper=tyqt_avrdude.bat\n").arg(model);
#else
        out << QString("%1.upload.avrdude_wrapper=tyqt_avrdude.sh\n").arg(model);
#endif
    }

    if (src.error())
        return reportFileError(src);
    src.close();

    if (dest.error())
        return reportFileError(dest);
    if (!dest.flush())
        return reportFileError(dest);

    if (!writeAvrdudeScript())
        return false;

    emit log(tr("Backup '%1' to '%2'").arg(nicePath(filename), nicePath(filename + ".notyqt")));
    if (!safeCopy(filename, filename + ".notyqt"))
        return false;

    emit log(tr("Commit changes to '%1'").arg(nicePath(filename)));
    if (!dest.commit())
        return reportFileError(dest);

    update();
    return true;
}

bool ArduinoInstallation::writeAvrdudeScript()
{
#ifdef _WIN32
    QFile script(arduinoPath("hardware/tools/tyqt_avrdude.bat"));
    emit log(tr("Write avrdude script to '%1'").arg(nicePath(script.fileName())));

    if (!script.open(QIODevice::WriteOnly | QIODevice::Text))
        return reportFileError(script);

    QTextStream script_out(&script);
    script_out << "@echo off\n";
    script_out << QString("\"%1\" avrdude %*\n")
                  .arg(QDir::toNativeSeparators(QCoreApplication::applicationFilePath()));

    if (script.error())
        return reportFileError(script);
    if (!script.flush())
        return reportFileError(script);
#else
    QFile script(arduinoPath("hardware/tools/tyqt_avrdude.sh"));
    emit log(tr("Write avrdude script to '%1'").arg(nicePath(script.fileName())));

    if (!script.open(QIODevice::WriteOnly | QIODevice::Text))
        return reportFileError(script);

    QTextStream script_out(&script);
    script_out << "#!/bin/sh\n";
    script_out << QString("\"%1\" avrdude \"$@\"\n").arg(QCoreApplication::applicationFilePath());

    if (script.error())
        return reportFileError(script);
    if (!script.flush())
        return reportFileError(script);
    script.close();

    if (!script.setPermissions(QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner |
                               QFile::ReadGroup | QFile::ExeGroup | QFile::ReadOther | QFile::ExeOther))
        return reportFileError(script);
#endif

    return true;
}

void ArduinoInstallation::updateState()
{
    valid_ = false;
    integrated_ = false;

    arduino_version_ = "";
    arduino_legacy_ = false;
    teensyduino_version_ = "";

    if (dir_.path().isEmpty() || !dir_.exists())
        return;

    arduino_version_ = readVersion(arduinoPath("lib/version.txt"));
    if (arduino_version_.isEmpty())
        return;
    arduino_legacy_ = arduino_version_.startsWith("1.0.");
    teensyduino_version_ = readVersion(arduinoPath("lib/teensyduino.txt"));
    if (teensyduino_version_.isEmpty())
        return;

    valid_ = true;
    if (arduino_legacy_) {
        integrated_ = findMarker(arduinoPath("hardware/teensy/boards.txt"), "TyQt");
    } else {
        integrated_ = findMarker(arduinoPath("hardware/teensy/avr/platform.txt"), "TyQt");
    }
}

bool ArduinoInstallation::safeCopy(const QString &filename, const QString &new_filename)
{
    QFile src(filename);
    QSaveFile dest(new_filename);

    if (!src.open(QIODevice::ReadOnly))
        return reportFileError(src);
    if (!dest.open(QIODevice::WriteOnly))
        return reportFileError(dest);

    /* Qt provides no way to do an atomic rename outside of QSaveFile, and no way to
       to copy a QFile to a QSaveFile.  */
    char buf[8192];
    int64_t len;
    while ((len = src.read(buf, sizeof(buf))) > 0) {
        if (dest.write(buf, len) < len)
            return reportFileError(dest);
    }

    if (src.error())
        return reportFileError(src);

    if (!dest.commit())
        return reportFileError(dest);

    return true;
}

QString ArduinoInstallation::readVersion(const QString &filename)
{
    QFile file(filename);

    if (!file.exists())
        return "";
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
        return "";

    return QTextStream(&file).readLine(32);
}

bool ArduinoInstallation::findMarker(const QString &filename, const QString &marker)
{
    QFile file(filename);

    if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
        return false;

    QTextStream in(&file);
    while (!in.atEnd()) {
        if (in.readLine().contains(marker, Qt::CaseInsensitive))
            return true;
    }

    return false;
}

QString ArduinoInstallation::arduinoPath(const QString &path) const
{
#ifdef __APPLE__
    return dir_.filePath("Contents/Java/" + path);
#else
    return dir_.filePath(path);
#endif
}

QString ArduinoInstallation::nicePath(const QString &path) const
{
    return QDir::toNativeSeparators(dir_.relativeFilePath(path));
}

bool ArduinoInstallation::reportFileError(const QFileDevice &dev)
{
    emit error(QString("%1").arg(dev.errorString()));
    return false;
}
<commit_msg>Respect Arduino upload verbosity setting<commit_after>/*
 * ty, a collection of GUI and command-line tools to manage Teensy devices
 *
 * Distributed under the MIT license (see LICENSE.txt or http://opensource.org/licenses/MIT)
 * Copyright (c) 2015 Niels Martignène <niels.martignene@gmail.com>
 */

#ifdef _WIN32
    #include <windows.h>
#endif
#include <QCoreApplication>
#include <QFile>
#include <QSaveFile>
#include <QTextStream>

#include "arduino_install.hh"
#include "tyqt.hh"

using namespace std;

ArduinoInstallation::ArduinoInstallation(const QString &path)
{
    setPath(path);
}

void ArduinoInstallation::setPath(const QString &path)
{
    dir_.setPath(path);
    update();
}

void ArduinoInstallation::update()
{
    updateState();
    emit changed();
}

bool ArduinoInstallation::integrate()
{
    if (arduino_legacy_)
        return integrateLegacy();

    emit log(tr("Integrate TyQt to '%1'").arg(QDir::toNativeSeparators(dir_.path())));

    auto filename = arduinoPath("hardware/teensy/avr/platform.txt");
    emit log(tr("Rewrite '%1' (to temporary file)").arg(nicePath(filename)));

    QFile src(filename);
    QSaveFile dest(filename);

    if (!src.open(QIODevice::ReadOnly | QIODevice::Text))
        return reportFileError(src);
    if (!dest.open(QIODevice::WriteOnly | QIODevice::Text))
        return reportFileError(dest);

    QTextStream in(&src), out(&dest);
    bool integrated = false;
    for (unsigned int i = 1; !in.atEnd(); i++) {
        auto line = in.readLine();

        if (line.contains("TyQt", Qt::CaseInsensitive)) {
            emit error(tr("This installation is already patched"));
            return false;
        }

        if (line.startsWith("tools.teensyloader") || line.contains("teensy_post_compile")) {
            emit log(tr(" + Comment out line %1 '%2...'").arg(i).arg(line.left(22)));
            out << "#";
        }
        out << line << "\n";

        if (line.startsWith("tools.teensyloader.upload.pattern") && !integrated) {
            emit log(tr(" + Integrate TyQt instructions after line %1").arg(i));
            out << QString("\n## TyQt\n"
                           "tools.teensyloader.cmd.path=%1\n").arg(QDir::toNativeSeparators(tyQt->clientFilePath()));
            out << "tools.teensyloader.upload.params.quiet=--quiet\n"
                   "tools.teensyloader.upload.params.verbose=\n"
                   "tools.teensyloader.upload.pattern=\"{cmd.path}\" upload --autostart --wait"
                   " {upload.verbose} \"{build.path}/{build.project_name}.hex\"\n";
            integrated = true;
        }
    }
    if (!integrated) {
        emit error(tr("Failed to add TyQt instructions"));
        return false;
    }

    if (src.error())
        return reportFileError(src);
    src.close();

    if (dest.error())
        return reportFileError(dest);
    if (!dest.flush())
        return reportFileError(dest);

    emit log(tr("Backup '%1' to '%2'").arg(nicePath(filename), nicePath(filename + ".notyqt")));
    if (!safeCopy(filename, filename + ".notyqt"))
        return false;

    emit log(tr("Commit changes to '%1'").arg(nicePath(filename)));
    if (!dest.commit())
        return reportFileError(dest);

    update();
    return true;
}

bool ArduinoInstallation::restore()
{
    emit log(tr("Remove TyQt integration from '%1'").arg(QDir::toNativeSeparators(dir_.path())));

    QString filename;
    if (arduino_legacy_) {
        filename = arduinoPath("hardware/teensy/boards.txt");
    } else {
        filename = arduinoPath("hardware/teensy/avr/platform.txt");
    }
    if (!findMarker(filename, "TyQt")) {
        emit error(tr("This installation is not using TyQt"));
        return false;
    }

    emit log(tr("Copy '%1' to '%2'").arg(nicePath(filename + ".notyqt"), nicePath(filename)));
    if (!safeCopy(filename + ".notyqt", filename))
        return false;

    if (arduino_legacy_) {
#ifdef _WIN32
        emit log(tr("Remove avrdude script '%1'").arg("hardware/tools/tyqt_avrdude.bat"));
        QFile::remove(arduinoPath("hardware/tools/tyqt_avrdude.bat"));
#else
        emit log(tr("Remove avrdude script '%1'").arg("hardware/tools/tyqt_avrdude.sh"));
        QFile::remove(arduinoPath("hardware/tools/tyqt_avrdude.sh"));
#endif
    }

    update();
    return true;
}

bool ArduinoInstallation::integrateLegacy()
{
    emit log(tr("Integrate TyQt to '%1' (legacy)").arg(QDir::toNativeSeparators(dir_.path())));

    auto filename = arduinoPath("hardware/teensy/boards.txt");
    emit log(tr("Rewrite '%1' (to temporary file)").arg(nicePath(filename)));

    QFile src(filename);
    QSaveFile dest(filename);

    if (!src.open(QIODevice::ReadOnly | QIODevice::Text))
        return reportFileError(src);
    if (!dest.open(QIODevice::WriteOnly | QIODevice::Text))
        return reportFileError(dest);

    QTextStream in(&src), out(&dest);
    QStringList models;
    for (unsigned int i = 1; !in.atEnd(); i++) {
        auto line = in.readLine();

        if (line.contains("TyQt", Qt::CaseInsensitive)) {
            emit error(tr("This installation is already patched"));
            return false;
        }

        if (line.startsWith("teensy") && line.contains("upload.avrdude_wrapper")) {
            models.append(line.section('.', 0, 0));

            emit log(tr(" + Comment out line %1 '%2...'").arg(i).arg(line.left(22)));
            out << "#";
        } else if (line.contains("teensy_post_compile")) {
            emit log(tr(" + Comment out line %1 '%2...'").arg(i).arg(line.left(22)));
            out << "#";
        }
        out << line << "\n";
    }
    if (models.isEmpty()) {
        emit error(tr("Failed to add TyQt instructions"));
        return false;
    }

    out << "\n## TyQt (legacy Arduino)\n";
    for (auto &model: models) {
        emit log(tr(" + Add TyQt instructions for '%1'").arg(model));
#ifdef _WIN32
        out << QString("%1.upload.avrdude_wrapper=tyqt_avrdude.bat\n").arg(model);
#else
        out << QString("%1.upload.avrdude_wrapper=tyqt_avrdude.sh\n").arg(model);
#endif
    }

    if (src.error())
        return reportFileError(src);
    src.close();

    if (dest.error())
        return reportFileError(dest);
    if (!dest.flush())
        return reportFileError(dest);

    if (!writeAvrdudeScript())
        return false;

    emit log(tr("Backup '%1' to '%2'").arg(nicePath(filename), nicePath(filename + ".notyqt")));
    if (!safeCopy(filename, filename + ".notyqt"))
        return false;

    emit log(tr("Commit changes to '%1'").arg(nicePath(filename)));
    if (!dest.commit())
        return reportFileError(dest);

    update();
    return true;
}

bool ArduinoInstallation::writeAvrdudeScript()
{
#ifdef _WIN32
    QFile script(arduinoPath("hardware/tools/tyqt_avrdude.bat"));
    emit log(tr("Write avrdude script to '%1'").arg(nicePath(script.fileName())));

    if (!script.open(QIODevice::WriteOnly | QIODevice::Text))
        return reportFileError(script);

    QTextStream script_out(&script);
    script_out << "@echo off\n";
    script_out << QString("\"%1\" avrdude %*\n")
                  .arg(QDir::toNativeSeparators(QCoreApplication::applicationFilePath()));

    if (script.error())
        return reportFileError(script);
    if (!script.flush())
        return reportFileError(script);
#else
    QFile script(arduinoPath("hardware/tools/tyqt_avrdude.sh"));
    emit log(tr("Write avrdude script to '%1'").arg(nicePath(script.fileName())));

    if (!script.open(QIODevice::WriteOnly | QIODevice::Text))
        return reportFileError(script);

    QTextStream script_out(&script);
    script_out << "#!/bin/sh\n";
    script_out << QString("\"%1\" avrdude \"$@\"\n").arg(QCoreApplication::applicationFilePath());

    if (script.error())
        return reportFileError(script);
    if (!script.flush())
        return reportFileError(script);
    script.close();

    if (!script.setPermissions(QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner |
                               QFile::ReadGroup | QFile::ExeGroup | QFile::ReadOther | QFile::ExeOther))
        return reportFileError(script);
#endif

    return true;
}

void ArduinoInstallation::updateState()
{
    valid_ = false;
    integrated_ = false;

    arduino_version_ = "";
    arduino_legacy_ = false;
    teensyduino_version_ = "";

    if (dir_.path().isEmpty() || !dir_.exists())
        return;

    arduino_version_ = readVersion(arduinoPath("lib/version.txt"));
    if (arduino_version_.isEmpty())
        return;
    arduino_legacy_ = arduino_version_.startsWith("1.0.");
    teensyduino_version_ = readVersion(arduinoPath("lib/teensyduino.txt"));
    if (teensyduino_version_.isEmpty())
        return;

    valid_ = true;
    if (arduino_legacy_) {
        integrated_ = findMarker(arduinoPath("hardware/teensy/boards.txt"), "TyQt");
    } else {
        integrated_ = findMarker(arduinoPath("hardware/teensy/avr/platform.txt"), "TyQt");
    }
}

bool ArduinoInstallation::safeCopy(const QString &filename, const QString &new_filename)
{
    QFile src(filename);
    QSaveFile dest(new_filename);

    if (!src.open(QIODevice::ReadOnly))
        return reportFileError(src);
    if (!dest.open(QIODevice::WriteOnly))
        return reportFileError(dest);

    /* Qt provides no way to do an atomic rename outside of QSaveFile, and no way to
       to copy a QFile to a QSaveFile.  */
    char buf[8192];
    int64_t len;
    while ((len = src.read(buf, sizeof(buf))) > 0) {
        if (dest.write(buf, len) < len)
            return reportFileError(dest);
    }

    if (src.error())
        return reportFileError(src);

    if (!dest.commit())
        return reportFileError(dest);

    return true;
}

QString ArduinoInstallation::readVersion(const QString &filename)
{
    QFile file(filename);

    if (!file.exists())
        return "";
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
        return "";

    return QTextStream(&file).readLine(32);
}

bool ArduinoInstallation::findMarker(const QString &filename, const QString &marker)
{
    QFile file(filename);

    if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
        return false;

    QTextStream in(&file);
    while (!in.atEnd()) {
        if (in.readLine().contains(marker, Qt::CaseInsensitive))
            return true;
    }

    return false;
}

QString ArduinoInstallation::arduinoPath(const QString &path) const
{
#ifdef __APPLE__
    return dir_.filePath("Contents/Java/" + path);
#else
    return dir_.filePath(path);
#endif
}

QString ArduinoInstallation::nicePath(const QString &path) const
{
    return QDir::toNativeSeparators(dir_.relativeFilePath(path));
}

bool ArduinoInstallation::reportFileError(const QFileDevice &dev)
{
    emit error(QString("%1").arg(dev.errorString()));
    return false;
}
<|endoftext|>


<commit_before>#ifndef UTENSOR_TENSOR_H
#define UTENSOR_TENSOR_H

#include "uTensor/util/uTensor_util.hpp"
#include <initializer_list>
#include <iostream>
#include <memory>
#include <vector>
#include <algorithm>
#include <stdlib.h>
#include <limits>

// enum class DType : char {
//   uint8,
//   int8,
//   uint16,
//   int32,
//   flt,
//   dbl,
// };

class Tensor;
class TensorIdxImporter;
typedef std::string TName;
typedef std::string OpName;
typedef std::vector<TName> TNameList;
typedef std::shared_ptr<Tensor> S_TENSOR;
typedef std::vector<S_TENSOR> S_TList;

class TensorShape: public std::vector<uint32_t> {
    public:
        using std::vector<uint32_t>::vector;

};

class uTensor {
public:
 virtual void inFocus(){};
 virtual void deFocus(){};
 virtual const std::string& getName() const;
 virtual void setName(std::string _name);

 virtual ~uTensor() = 0;
private:
 std::string name;

};

//inline uTensor::~uTensor() {}
class TensorBase {
 public:
  TensorShape shape;
  void* data;
  uint32_t total_size;
  uint32_t cache_size;

  void initialize(const TensorShape& vec);
  void allocate(uint8_t unit_size);

  ~TensorBase();
};

class Tensor : public uTensor {
  virtual void* read(size_t offset, size_t ele);
  virtual void* write(size_t offset, size_t ele);
  Tensor(const Tensor&);
  Tensor& operator=(const Tensor&);

 protected:
  std::shared_ptr<TensorBase> s;  // short for states
 public:
  Tensor();

  // returns how far a given dimension is apart
  size_t getStride(size_t dim_index);

  virtual void init(const TensorShape& v);

  virtual void init(const TensorShape& v, const void* data);

  virtual void resize(const TensorShape& v);

  const TensorShape& getShape(void) const;

  uint32_t getSize(void);

  virtual uint16_t unit_size(void);

  uint32_t getSize_in_bytes(void);

  // returns the number of dimensions in the tensor
  size_t getDim(void);

  template <class T>
  const T* read(size_t offset, size_t ele) {
    return (const T*)read(offset, ele);
  }

  template <class T>
  T* write(size_t offset, size_t ele) {
    return (T*)write(offset, ele);
  }

  ~Tensor();
};

template<class T>
class BinaryTensor : public Tensor {
  public:
  BinaryTensor(const TensorShape& v, const T* g) : Tensor() {
    Tensor::init(v, g);
  }

  virtual uint16_t unit_size(void) override {
    return sizeof(T);
  }

  virtual void* read(size_t offset, size_t ele) override {
    if (ele > s->total_size) {
        ERR_EXIT("data overflow");
    }
    return (void *)((T*)s->data + offset);
  }

  virtual void* write(size_t offset, size_t ele) override {
    return nullptr;
  }
  ~BinaryTensor() {
    s->data = nullptr;
  }

 private:
  BinaryTensor(const BinaryTensor&);
  BinaryTensor& operator=(const BinaryTensor&);
};

template <class T>
class RamTensor : public Tensor {
  // need deep copy
 public:
  //RamTensor(TName _name) : Tensor(_name) {}
  RamTensor() {};

  RamTensor(std::initializer_list<uint32_t> l) {
    TensorShape v;
    for (auto i : l) {
      v.push_back(i);
    }

    Tensor::init(v);
  }

  RamTensor(const TensorShape& v) : Tensor() {
    Tensor::init(v);
  }

  // PRE:      l, initization list, specifying the element/dimension
  // POST:     When a degenerative index is supplied, the pointer
  //          lowest specified dimension is returned.
  //          Otherwise, return the pointer to the specific element.
  virtual void* read(size_t offset, size_t ele) override {
    if (ele > s->total_size) {
        ERR_EXIT("data overflow");
    }
    return (void *)((T*)s->data + offset);
  }
  virtual void* write(size_t offset, size_t ele) override {
    if (ele > s->total_size) {
        ERR_EXIT("data overflow");
    }
    return (void*)((T*)s->data + offset);
  }

  // virtual void* read(size_t offset, size_t ele) override{};
  virtual uint16_t unit_size(void) override {
    return sizeof(T);
  }
  ~RamTensor() {}
 private:
  RamTensor(const RamTensor&);
  RamTensor& operator=(const RamTensor&);

};

template <typename Tin, typename Tout>
Tensor* TensorCast(Tensor* input) {
  Tensor* output = new RamTensor<Tout>(input->getShape());
  const Tin* inputPrt = input->read<Tin>(0, 0);
  Tout* outputPrt = output->write<Tout>(0, 0);

  for (uint32_t i = 0; i < input->getSize(); i++) {
    outputPrt[i] = static_cast<Tout>(inputPrt[i]);
  }

  return output;
}

template <typename T>
Tensor* TensorConstant(const TensorShape& shape, T c) {
  Tensor* output = new RamTensor<T>(shape);
  T* outPrt = output->write<T>(0, 0);

  for (uint32_t i = 0; i < output->getSize(); i++) {
    outPrt[i] = c;
  }

  return output;
}

template <typename T>
Tensor* TensorConstant(std::initializer_list<uint32_t> l, T c) {
  TensorShape v;
  for (auto i : l) {
    v.push_back(i);
  }

  return TensorConstant<T>(v, c);
}

//
// permuteIndexTransform trans(inputTensor.getShape(), permute);
//
// Tensor<int> outputTensor(trans.getNewShape());  //of shape {100,40,10,10}
// size_t output_buffer_index = trans[input_buffer_index];

class permuteIndexTransform {
 private:
  std::vector<uint8_t> permute;
  std::vector<uint8_t> depermute;
  TensorShape in_shape;
  TensorShape in_stride;
  TensorShape out_shape;
  TensorShape out_stride;

  void computeOutputShape(void);

  size_t evalStride(size_t dim_index, const TensorShape& s);

  void computeInputStride(void);
  void computeOutputStride(void);

 public:
  permuteIndexTransform(const TensorShape& input_shape, const std::vector<uint8_t>& permute);

  const std::vector<uint8_t>& getPermute(void) const;
  void setPermute(const std::vector<uint8_t>& _permute);

  void setInputShape(const TensorShape& s);
  TensorShape getNewShape(void);

  void apply(void);

  size_t operator[](const size_t index);
};

template <typename T>
void printDim(Tensor* t) {
  printf("Dimension: ");
  TensorShape s = t->getShape();
  for (auto d : s) {
    printf("[%lu] ", d);
  }
  printf("\r\n");
}

template <typename T>
void tensorChkAlloc(Tensor** t, const TensorShape& dim) {
  if (*t && (*t)->getSize() == 0) {
    (*t)->init(dim);
  } else if (*t && (*t)->getShape() != dim) {
    ERR_EXIT("Dim mismatched...\r\n");
  } else if (*t == nullptr){
      *t = new RamTensor<T>(dim);
  }

}

//
// permuteIndexTransform trans(inputTensor.getShape(), permute);
//
// Tensor<int> outputTensor(trans.getNewShape());  //of shape {100,40,10,10}
// size_t output_buffer_index = trans[input_buffer_index];

class broadcastIndexTransform {
 private:
  TensorShape l_shape;
  TensorShape l_stride;
  TensorShape s_shape;
  TensorShape s_stride;
  bool swap_flag;

  size_t evalStride(size_t dim_index, const TensorShape& s);

  void computeSStride(void);
  void computeLStride(void);

  void sortShape(const TensorShape& a, const TensorShape& b);

  void checkShape(void);

//b_shape being a smaller shape
 public:
  broadcastIndexTransform(const TensorShape& _l_shape, const TensorShape& _s_shape);

  void apply(void);

  const TensorShape& getOutputShape(void) const;

  bool is_swaped(void);

  size_t operator[](const size_t linear_index);
};

#endif
<commit_msg>initial WrappedRamTensor : RamTensor implementation<commit_after>#ifndef UTENSOR_TENSOR_H
#define UTENSOR_TENSOR_H

#include "uTensor/util/uTensor_util.hpp"
#include <initializer_list>
#include <iostream>
#include <memory>
#include <vector>
#include <algorithm>
#include <stdlib.h>
#include <limits>

// enum class DType : char {
//   uint8,
//   int8,
//   uint16,
//   int32,
//   flt,
//   dbl,
// };

class Tensor;
class TensorIdxImporter;
typedef std::string TName;
typedef std::string OpName;
typedef std::vector<TName> TNameList;
typedef std::shared_ptr<Tensor> S_TENSOR;
typedef std::vector<S_TENSOR> S_TList;

class TensorShape: public std::vector<uint32_t> {
    public:
        using std::vector<uint32_t>::vector;

};

class uTensor {
public:
 virtual void inFocus(){};
 virtual void deFocus(){};
 virtual const std::string& getName() const;
 virtual void setName(std::string _name);

 virtual ~uTensor() = 0;
private:
 std::string name;

};

//inline uTensor::~uTensor() {}
class TensorBase {
 public:
  TensorShape shape;
  void* data;
  uint32_t total_size;
  uint32_t cache_size;

  void initialize(const TensorShape& vec);
  void allocate(uint8_t unit_size);

  ~TensorBase();
};

class Tensor : public uTensor {
  virtual void* read(size_t offset, size_t ele);
  virtual void* write(size_t offset, size_t ele);
  Tensor(const Tensor&);
  Tensor& operator=(const Tensor&);

 protected:
  std::shared_ptr<TensorBase> s;  // short for states
 public:
  Tensor();

  // returns how far a given dimension is apart
  size_t getStride(size_t dim_index);

  virtual void init(const TensorShape& v);

  virtual void init(const TensorShape& v, const void* data);

  virtual void resize(const TensorShape& v);

  const TensorShape& getShape(void) const;

  uint32_t getSize(void);

  virtual uint16_t unit_size(void);

  uint32_t getSize_in_bytes(void);

  // returns the number of dimensions in the tensor
  size_t getDim(void);

  template <class T>
  const T* read(size_t offset, size_t ele) {
    return (const T*)read(offset, ele);
  }

  template <class T>
  T* write(size_t offset, size_t ele) {
    return (T*)write(offset, ele);
  }

  ~Tensor();
};

template<class T>
class BinaryTensor : public Tensor {
  public:
  BinaryTensor(const TensorShape& v, const T* g) : Tensor() {
    Tensor::init(v, g);
  }

  virtual uint16_t unit_size(void) override {
    return sizeof(T);
  }

  virtual void* read(size_t offset, size_t ele) override {
    if (ele > s->total_size) {
        ERR_EXIT("data overflow");
    }
    return (void *)((T*)s->data + offset);
  }

  virtual void* write(size_t offset, size_t ele) override {
    return nullptr;
  }
  ~BinaryTensor() {
    s->data = nullptr;
  }

 private:
  BinaryTensor(const BinaryTensor&);
  BinaryTensor& operator=(const BinaryTensor&);
};

template <class T>
class RamTensor : public Tensor {
  // need deep copy
 protected:
    using Tensor::s;
 public:
  //RamTensor(TName _name) : Tensor(_name) {}
  RamTensor() {};

  RamTensor(std::initializer_list<uint32_t> l) {
    TensorShape v;
    for (auto i : l) {
      v.push_back(i);
    }

    Tensor::init(v);
  }

  RamTensor(const TensorShape& v) : Tensor() {
    Tensor::init(v);
  }

  // PRE:      l, initization list, specifying the element/dimension
  // POST:     When a degenerative index is supplied, the pointer
  //          lowest specified dimension is returned.
  //          Otherwise, return the pointer to the specific element.
  virtual void* read(size_t offset, size_t ele) override {
    if (ele > s->total_size) {
        ERR_EXIT("data overflow");
    }
    return (void *)((T*)s->data + offset);
  }
  virtual void* write(size_t offset, size_t ele) override {
    if (ele > s->total_size) {
        ERR_EXIT("data overflow");
    }
    return (void*)((T*)s->data + offset);
  }

  // virtual void* read(size_t offset, size_t ele) override{};
  virtual uint16_t unit_size(void) override {
    return sizeof(T);
  }
  ~RamTensor() {}
 private:
  RamTensor(const RamTensor&);
  RamTensor& operator=(const RamTensor&);

};

// application owns the pointer
// the printer may be modified outside of the application
template <class T>
class WrappedRamTensor : public RamTensor<T> {

 protected:
  using RamTensor<T>::s;

 public:
  WrappedRamTensor() {};

  WrappedRamTensor(std::initializer_list<uint32_t> l, T* ptr) {
    std::vector<uint32_t> v;
    for (auto i : l) {
      v.push_back(i);
    }

    Tensor::init(v, ptr);
  }

  void setPointer(void* ptr) {
    s->data = ptr;
  }

  T* getPointer(void) {
    return (T*) s->data;
  }

  ~WrappedRamTensor() {
    s->data = nullptr;
  }

 private:
  WrappedRamTensor(const WrappedRamTensor&);
  WrappedRamTensor& operator=(const WrappedRamTensor&);

};

template <typename Tin, typename Tout>
Tensor* TensorCast(Tensor* input) {
  Tensor* output = new RamTensor<Tout>(input->getShape());
  const Tin* inputPrt = input->read<Tin>(0, 0);
  Tout* outputPrt = output->write<Tout>(0, 0);

  for (uint32_t i = 0; i < input->getSize(); i++) {
    outputPrt[i] = static_cast<Tout>(inputPrt[i]);
  }

  return output;
}

template <typename T>
Tensor* TensorConstant(const TensorShape& shape, T c) {
  Tensor* output = new RamTensor<T>(shape);
  T* outPrt = output->write<T>(0, 0);

  for (uint32_t i = 0; i < output->getSize(); i++) {
    outPrt[i] = c;
  }

  return output;
}

template <typename T>
Tensor* TensorConstant(std::initializer_list<uint32_t> l, T c) {
  TensorShape v;
  for (auto i : l) {
    v.push_back(i);
  }

  return TensorConstant<T>(v, c);
}

//
// permuteIndexTransform trans(inputTensor.getShape(), permute);
//
// Tensor<int> outputTensor(trans.getNewShape());  //of shape {100,40,10,10}
// size_t output_buffer_index = trans[input_buffer_index];

class permuteIndexTransform {
 private:
  std::vector<uint8_t> permute;
  std::vector<uint8_t> depermute;
  TensorShape in_shape;
  TensorShape in_stride;
  TensorShape out_shape;
  TensorShape out_stride;

  void computeOutputShape(void);

  size_t evalStride(size_t dim_index, const TensorShape& s);

  void computeInputStride(void);
  void computeOutputStride(void);

 public:
  permuteIndexTransform(const TensorShape& input_shape, const std::vector<uint8_t>& permute);

  const std::vector<uint8_t>& getPermute(void) const;
  void setPermute(const std::vector<uint8_t>& _permute);

  void setInputShape(const TensorShape& s);
  TensorShape getNewShape(void);

  void apply(void);

  size_t operator[](const size_t index);
};

template <typename T>
void printDim(Tensor* t) {
  printf("Dimension: ");
  TensorShape s = t->getShape();
  for (auto d : s) {
    printf("[%lu] ", d);
  }
  printf("\r\n");
}

template <typename T>
void tensorChkAlloc(Tensor** t, const TensorShape& dim) {
  if (*t && (*t)->getSize() == 0) {
    (*t)->init(dim);
  } else if (*t && (*t)->getShape() != dim) {
    ERR_EXIT("Dim mismatched...\r\n");
  } else if (*t == nullptr){
      *t = new RamTensor<T>(dim);
  }

}

//
// permuteIndexTransform trans(inputTensor.getShape(), permute);
//
// Tensor<int> outputTensor(trans.getNewShape());  //of shape {100,40,10,10}
// size_t output_buffer_index = trans[input_buffer_index];

class broadcastIndexTransform {
 private:
  TensorShape l_shape;
  TensorShape l_stride;
  TensorShape s_shape;
  TensorShape s_stride;
  bool swap_flag;

  size_t evalStride(size_t dim_index, const TensorShape& s);

  void computeSStride(void);
  void computeLStride(void);

  void sortShape(const TensorShape& a, const TensorShape& b);

  void checkShape(void);

//b_shape being a smaller shape
 public:
  broadcastIndexTransform(const TensorShape& _l_shape, const TensorShape& _s_shape);

  void apply(void);

  const TensorShape& getOutputShape(void) const;

  bool is_swaped(void);

  size_t operator[](const size_t linear_index);
};

#endif
<|endoftext|>


<commit_before>/*=============================================================================

  Library: CppMicroServices

  Copyright (c) The CppMicroServices developers. See the COPYRIGHT
  file at the top-level directory of this distribution and at
  https://github.com/CppMicroServices/CppMicroServices/COPYRIGHT .

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

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

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

=============================================================================*/

#include "BundleObjFile.h"

#include "cppmicroservices_mach-o.h"

#include <cerrno>
#include <cstring>
#include <fstream>

#include <sys/stat.h>

namespace cppmicroservices {

struct InvalidMachOException : public InvalidObjFileException
{
  InvalidMachOException(const std::string& what, int errorNumber = 0)
    : InvalidObjFileException(what, errorNumber)
  {}
};

template<uint32_t> struct MachO;

template<> struct MachO<MH_MAGIC>
{
  typedef mach_header Mhdr;
  typedef nlist symtab_entry;
};

template<> struct MachO<MH_MAGIC_64>
{
  typedef mach_header_64 Mhdr;
  typedef nlist_64 symtab_entry;
};

template<typename I> I readBE(I i)
{
#ifdef US_LITTLE_ENDIAN
  I r = 0;
  for (unsigned int n = 0; n < sizeof(I); ++n)
  {
    r |= static_cast<I>(*(reinterpret_cast<unsigned char*>(&i) + n)) << ((sizeof(I) - 1 - n) * 8);
  }
  return r;
#else
  return i;
#endif
}

template<class MachOType>
class BundleMachOFile : public BundleObjFile, private MachOType
{
public:

  typedef typename MachOType::Mhdr Mhdr;
  typedef typename MachOType::symtab_entry symtab_entry;

  BundleMachOFile(std::ifstream& fs, std::size_t fileOffset)
  {
    fs.seekg(fileOffset);
    Mhdr mhdr;
    fs.read(reinterpret_cast<char*>(&mhdr), sizeof mhdr);
    if (mhdr.filetype != MH_DYLIB && mhdr.filetype != MH_BUNDLE)
    {
      throw InvalidMachOException("Not a Mach-O dynamic shared library or bundle file.");
    }

    // iterate over all load commands
    uint32_t ncmds = mhdr.ncmds;
    uint32_t lcmd_offset = static_cast<uint32_t>(fs.tellg());
    uint32_t symtab_offset = 0;
    uint32_t strtab_offset = 0;
    uint32_t strtab_size = 0;
    for (uint32_t i = 0; i < ncmds; ++i)
    {
      load_command lcmd;
      fs.read(reinterpret_cast<char*>(&lcmd), sizeof lcmd);
      if (lcmd.cmd == LC_ID_DYLIB)
      {
        dylib dylib_id;
        fs.read(reinterpret_cast<char*>(&dylib_id), sizeof dylib_id);
        PrintVersionString(dylib_id.current_version);
        PrintVersionString(dylib_id.compatibility_version);
        fs.seekg(lcmd_offset + dylib_id.name.offset);
        std::getline(fs, m_InstallName, '\0');
      }
      else if (lcmd.cmd == LC_LOAD_DYLIB)
      {
        dylib dylib_id;
        fs.read(reinterpret_cast<char*>(&dylib_id), sizeof dylib_id);
        fs.seekg(lcmd_offset + dylib_id.name.offset);
        std::string id;
        std::getline(fs, id, '\0');
        m_Needed.push_back(id);
      }
      else if (lcmd.cmd == LC_SYMTAB)
      {
        fs.seekg(-2 * static_cast<int>(sizeof(uint32_t)), std::ios_base::cur);
        symtab_command symtab;
        fs.read(reinterpret_cast<char*>(&symtab), sizeof symtab);
        symtab_offset = symtab.symoff;
        strtab_offset = symtab.stroff;
        strtab_size = symtab.strsize;
      }
      else if (lcmd.cmd == LC_DYSYMTAB)
      {
        fs.seekg(-2 * static_cast<int>(sizeof(uint32_t)), std::ios_base::cur);
        dysymtab_command dysymtab;
        fs.read(reinterpret_cast<char*>(&dysymtab), sizeof dysymtab);
        if (dysymtab.nextdefsym != 0)
        {
          // read the defined external symbol table entries
          symtab_entry* extSyms = new symtab_entry[dysymtab.nextdefsym];
          fs.seekg(fileOffset + symtab_offset + dysymtab.iextdefsym * sizeof(symtab_entry));
          fs.read(reinterpret_cast<char*>(extSyms), dysymtab.nextdefsym * sizeof(symtab_entry));

          // read the string table
          char* strtab = new char[strtab_size];
          fs.seekg(fileOffset + strtab_offset);
          fs.read(strtab, strtab_size);

          // iterate over all defined external symbol table entries
          symtab_entry* extSym = extSyms;
          for (std::size_t i = 0; i < dysymtab.nextdefsym; ++i, ++extSym)
          {
            if (static_cast<uint32_t>(extSym->n_un.n_strx) >= strtab_size) continue;
            // strip of the leading "_" in the symbol name
            if (this->ExtractBundleName(&strtab[extSym->n_un.n_strx + 1], m_BundleName))
            {
              break;
            }
          }
          delete[] strtab;
          delete[] extSyms;
        }
      }

      lcmd_offset += lcmd.cmdsize;
      fs.seekg(lcmd_offset);
    }
  }

  virtual std::vector<std::string> GetDependencies() const
  {
    return m_Needed;
  }

  virtual std::string GetLibName() const
  {
    return m_InstallName;
  }

  virtual std::string GetBundleName() const
  {
    return m_BundleName;
  }

private:

  std::vector<std::string> m_Needed;
  std::string m_InstallName;
  std::string m_BundleName;

  void PrintVersionString(uint32_t /*version*/)
  {
    /*
    uint32_t pv = version & 0xff;
    uint32_t minor = (version & 0xff00) >> 8;
    uint32_t major = (version & 0xff0000) >> 16;
    std::cout << major << "." << minor << "." << pv << std::endl;
    */
  }
};

static std::vector<std::vector<uint32_t> > GetMachOIdents(std::ifstream& is)
{
  // magic (32 or 64 bit) | cputype | offset
  std::vector<std::vector<uint32_t> > idents;

  uint32_t magic;
  is.seekg(0);
  is.read(reinterpret_cast<char*>(&magic), sizeof magic);

  if (readBE(magic) == FAT_MAGIC)
  {
    is.seekg(0);
    fat_header fatHdr;
    is.read(reinterpret_cast<char*>(&fatHdr), sizeof fatHdr);
    fat_arch* fatArchs = new fat_arch[readBE(fatHdr.nfat_arch)];
    is.read(reinterpret_cast<char*>(fatArchs), sizeof *fatArchs * readBE(fatHdr.nfat_arch));
    fat_arch* currArch = fatArchs;
    for (uint32_t i = 0; i < readBE(fatHdr.nfat_arch); ++i, ++currArch)
    {
      is.seekg(readBE(currArch->offset));
      mach_header machHdr;
      is.read(reinterpret_cast<char*>(&machHdr), sizeof machHdr);
      std::vector<uint32_t> ident(3, 0);
      ident[0] = machHdr.magic;
      ident[1] = readBE(currArch->cputype);
      ident[2] = readBE(currArch->offset);
      idents.push_back(ident);
    }
  }
  else
  {
    std::vector<uint32_t> ident(3, 0);
    ident[0] = magic;
    is.read(reinterpret_cast<char*>(&ident[1]), sizeof(uint32_t));
    idents.push_back(ident);
  }
  return idents;
}

// We can't get the identification bits for the currently
// running bundle (the host system) directly from the file
// because the file could itself be a fat binary with multiple
// possible target systems.
static std::vector<uint32_t> GetMachOIdent()
{
  // magic (32 or 64 bit) | cputype | offset
  std::vector<uint32_t> ident(3, 0);

#ifdef __LP64__
  ident[0] = MH_MAGIC_64;
#else
  ident[1] = MH_MAGIC;
#endif

#if defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__)
  ident[1] = CPU_TYPE_POWERPC64;
#elif defined(__powerpc__) || defined(__ppc__) || defined(__PPC__)
  ident[1] = CPU_TYPE_POWERPC;
#elif defined(__sparc)
  ident[1] = CPU_TYPE_SPARC;
#elif defined(__x86_64__) || defined(_M_X64)
  ident[1] = CPU_TYPE_X86_64;
#elif defined(__i386) || defined(_M_IX86)
  ident[1] = CPU_TYPE_X86;
#elif defined(__arm__) || defined(_M_ARM)
  ident[1] = CPU_TYPE_ARM;
#endif

  return ident;
}

BundleObjFile* CreateBundleMachOFile(const char* /*selfName*/, const std::string& fileName)
{
  struct stat machStat;
  if (stat(fileName.c_str(), &machStat) != 0)
  {
    throw InvalidMachOException("Stat for " + fileName + " failed", errno);
  }

  std::size_t fileSize = machStat.st_size;

  // magic number
  if (fileSize < sizeof(uint32_t))
  {
    throw InvalidMachOException("Missing magic number");
  }

  std::ifstream machFile(fileName.c_str(), std::ios_base::binary);
  machFile.exceptions(std::ifstream::failbit | std::ifstream::badbit) ;

  std::vector<uint32_t> selfIdent = GetMachOIdent();
  std::vector<std::vector<uint32_t> > fileIdents = GetMachOIdents(machFile);

  std::vector<uint32_t> matchingIdent(3, 0);

  // check if the identifications match for the running application
  // and the Mach-O file (or one of the embedded files in the fat binary)
  for (std::size_t i = 0; i < fileIdents.size(); ++i)
  {
    if (memcmp(&fileIdents[i][0], &selfIdent[0], 2 * sizeof(uint32_t)) == 0)
    {
      matchingIdent = fileIdents[i];
    }
  }

  if (matchingIdent[0] == 0)
  {
    throw InvalidMachOException("Not a compatible Mach-O file or fat binary");
  }

  if (matchingIdent[0] == MH_MAGIC)
  {
    //std::cout << "Mach-O (32-bit) binary" << std::endl;
    return new BundleMachOFile<MachO<MH_MAGIC> >(machFile, matchingIdent[2]);
  }
  else if (matchingIdent[0] == MH_MAGIC_64)
  {
    //std::cout << "Mach-O (64-bit) binary" << std::endl;
    return new BundleMachOFile<MachO<MH_MAGIC_64> >(machFile, matchingIdent[2]);
  }
  else
  {
    throw InvalidMachOException("Internal error: Mach-O magic is neither MH_MAGIC nor MH_MAGIC_64");
  }
}

}
<commit_msg>Fix MachO magic number identification<commit_after>/*=============================================================================

  Library: CppMicroServices

  Copyright (c) The CppMicroServices developers. See the COPYRIGHT
  file at the top-level directory of this distribution and at
  https://github.com/CppMicroServices/CppMicroServices/COPYRIGHT .

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

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

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

=============================================================================*/

#include "BundleObjFile.h"

#include "cppmicroservices_mach-o.h"

#include <cerrno>
#include <cstring>
#include <fstream>

#include <sys/stat.h>

namespace cppmicroservices {

struct InvalidMachOException : public InvalidObjFileException
{
  InvalidMachOException(const std::string& what, int errorNumber = 0)
    : InvalidObjFileException(what, errorNumber)
  {}
};

template<uint32_t> struct MachO;

template<> struct MachO<MH_MAGIC>
{
  typedef mach_header Mhdr;
  typedef nlist symtab_entry;
};

template<> struct MachO<MH_MAGIC_64>
{
  typedef mach_header_64 Mhdr;
  typedef nlist_64 symtab_entry;
};

template<typename I> I readBE(I i)
{
#ifdef US_LITTLE_ENDIAN
  I r = 0;
  for (unsigned int n = 0; n < sizeof(I); ++n)
  {
    r |= static_cast<I>(*(reinterpret_cast<unsigned char*>(&i) + n)) << ((sizeof(I) - 1 - n) * 8);
  }
  return r;
#else
  return i;
#endif
}

template<class MachOType>
class BundleMachOFile : public BundleObjFile, private MachOType
{
public:

  typedef typename MachOType::Mhdr Mhdr;
  typedef typename MachOType::symtab_entry symtab_entry;

  BundleMachOFile(std::ifstream& fs, std::size_t fileOffset)
  {
    fs.seekg(fileOffset);
    Mhdr mhdr;
    fs.read(reinterpret_cast<char*>(&mhdr), sizeof mhdr);
    if (mhdr.filetype != MH_DYLIB && mhdr.filetype != MH_BUNDLE)
    {
      throw InvalidMachOException("Not a Mach-O dynamic shared library or bundle file.");
    }

    // iterate over all load commands
    uint32_t ncmds = mhdr.ncmds;
    uint32_t lcmd_offset = static_cast<uint32_t>(fs.tellg());
    uint32_t symtab_offset = 0;
    uint32_t strtab_offset = 0;
    uint32_t strtab_size = 0;
    for (uint32_t i = 0; i < ncmds; ++i)
    {
      load_command lcmd;
      fs.read(reinterpret_cast<char*>(&lcmd), sizeof lcmd);
      if (lcmd.cmd == LC_ID_DYLIB)
      {
        dylib dylib_id;
        fs.read(reinterpret_cast<char*>(&dylib_id), sizeof dylib_id);
        PrintVersionString(dylib_id.current_version);
        PrintVersionString(dylib_id.compatibility_version);
        fs.seekg(lcmd_offset + dylib_id.name.offset);
        std::getline(fs, m_InstallName, '\0');
      }
      else if (lcmd.cmd == LC_LOAD_DYLIB)
      {
        dylib dylib_id;
        fs.read(reinterpret_cast<char*>(&dylib_id), sizeof dylib_id);
        fs.seekg(lcmd_offset + dylib_id.name.offset);
        std::string id;
        std::getline(fs, id, '\0');
        m_Needed.push_back(id);
      }
      else if (lcmd.cmd == LC_SYMTAB)
      {
        fs.seekg(-2 * static_cast<int>(sizeof(uint32_t)), std::ios_base::cur);
        symtab_command symtab;
        fs.read(reinterpret_cast<char*>(&symtab), sizeof symtab);
        symtab_offset = symtab.symoff;
        strtab_offset = symtab.stroff;
        strtab_size = symtab.strsize;
      }
      else if (lcmd.cmd == LC_DYSYMTAB)
      {
        fs.seekg(-2 * static_cast<int>(sizeof(uint32_t)), std::ios_base::cur);
        dysymtab_command dysymtab;
        fs.read(reinterpret_cast<char*>(&dysymtab), sizeof dysymtab);
        if (dysymtab.nextdefsym != 0)
        {
          // read the defined external symbol table entries
          symtab_entry* extSyms = new symtab_entry[dysymtab.nextdefsym];
          fs.seekg(fileOffset + symtab_offset + dysymtab.iextdefsym * sizeof(symtab_entry));
          fs.read(reinterpret_cast<char*>(extSyms), dysymtab.nextdefsym * sizeof(symtab_entry));

          // read the string table
          char* strtab = new char[strtab_size];
          fs.seekg(fileOffset + strtab_offset);
          fs.read(strtab, strtab_size);

          // iterate over all defined external symbol table entries
          symtab_entry* extSym = extSyms;
          for (std::size_t i = 0; i < dysymtab.nextdefsym; ++i, ++extSym)
          {
            if (static_cast<uint32_t>(extSym->n_un.n_strx) >= strtab_size) continue;
            // strip of the leading "_" in the symbol name
            if (this->ExtractBundleName(&strtab[extSym->n_un.n_strx + 1], m_BundleName))
            {
              break;
            }
          }
          delete[] strtab;
          delete[] extSyms;
        }
      }

      lcmd_offset += lcmd.cmdsize;
      fs.seekg(lcmd_offset);
    }
  }

  virtual std::vector<std::string> GetDependencies() const
  {
    return m_Needed;
  }

  virtual std::string GetLibName() const
  {
    return m_InstallName;
  }

  virtual std::string GetBundleName() const
  {
    return m_BundleName;
  }

private:

  std::vector<std::string> m_Needed;
  std::string m_InstallName;
  std::string m_BundleName;

  void PrintVersionString(uint32_t /*version*/)
  {
    /*
    uint32_t pv = version & 0xff;
    uint32_t minor = (version & 0xff00) >> 8;
    uint32_t major = (version & 0xff0000) >> 16;
    std::cout << major << "." << minor << "." << pv << std::endl;
    */
  }
};

static std::vector<std::vector<uint32_t> > GetMachOIdents(std::ifstream& is)
{
  // magic (32 or 64 bit) | cputype | offset
  std::vector<std::vector<uint32_t> > idents;

  uint32_t magic;
  is.seekg(0);
  is.read(reinterpret_cast<char*>(&magic), sizeof magic);

  if (readBE(magic) == FAT_MAGIC)
  {
    is.seekg(0);
    fat_header fatHdr;
    is.read(reinterpret_cast<char*>(&fatHdr), sizeof fatHdr);
    fat_arch* fatArchs = new fat_arch[readBE(fatHdr.nfat_arch)];
    is.read(reinterpret_cast<char*>(fatArchs), sizeof *fatArchs * readBE(fatHdr.nfat_arch));
    fat_arch* currArch = fatArchs;
    for (uint32_t i = 0; i < readBE(fatHdr.nfat_arch); ++i, ++currArch)
    {
      is.seekg(readBE(currArch->offset));
      mach_header machHdr;
      is.read(reinterpret_cast<char*>(&machHdr), sizeof machHdr);
      std::vector<uint32_t> ident(3, 0);
      ident[0] = machHdr.magic;
      ident[1] = readBE(currArch->cputype);
      ident[2] = readBE(currArch->offset);
      idents.push_back(ident);
    }
  }
  else
  {
    std::vector<uint32_t> ident(3, 0);
    ident[0] = magic;
    is.read(reinterpret_cast<char*>(&ident[1]), sizeof(uint32_t));
    idents.push_back(ident);
  }
  return idents;
}

// We can't get the identification bits for the currently
// running bundle (the host system) directly from the file
// because the file could itself be a fat binary with multiple
// possible target systems.
static std::vector<uint32_t> GetMachOIdent()
{
  // magic (32 or 64 bit) | cputype | offset
  std::vector<uint32_t> ident(3, 0);

#ifdef __LP64__
  ident[0] = MH_MAGIC_64;
#else
  ident[0] = MH_MAGIC;
#endif

#if defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__)
  ident[1] = CPU_TYPE_POWERPC64;
#elif defined(__powerpc__) || defined(__ppc__) || defined(__PPC__)
  ident[1] = CPU_TYPE_POWERPC;
#elif defined(__sparc)
  ident[1] = CPU_TYPE_SPARC;
#elif defined(__x86_64__) || defined(_M_X64)
  ident[1] = CPU_TYPE_X86_64;
#elif defined(__i386) || defined(_M_IX86)
  ident[1] = CPU_TYPE_X86;
#elif defined(__arm__) || defined(_M_ARM)
  ident[1] = CPU_TYPE_ARM;
#endif

  return ident;
}

BundleObjFile* CreateBundleMachOFile(const char* /*selfName*/, const std::string& fileName)
{
  struct stat machStat;
  if (stat(fileName.c_str(), &machStat) != 0)
  {
    throw InvalidMachOException("Stat for " + fileName + " failed", errno);
  }

  std::size_t fileSize = machStat.st_size;

  // magic number
  if (fileSize < sizeof(uint32_t))
  {
    throw InvalidMachOException("Missing magic number");
  }

  std::ifstream machFile(fileName.c_str(), std::ios_base::binary);
  machFile.exceptions(std::ifstream::failbit | std::ifstream::badbit) ;

  std::vector<uint32_t> selfIdent = GetMachOIdent();
  std::vector<std::vector<uint32_t> > fileIdents = GetMachOIdents(machFile);

  std::vector<uint32_t> matchingIdent(3, 0);

  // check if the identifications match for the running application
  // and the Mach-O file (or one of the embedded files in the fat binary)
  for (std::size_t i = 0; i < fileIdents.size(); ++i)
  {
    if (memcmp(&fileIdents[i][0], &selfIdent[0], 2 * sizeof(uint32_t)) == 0)
    {
      matchingIdent = fileIdents[i];
    }
  }

  if (matchingIdent[0] == 0)
  {
    throw InvalidMachOException("Not a compatible Mach-O file or fat binary");
  }

  if (matchingIdent[0] == MH_MAGIC)
  {
    //std::cout << "Mach-O (32-bit) binary" << std::endl;
    return new BundleMachOFile<MachO<MH_MAGIC> >(machFile, matchingIdent[2]);
  }
  else if (matchingIdent[0] == MH_MAGIC_64)
  {
    //std::cout << "Mach-O (64-bit) binary" << std::endl;
    return new BundleMachOFile<MachO<MH_MAGIC_64> >(machFile, matchingIdent[2]);
  }
  else
  {
    throw InvalidMachOException("Internal error: Mach-O magic is neither MH_MAGIC nor MH_MAGIC_64");
  }
}

}
<|endoftext|>


<commit_before>//* This file is part of the MOOSE framework
//* https://www.mooseframework.org
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html

#include "SmoothMesh.h"

// libMesh includes
#include "libmesh/mesh_smoother_laplace.h"

registerMooseObject("MooseApp", SmoothMesh);

template <>
InputParameters
validParams<SmoothMesh>()
{
  InputParameters params = validParams<MeshModifier>();

  params.addClassDescription("Utilizes a simple Laplacian based smoother to attempt to improve "
                             "mesh quality.  Will not move boundary nodes or nodes along "
                             "block/subdomain boundaries");

  params.addParam<unsigned int>("iterations", 1, "The number of smoothing iterations to do.");

  return params;
}

SmoothMesh::SmoothMesh(const InputParameters & parameters)
  : MeshModifier(parameters), _iterations(getParam<unsigned int>("iterations"))
{
}

void
SmoothMesh::modify()
{
  // Check that we have access to the mesh
  if (!_mesh_ptr)
    mooseError("_mesh_ptr must be initialized before calling SmoothMesh::modify()");

  LaplaceMeshSmoother lms(static_cast<UnstructuredMesh &>(_mesh_ptr->getMesh()));

  lms.smooth(_iterations);
}
<commit_msg>Add missing include refs #11877<commit_after>//* This file is part of the MOOSE framework
//* https://www.mooseframework.org
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html

#include "SmoothMesh.h"

// MOOSE includes
#include "MooseMesh.h"

// libMesh includes
#include "libmesh/mesh_smoother_laplace.h"
#include "libmesh/unstructured_mesh.h"

registerMooseObject("MooseApp", SmoothMesh);

template <>
InputParameters
validParams<SmoothMesh>()
{
  InputParameters params = validParams<MeshModifier>();

  params.addClassDescription("Utilizes a simple Laplacian based smoother to attempt to improve "
                             "mesh quality.  Will not move boundary nodes or nodes along "
                             "block/subdomain boundaries");

  params.addParam<unsigned int>("iterations", 1, "The number of smoothing iterations to do.");

  return params;
}

SmoothMesh::SmoothMesh(const InputParameters & parameters)
  : MeshModifier(parameters), _iterations(getParam<unsigned int>("iterations"))
{
}

void
SmoothMesh::modify()
{
  // Check that we have access to the mesh
  if (!_mesh_ptr)
    mooseError("_mesh_ptr must be initialized before calling SmoothMesh::modify()");

  LaplaceMeshSmoother lms(static_cast<UnstructuredMesh &>(_mesh_ptr->getMesh()));

  lms.smooth(_iterations);
}
<|endoftext|>