<commit_before>/*******************************************************************************
 *
 * MIT License
 *
 * Copyright (c) 2019 Advanced Micro Devices, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 *******************************************************************************/
#ifndef BFLOAT16_H_
#define BFLOAT16_H_
#include <boost/operators.hpp>
#include <iostream>
#include <miopen/config.h>

class bfloat16 : boost::totally_ordered<bfloat16, boost::arithmetic<bfloat16>>
{
    public:
    bfloat16() : data_{0} {}
    explicit bfloat16(float rhs)
    {
        static union
        {
            std::uint32_t bf16_st;
            float float_st;
        } bits_st;

        bits_st.float_st = rhs;

        // BF16 round and NaN preservation code matches
        // https://github.com/ROCmSoftwarePlatform/rocBLAS/blob/develop/library/include/rocblas_bfloat16.h
        if((~bits_st.bf16_st & 0x7f800000) == 0) // Inf or NaN
        {
            // When all of the exponent bits are 1, the value is Inf or NaN.
            // Inf is indicated by a zero mantissa. NaN is indicated by any nonzero
            // mantissa bit. Quiet NaN is indicated by the most significant mantissa
            // bit being 1. Signaling NaN is indicated by the most significant
            // mantissa bit being 0 but some other bit(s) being 1. If any of the
            // lower 16 bits of the mantissa are 1, we set the least significant bit
            // of the bfloat16 mantissa, in order to preserve signaling NaN in case
            // the bloat16's mantissa bits are all 0.
            if((bits_st.bf16_st & 0xffff) != 0)
            {
                bits_st.bf16_st |= 0x10000; // Preserve signaling NaN
            }
        }
        else
        {
#if MIOPEN_USE_RNE_BFLOAT16 == 1
            // When the exponent bits are not all 1s, then the value is zero, normal,
            // or subnormal. We round the bfloat16 mantissa up by adding 0x7FFF, plus
            // 1 if the least significant bit of the bfloat16 mantissa is 1 (odd).
            // This causes the bfloat16's mantissa to be incremented by 1 if the 16
            // least significant bits of the float mantissa are greater than 0x8000,
            // or if they are equal to 0x8000 and the least significant bit of the
            // bfloat16 mantissa is 1 (odd). This causes it to be rounded to even when
            // the lower 16 bits are exactly 0x8000. If the bfloat16 mantissa already
            // has the value 0x7f, then incrementing it causes it to become 0x00 and
            // the exponent is incremented by one, which is the next higher FP value
            // to the unrounded bfloat16 value. When the bfloat16 value is subnormal
            // with an exponent of 0x00 and a mantissa of 0x7F, it may be rounded up
            // to a normal value with an exponent of 0x01 and a mantissa of 0x00.
            // When the bfloat16 value has an exponent of 0xFE and a mantissa of 0x7F,
            // incrementing it causes it to become an exponent of 0xFF and a mantissa
            // of 0x00, which is Inf, the next higher value to the unrounded value.
            bits_st.bf16_st +=
                (0x7fff + ((bits_st.bf16_st >> 16) & 1)); // Round to nearest, round to even
#else                                                     // truncation
// do nothing
#endif
        }
        data_ = bits_st.bf16_st >> 16;
    }
    operator float() const
    {
        static union
        {
            std::uint32_t bf16_st;
            float float_st;
        } bits_st;

        bits_st.bf16_st = data_;
        bits_st.bf16_st = bits_st.bf16_st << 16;
        return bits_st.float_st;
    }

    bfloat16 operator-() const { return bfloat16(-static_cast<float>(*this)); }
    bfloat16 operator+() const { return *this; }

    bfloat16& operator=(const float rhs)
    {
        *this = bfloat16(rhs);
        return *this;
    }
    bfloat16& operator+=(bfloat16 rhs)
    {
        *this = bfloat16(static_cast<float>(*this) + static_cast<float>(rhs));
        return *this;
    }

    bfloat16& operator+=(float rhs)
    {
        *this = bfloat16(static_cast<float>(*this) + rhs);
        return *this;
    }

    bfloat16& operator-=(bfloat16 rhs)
    {
        *this += -rhs;
        return *this;
    }
    bfloat16& operator*=(bfloat16 rhs)
    {
        *this = bfloat16(static_cast<float>(*this) * static_cast<float>(rhs));
        return *this;
    }
    bfloat16& operator*=(float rhs)
    {
        *this = bfloat16(static_cast<float>(*this) * rhs);
        return *this;
    }

    bfloat16& operator/=(bfloat16 rhs)
    {
        *this = bfloat16(static_cast<float>(*this) / static_cast<float>(rhs));
        return *this;
    }
    bool operator<(bfloat16 rhs) const
    {
        return static_cast<float>(*this) < static_cast<float>(rhs);
    }
    bool operator==(bfloat16 rhs) const { return std::equal_to<float>()(*this, rhs); }

    static constexpr bfloat16 generate(uint16_t val) { return bfloat16{val, true}; }

    private:
    constexpr bfloat16(std::uint16_t val, bool) : data_{val} {}

    std::uint16_t data_;
};

namespace std {
template <>
class numeric_limits<bfloat16>
{
    public:
    static constexpr bool is_specialized = true;
    static constexpr bfloat16 min() noexcept { return bfloat16::generate(0x007F); }
    static constexpr bfloat16 max() noexcept { return bfloat16::generate(0x7F7F); }
    static constexpr bfloat16 lowest() noexcept { return bfloat16::generate(0xFF7F); }
    static constexpr bfloat16 epsilon() noexcept { return bfloat16::generate(0x3C00); }
    static constexpr bfloat16 infinity() noexcept { return bfloat16::generate(0x7F80); }
    static constexpr bfloat16 quiet_NaN() noexcept { return bfloat16::generate(0x7FC0); }
    static constexpr bfloat16 signaling_NaN() noexcept { return bfloat16::generate(0x7FC0); }
    static constexpr bfloat16 denorm_min() noexcept { return bfloat16::generate(0); }
};
} // namespace std
#endif
<commit_msg>* fix for bfloat16 class (#1908)<commit_after>/*******************************************************************************
 *
 * MIT License
 *
 * Copyright (c) 2019 Advanced Micro Devices, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 *******************************************************************************/
#ifndef BFLOAT16_H_
#define BFLOAT16_H_
#include <boost/operators.hpp>
#include <iostream>
#include <miopen/config.h>

class bfloat16 : boost::totally_ordered<bfloat16, boost::arithmetic<bfloat16>>
{
    public:
    bfloat16() : data_{0} {}
    explicit bfloat16(float rhs)
    {
        union
        {
            float float_st;
            std::uint32_t bf16_st;
        } bits_st = {rhs};

        // BF16 round and NaN preservation code matches
        // https://github.com/ROCmSoftwarePlatform/rocBLAS/blob/develop/library/include/rocblas_bfloat16.h
        if((~bits_st.bf16_st & 0x7f800000) == 0) // Inf or NaN
        {
            // When all of the exponent bits are 1, the value is Inf or NaN.
            // Inf is indicated by a zero mantissa. NaN is indicated by any nonzero
            // mantissa bit. Quiet NaN is indicated by the most significant mantissa
            // bit being 1. Signaling NaN is indicated by the most significant
            // mantissa bit being 0 but some other bit(s) being 1. If any of the
            // lower 16 bits of the mantissa are 1, we set the least significant bit
            // of the bfloat16 mantissa, in order to preserve signaling NaN in case
            // the bloat16's mantissa bits are all 0.
            if((bits_st.bf16_st & 0xffff) != 0)
            {
                bits_st.bf16_st |= 0x10000; // Preserve signaling NaN
            }
        }
        else
        {
#if MIOPEN_USE_RNE_BFLOAT16 == 1
            // When the exponent bits are not all 1s, then the value is zero, normal,
            // or subnormal. We round the bfloat16 mantissa up by adding 0x7FFF, plus
            // 1 if the least significant bit of the bfloat16 mantissa is 1 (odd).
            // This causes the bfloat16's mantissa to be incremented by 1 if the 16
            // least significant bits of the float mantissa are greater than 0x8000,
            // or if they are equal to 0x8000 and the least significant bit of the
            // bfloat16 mantissa is 1 (odd). This causes it to be rounded to even when
            // the lower 16 bits are exactly 0x8000. If the bfloat16 mantissa already
            // has the value 0x7f, then incrementing it causes it to become 0x00 and
            // the exponent is incremented by one, which is the next higher FP value
            // to the unrounded bfloat16 value. When the bfloat16 value is subnormal
            // with an exponent of 0x00 and a mantissa of 0x7F, it may be rounded up
            // to a normal value with an exponent of 0x01 and a mantissa of 0x00.
            // When the bfloat16 value has an exponent of 0xFE and a mantissa of 0x7F,
            // incrementing it causes it to become an exponent of 0xFF and a mantissa
            // of 0x00, which is Inf, the next higher value to the unrounded value.
            bits_st.bf16_st +=
                (0x7fff + ((bits_st.bf16_st >> 16) & 1)); // Round to nearest, round to even
#else                                                     // truncation
// do nothing
#endif
        }
        data_ = bits_st.bf16_st >> 16;
    }
    operator float() const
    {
        union
        {
            std::uint32_t bf16_st;
            float float_st;
        } bits_st = {data_};

        bits_st.bf16_st = bits_st.bf16_st << 16;
        return bits_st.float_st;
    }

    bfloat16 operator-() const { return bfloat16(-static_cast<float>(*this)); }
    bfloat16 operator+() const { return *this; }

    bfloat16& operator=(const float rhs)
    {
        *this = bfloat16(rhs);
        return *this;
    }
    bfloat16& operator+=(bfloat16 rhs)
    {
        *this = bfloat16(static_cast<float>(*this) + static_cast<float>(rhs));
        return *this;
    }

    bfloat16& operator+=(float rhs)
    {
        *this = bfloat16(static_cast<float>(*this) + rhs);
        return *this;
    }

    bfloat16& operator-=(bfloat16 rhs)
    {
        *this += -rhs;
        return *this;
    }
    bfloat16& operator*=(bfloat16 rhs)
    {
        *this = bfloat16(static_cast<float>(*this) * static_cast<float>(rhs));
        return *this;
    }
    bfloat16& operator*=(float rhs)
    {
        *this = bfloat16(static_cast<float>(*this) * rhs);
        return *this;
    }

    bfloat16& operator/=(bfloat16 rhs)
    {
        *this = bfloat16(static_cast<float>(*this) / static_cast<float>(rhs));
        return *this;
    }
    bool operator<(bfloat16 rhs) const
    {
        return static_cast<float>(*this) < static_cast<float>(rhs);
    }
    bool operator==(bfloat16 rhs) const { return std::equal_to<float>()(*this, rhs); }

    static constexpr bfloat16 generate(uint16_t val) { return bfloat16{val, true}; }

    private:
    constexpr bfloat16(std::uint16_t val, bool) : data_{val} {}

    std::uint16_t data_;
};

namespace std {
template <>
class numeric_limits<bfloat16>
{
    public:
    static constexpr bool is_specialized = true;
    static constexpr bfloat16 min() noexcept { return bfloat16::generate(0x007F); }
    static constexpr bfloat16 max() noexcept { return bfloat16::generate(0x7F7F); }
    static constexpr bfloat16 lowest() noexcept { return bfloat16::generate(0xFF7F); }
    static constexpr bfloat16 epsilon() noexcept { return bfloat16::generate(0x3C00); }
    static constexpr bfloat16 infinity() noexcept { return bfloat16::generate(0x7F80); }
    static constexpr bfloat16 quiet_NaN() noexcept { return bfloat16::generate(0x7FC0); }
    static constexpr bfloat16 signaling_NaN() noexcept { return bfloat16::generate(0x7FC0); }
    static constexpr bfloat16 denorm_min() noexcept { return bfloat16::generate(0); }
};
} // namespace std
#endif
<|endoftext|>


<commit_before>/*
 * %injeqt copyright begin%
 * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com)
 * %injeqt copyright end%
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "implemented-by.h"

#include "extract-interfaces.h"

namespace injeqt { namespace internal {

implemented_by::implemented_by(type interface_type, type implementation_type) :
	_interface_type{std::move(interface_type)},
	_implementation_type{std::move(implementation_type)}
{
}

type implemented_by::interface_type() const
{
	return _interface_type;
}

type implemented_by::implementation_type() const
{
	return _implementation_type;
}

void validate(const implemented_by &ib)
{
	auto interaces = extract_interfaces(ib.implementation_type());
	if (std::find(std::begin(interaces), std::end(interaces), ib.interface_type()) == std::end(interaces))
		throw invalid_implemented_by_exception{};
}

bool operator == (const implemented_by &x, const implemented_by &y)
{
	if (x.interface_type() != y.interface_type())
		return false;

	if (x.implementation_type() != y.implementation_type())
		return false;

	return true;
}

bool operator != (const implemented_by &x, const implemented_by &y)
{
	return !(x == y);
}

}}
<commit_msg>add missing checks<commit_after>/*
 * %injeqt copyright begin%
 * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com)
 * %injeqt copyright end%
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "implemented-by.h"

#include "extract-interfaces.h"

namespace injeqt { namespace internal {

implemented_by::implemented_by(type interface_type, type implementation_type) :
	_interface_type{std::move(interface_type)},
	_implementation_type{std::move(implementation_type)}
{
}

type implemented_by::interface_type() const
{
	return _interface_type;
}

type implemented_by::implementation_type() const
{
	return _implementation_type;
}

void validate(const implemented_by &ib)
{
	validate(ib.interface_type());
	validate(ib.implementation_type());

	auto interfaces = extract_interfaces(ib.implementation_type());
	if (std::find(std::begin(interfaces), std::end(interfaces), ib.interface_type()) == std::end(interfaces))
		throw invalid_implemented_by_exception{};
}

bool operator == (const implemented_by &x, const implemented_by &y)
{
	if (x.interface_type() != y.interface_type())
		return false;

	if (x.implementation_type() != y.implementation_type())
		return false;

	return true;
}

bool operator != (const implemented_by &x, const implemented_by &y)
{
	return !(x == y);
}

}}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2007  Justin Karneges
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301  USA
 *
 */

#include <QtCore>
#include <QHostAddress>
#include "qdnssd.h"

// for ntohl
#ifdef Q_OS_WIN
# include <windows.h>
#else
# include <netinet/in.h>
#endif

class Command
{
public:
	enum Type
	{
		Query,
		Browse,
		Resolve,
		Reg
	};

	Type type;

	QString name; // query, resolve, reg
	int rtype; // query
	QString stype; // browse, resolve, reg
	QString domain; // browse, resolve, reg
	int port; // reg
	QByteArray txtRecord; // reg

	int id;
	int dnsId;
	bool error;
	bool done; // for resolve

	Command() :
		error(false),
		done(false)
	{
	}
};

static QString nameToString(const QByteArray &in)
{
	QStringList parts;
	int at = 0;
	while(at < in.size())
	{
		int len = in[at++];
		parts += QString::fromUtf8(in.mid(at, len));
		at += len;
	}
	return parts.join(".");
}

static QString recordToDesc(const QDnsSd::Record &rec)
{
	QString desc;

	if(rec.rrtype == 1) // A
	{
		quint32 *p = (quint32 *)rec.rdata.data();
		desc = QHostAddress(ntohl(*p)).toString();
	}
	else if(rec.rrtype == 28) // AAAA
	{
		desc = QHostAddress((quint8 *)rec.rdata.data()).toString();
	}
	else if(rec.rrtype == 12) // PTR
	{
		desc = QString("[%1]").arg(nameToString(rec.rdata));
	}
	else
		desc = QString("%1 bytes").arg(rec.rdata.size());

	return desc;
}

static QStringList txtRecordToStringList(const QByteArray &rdata)
{
	QList<QByteArray> txtEntries = QDnsSd::parseTxtRecord(rdata);
	if(txtEntries.isEmpty())
		return QStringList();

	QStringList out;
	foreach(const QByteArray &entry, txtEntries)
		out += QString::fromUtf8(entry);
	return out;
}

static void printIndentedTxt(const QByteArray &txtRecord)
{
	QStringList list = txtRecordToStringList(txtRecord);
	if(!list.isEmpty())
	{
		foreach(const QString &s, list)
			printf("   %s\n", qPrintable(s));
	}
	else
		printf("   (TXT parsing error)\n");
}

class App : public QObject
{
	Q_OBJECT
public:
	QList<Command> commands;
	QDnsSd *dns;

	App()
	{
		dns = new QDnsSd(this);
		connect(dns, SIGNAL(queryResult(int, const QDnsSd::QueryResult &)), SLOT(dns_queryResult(int, const QDnsSd::QueryResult &)));
		connect(dns, SIGNAL(browseResult(int, const QDnsSd::BrowseResult &)), SLOT(dns_browseResult(int, const QDnsSd::BrowseResult &)));
		connect(dns, SIGNAL(resolveResult(int, const QDnsSd::ResolveResult &)), SLOT(dns_resolveResult(int, const QDnsSd::ResolveResult &)));
		connect(dns, SIGNAL(regResult(int, const QDnsSd::RegResult &)), SLOT(dns_regResult(int, const QDnsSd::RegResult &)));
	}

public slots:
	void start()
	{
		for(int n = 0; n < commands.count(); ++n)
		{
			Command &c = commands[n];

			c.id = n;
			if(c.type == Command::Query)
			{
				printf("%2d: Query name=[%s], type=%d ...\n", c.id, qPrintable(c.name), c.rtype);
				c.dnsId = dns->query(c.name.toUtf8(), c.rtype);
			}
			else if(c.type == Command::Browse)
			{
				printf("%2d: Browse type=[%s]", c.id, qPrintable(c.stype));
				if(!c.domain.isEmpty())
					printf(", domain=[%s]", qPrintable(c.domain));
				printf(" ...\n");
				c.dnsId = dns->browse(c.stype.toUtf8(), c.domain.toUtf8());
			}
			else if(c.type == Command::Resolve)
			{
				printf("%2d: Resolve name=[%s], type=[%s], domain=[%s] ...\n", c.id, qPrintable(c.name), qPrintable(c.stype), qPrintable(c.domain));
				c.dnsId = dns->resolve(c.name.toUtf8(), c.stype.toUtf8(), c.domain.toUtf8());
			}
			else if(c.type == Command::Reg)
			{
				printf("%2d: Register name=[%s], type=[%s]", c.id, qPrintable(c.name), qPrintable(c.stype));
				if(!c.domain.isEmpty())
					printf(", domain=[%s]", qPrintable(c.domain));
				printf(", port=%d ...\n", c.port);
				if(!c.txtRecord.isEmpty())
					printIndentedTxt(c.txtRecord);

				c.dnsId = dns->reg(c.name.toUtf8(), c.stype.toUtf8(), c.domain.toUtf8(), c.port, c.txtRecord);
			}
		}
	}

signals:
	void quit();

private:
	int cmdIdToCmdIndex(int cmdId)
	{
		for(int n = 0; n < commands.count(); ++n)
		{
			const Command &c = commands[n];
			if(c.id == cmdId)
				return n;
		}
		return -1;
	}

	int dnsIdToCmdIndex(int dnsId)
	{
		for(int n = 0; n < commands.count(); ++n)
		{
			const Command &c = commands[n];
			if(c.dnsId == dnsId)
				return n;
		}
		return -1;
	}

	void tryQuit()
	{
		// quit if there are nothing but errors or completed resolves
		bool doQuit = true;
		foreach(const Command &c, commands)
		{
			if(c.error || (c.type == Command::Resolve && c.done))
				continue;

			doQuit = false;
			break;
		}

		if(doQuit)
			emit quit();
	}

private slots:
	void dns_queryResult(int id, const QDnsSd::QueryResult &result)
	{
		int at = dnsIdToCmdIndex(id);
		Command &c = commands[at];

		if(!result.success)
		{
			printf("%2d: Error.", c.id);
			if(!result.lowLevelError.func.isEmpty())
				printf(" (%s, %d)", qPrintable(result.lowLevelError.func), result.lowLevelError.code);
			printf("\n");
			c.error = true;
			tryQuit();
			return;
		}

		foreach(const QDnsSd::Record &rec, result.records)
		{
			if(rec.added)
			{
				printf("%2d: Added:   %s, ttl=%d\n", c.id, qPrintable(recordToDesc(rec)), rec.ttl);
				if(rec.rrtype == 16)
					printIndentedTxt(rec.rdata);
			}
			else
				printf("%2d: Removed: %s, ttl=%d\n", c.id, qPrintable(recordToDesc(rec)), rec.ttl);
		}
	}

	void dns_browseResult(int id, const QDnsSd::BrowseResult &result)
	{
		int at = dnsIdToCmdIndex(id);
		Command &c = commands[at];

		if(!result.success)
		{
			printf("%2d: Error.", c.id);
			if(!result.lowLevelError.func.isEmpty())
				printf(" (%s, %d)", qPrintable(result.lowLevelError.func), result.lowLevelError.code);
			printf("\n");
			c.error = true;
			tryQuit();
			return;
		}

		foreach(const QDnsSd::BrowseEntry &e, result.entries)
		{
			if(e.added)
				printf("%2d: Added:   [%s] [%s] [%s]\n", c.id, e.serviceName.data(), e.serviceType.data(), e.replyDomain.data());
			else
				printf("%2d: Removed: [%s]\n", c.id, e.serviceName.data());
		}
	}

	void dns_resolveResult(int id, const QDnsSd::ResolveResult &result)
	{
		int at = dnsIdToCmdIndex(id);
		Command &c = commands[at];

		if(!result.success)
		{
			printf("%2d: Error.", c.id);
			if(!result.lowLevelError.func.isEmpty())
				printf(" (%s, %d)", qPrintable(result.lowLevelError.func), result.lowLevelError.code);
			printf("\n");
			c.error = true;
			tryQuit();
			return;
		}

		printf("%2d: Result: host=[%s] port=%d\n", c.id, result.hostTarget.data(), result.port);
		if(!result.txtRecord.isEmpty())
			printIndentedTxt(result.txtRecord);

		c.done = true;
		tryQuit();
	}

	void dns_regResult(int id, const QDnsSd::RegResult &result)
	{
		int at = dnsIdToCmdIndex(id);
		Command &c = commands[at];

		if(!result.success)
		{
			QString errstr;
			if(result.errorCode == QDnsSd::RegResult::ErrorConflict)
				errstr = "Conflict";
			else
				errstr = "Generic";
			printf("%2d: Error (%s).", c.id, qPrintable(errstr));
			if(!result.lowLevelError.func.isEmpty())
				printf(" (%s, %d)", qPrintable(result.lowLevelError.func), result.lowLevelError.code);
			printf("\n");
			c.error = true;
			tryQuit();
			return;
		}

		printf("%2d: Registered: domain=[%s]\n", c.id, result.domain.data());
	}
};

#include "sdtest.moc"

void usage()
{
	printf("usage: sdtest [[command] (command) ...]\n");
	printf(" options: --txt=str0,...,strn\n");
	printf("\n");
	printf(" q=name,type#                   query for a record\n");
	printf(" b=type(,domain)                browse for services\n");
	printf(" r=name,type,domain             resolve a service\n");
	printf(" e=name,type,port(,domain)      register a service\n");
	printf("\n");
}

int main(int argc, char **argv)
{
	QCoreApplication qapp(argc, argv);

	QStringList args = qapp.arguments();
	args.removeFirst();

	if(args.count() < 1)
	{
		usage();
		return 1;
	}

	// options
	QStringList txt;

	for(int n = 0; n < args.count(); ++n)
	{
		QString s = args[n];
		if(!s.startsWith("--"))
			continue;
		QString var;
		QString val;
		int x = s.indexOf('=');
		if(x != -1)
		{
			var = s.mid(2, x - 2);
			val = s.mid(x + 1);
		}
		else
		{
			var = s.mid(2);
		}

		bool known = true;

		if(var == "txt")
		{
			txt = val.split(',');
		}
		else
			known = false;

		if(known)
		{
			args.removeAt(n);
			--n; // adjust position
		}
	}

	// commands
	QList<Command> commands;

	for(int n = 0; n < args.count(); ++n)
	{
		QString str = args[n];
		int n = str.indexOf('=');
		if(n == -1)
		{
			printf("Error: bad format of command.\n");
			return 1;
		}

		QString type = str.mid(0, n);
		QString rest = str.mid(n + 1);
		QStringList parts = rest.split(',');

		if(type == "q")
		{
			if(parts.count() < 2)
			{
				usage();
				return 1;
			}

			Command c;
			c.type = Command::Query;
			c.name = parts[0];
			c.rtype = parts[1].toInt();
			commands += c;
		}
		else if(type == "b")
		{
			if(parts.count() < 1)
			{
				usage();
				return 1;
			}

			Command c;
			c.type = Command::Browse;
			c.stype = parts[0];
			if(parts.count() >= 2)
				c.domain = parts[1];
			commands += c;
		}
		else if(type == "r")
		{
			if(parts.count() < 3)
			{
				usage();
				return 1;
			}

			Command c;
			c.type = Command::Resolve;
			c.name = parts[0];
			c.stype = parts[1];
			c.domain = parts[2];
			commands += c;
		}
		else if(type == "e")
		{
			if(parts.count() < 3)
			{
				usage();
				return 1;
			}

			Command c;
			c.type = Command::Reg;
			c.name = parts[0];
			c.stype = parts[1];
			c.port = parts[2].toInt();
			if(parts.count() >= 4)
				c.domain = parts[3];

			if(!txt.isEmpty())
			{
				QList<QByteArray> strings;
				foreach(const QString &str, txt)
					strings += str.toUtf8();

				QByteArray txtRecord = QDnsSd::createTxtRecord(strings);
				if(txtRecord.isEmpty())
				{
					printf("Error: failed to create TXT record, input too large or invalid\n");
					return 1;
				}

				c.txtRecord = txtRecord;
			}

			commands += c;
		}
		else
		{
			printf("Error: unknown command type '%s'.\n", qPrintable(type));
			return 1;
		}
	}

	App app;
	app.commands = commands;
	QObject::connect(&app, SIGNAL(quit()), &qapp, SLOT(quit()));
	QTimer::singleShot(0, &app, SLOT(start()));
	qapp.exec();
	return 0;
}
<commit_msg>more unicode fixes<commit_after>/*
 * Copyright (C) 2007  Justin Karneges
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301  USA
 *
 */

#include <QtCore>
#include <QHostAddress>
#include "qdnssd.h"

// for ntohl
#ifdef Q_OS_WIN
# include <windows.h>
#else
# include <netinet/in.h>
#endif

class Command
{
public:
	enum Type
	{
		Query,
		Browse,
		Resolve,
		Reg
	};

	Type type;

	QString name; // query, resolve, reg
	int rtype; // query
	QString stype; // browse, resolve, reg
	QString domain; // browse, resolve, reg
	int port; // reg
	QByteArray txtRecord; // reg

	int id;
	int dnsId;
	bool error;
	bool done; // for resolve

	Command() :
		error(false),
		done(false)
	{
	}
};

static QString nameToString(const QByteArray &in)
{
	QStringList parts;
	int at = 0;
	while(at < in.size())
	{
		int len = in[at++];
		parts += QString::fromUtf8(in.mid(at, len));
		at += len;
	}
	return parts.join(".");
}

static QString recordToDesc(const QDnsSd::Record &rec)
{
	QString desc;

	if(rec.rrtype == 1) // A
	{
		quint32 *p = (quint32 *)rec.rdata.data();
		desc = QHostAddress(ntohl(*p)).toString();
	}
	else if(rec.rrtype == 28) // AAAA
	{
		desc = QHostAddress((quint8 *)rec.rdata.data()).toString();
	}
	else if(rec.rrtype == 12) // PTR
	{
		desc = QString("[%1]").arg(nameToString(rec.rdata));
	}
	else
		desc = QString("%1 bytes").arg(rec.rdata.size());

	return desc;
}

static QStringList txtRecordToStringList(const QByteArray &rdata)
{
	QList<QByteArray> txtEntries = QDnsSd::parseTxtRecord(rdata);
	if(txtEntries.isEmpty())
		return QStringList();

	QStringList out;
	foreach(const QByteArray &entry, txtEntries)
		out += QString::fromUtf8(entry);
	return out;
}

static void printIndentedTxt(const QByteArray &txtRecord)
{
	QStringList list = txtRecordToStringList(txtRecord);
	if(!list.isEmpty())
	{
		foreach(const QString &s, list)
			printf("   %s\n", qPrintable(s));
	}
	else
		printf("   (TXT parsing error)\n");
}

class App : public QObject
{
	Q_OBJECT
public:
	QList<Command> commands;
	QDnsSd *dns;

	App()
	{
		dns = new QDnsSd(this);
		connect(dns, SIGNAL(queryResult(int, const QDnsSd::QueryResult &)), SLOT(dns_queryResult(int, const QDnsSd::QueryResult &)));
		connect(dns, SIGNAL(browseResult(int, const QDnsSd::BrowseResult &)), SLOT(dns_browseResult(int, const QDnsSd::BrowseResult &)));
		connect(dns, SIGNAL(resolveResult(int, const QDnsSd::ResolveResult &)), SLOT(dns_resolveResult(int, const QDnsSd::ResolveResult &)));
		connect(dns, SIGNAL(regResult(int, const QDnsSd::RegResult &)), SLOT(dns_regResult(int, const QDnsSd::RegResult &)));
	}

public slots:
	void start()
	{
		for(int n = 0; n < commands.count(); ++n)
		{
			Command &c = commands[n];

			c.id = n;
			if(c.type == Command::Query)
			{
				printf("%2d: Query name=[%s], type=%d ...\n", c.id, qPrintable(c.name), c.rtype);
				c.dnsId = dns->query(c.name.toUtf8(), c.rtype);
			}
			else if(c.type == Command::Browse)
			{
				printf("%2d: Browse type=[%s]", c.id, qPrintable(c.stype));
				if(!c.domain.isEmpty())
					printf(", domain=[%s]", qPrintable(c.domain));
				printf(" ...\n");
				c.dnsId = dns->browse(c.stype.toUtf8(), c.domain.toUtf8());
			}
			else if(c.type == Command::Resolve)
			{
				printf("%2d: Resolve name=[%s], type=[%s], domain=[%s] ...\n", c.id, qPrintable(c.name), qPrintable(c.stype), qPrintable(c.domain));
				c.dnsId = dns->resolve(c.name.toUtf8(), c.stype.toUtf8(), c.domain.toUtf8());
			}
			else if(c.type == Command::Reg)
			{
				printf("%2d: Register name=[%s], type=[%s]", c.id, qPrintable(c.name), qPrintable(c.stype));
				if(!c.domain.isEmpty())
					printf(", domain=[%s]", qPrintable(c.domain));
				printf(", port=%d ...\n", c.port);
				if(!c.txtRecord.isEmpty())
					printIndentedTxt(c.txtRecord);

				c.dnsId = dns->reg(c.name.toUtf8(), c.stype.toUtf8(), c.domain.toUtf8(), c.port, c.txtRecord);
			}
		}
	}

signals:
	void quit();

private:
	int cmdIdToCmdIndex(int cmdId)
	{
		for(int n = 0; n < commands.count(); ++n)
		{
			const Command &c = commands[n];
			if(c.id == cmdId)
				return n;
		}
		return -1;
	}

	int dnsIdToCmdIndex(int dnsId)
	{
		for(int n = 0; n < commands.count(); ++n)
		{
			const Command &c = commands[n];
			if(c.dnsId == dnsId)
				return n;
		}
		return -1;
	}

	void tryQuit()
	{
		// quit if there are nothing but errors or completed resolves
		bool doQuit = true;
		foreach(const Command &c, commands)
		{
			if(c.error || (c.type == Command::Resolve && c.done))
				continue;

			doQuit = false;
			break;
		}

		if(doQuit)
			emit quit();
	}

private slots:
	void dns_queryResult(int id, const QDnsSd::QueryResult &result)
	{
		int at = dnsIdToCmdIndex(id);
		Command &c = commands[at];

		if(!result.success)
		{
			printf("%2d: Error.", c.id);
			if(!result.lowLevelError.func.isEmpty())
				printf(" (%s, %d)", qPrintable(result.lowLevelError.func), result.lowLevelError.code);
			printf("\n");
			c.error = true;
			tryQuit();
			return;
		}

		foreach(const QDnsSd::Record &rec, result.records)
		{
			if(rec.added)
			{
				printf("%2d: Added:   %s, ttl=%d\n", c.id, qPrintable(recordToDesc(rec)), rec.ttl);
				if(rec.rrtype == 16)
					printIndentedTxt(rec.rdata);
			}
			else
				printf("%2d: Removed: %s, ttl=%d\n", c.id, qPrintable(recordToDesc(rec)), rec.ttl);
		}
	}

	void dns_browseResult(int id, const QDnsSd::BrowseResult &result)
	{
		int at = dnsIdToCmdIndex(id);
		Command &c = commands[at];

		if(!result.success)
		{
			printf("%2d: Error.", c.id);
			if(!result.lowLevelError.func.isEmpty())
				printf(" (%s, %d)", qPrintable(result.lowLevelError.func), result.lowLevelError.code);
			printf("\n");
			c.error = true;
			tryQuit();
			return;
		}

		foreach(const QDnsSd::BrowseEntry &e, result.entries)
		{
			if(e.added)
				printf("%2d: Added:   [%s] [%s] [%s]\n", c.id, qPrintable(QString::fromUtf8(e.serviceName)), qPrintable(QString::fromUtf8(e.serviceType)), qPrintable(QString::fromUtf8(e.replyDomain)));
			else
				printf("%2d: Removed: [%s]\n", c.id, qPrintable(QString::fromUtf8(e.serviceName)));
		}
	}

	void dns_resolveResult(int id, const QDnsSd::ResolveResult &result)
	{
		int at = dnsIdToCmdIndex(id);
		Command &c = commands[at];

		if(!result.success)
		{
			printf("%2d: Error.", c.id);
			if(!result.lowLevelError.func.isEmpty())
				printf(" (%s, %d)", qPrintable(result.lowLevelError.func), result.lowLevelError.code);
			printf("\n");
			c.error = true;
			tryQuit();
			return;
		}

		printf("%2d: Result: host=[%s] port=%d\n", c.id, qPrintable(QString::fromUtf8(result.hostTarget)), result.port);
		if(!result.txtRecord.isEmpty())
			printIndentedTxt(result.txtRecord);

		c.done = true;
		tryQuit();
	}

	void dns_regResult(int id, const QDnsSd::RegResult &result)
	{
		int at = dnsIdToCmdIndex(id);
		Command &c = commands[at];

		if(!result.success)
		{
			QString errstr;
			if(result.errorCode == QDnsSd::RegResult::ErrorConflict)
				errstr = "Conflict";
			else
				errstr = "Generic";
			printf("%2d: Error (%s).", c.id, qPrintable(errstr));
			if(!result.lowLevelError.func.isEmpty())
				printf(" (%s, %d)", qPrintable(result.lowLevelError.func), result.lowLevelError.code);
			printf("\n");
			c.error = true;
			tryQuit();
			return;
		}

		printf("%2d: Registered: domain=[%s]\n", c.id, qPrintable(QString::fromUtf8(result.domain)));
	}
};

#include "sdtest.moc"

void usage()
{
	printf("usage: sdtest [[command] (command) ...]\n");
	printf(" options: --txt=str0,...,strn\n");
	printf("\n");
	printf(" q=name,type#                   query for a record\n");
	printf(" b=type(,domain)                browse for services\n");
	printf(" r=name,type,domain             resolve a service\n");
	printf(" e=name,type,port(,domain)      register a service\n");
	printf("\n");
}

int main(int argc, char **argv)
{
	QCoreApplication qapp(argc, argv);

	QStringList args = qapp.arguments();
	args.removeFirst();

	if(args.count() < 1)
	{
		usage();
		return 1;
	}

	// options
	QStringList txt;

	for(int n = 0; n < args.count(); ++n)
	{
		QString s = args[n];
		if(!s.startsWith("--"))
			continue;
		QString var;
		QString val;
		int x = s.indexOf('=');
		if(x != -1)
		{
			var = s.mid(2, x - 2);
			val = s.mid(x + 1);
		}
		else
		{
			var = s.mid(2);
		}

		bool known = true;

		if(var == "txt")
		{
			txt = val.split(',');
		}
		else
			known = false;

		if(known)
		{
			args.removeAt(n);
			--n; // adjust position
		}
	}

	// commands
	QList<Command> commands;

	for(int n = 0; n < args.count(); ++n)
	{
		QString str = args[n];
		int n = str.indexOf('=');
		if(n == -1)
		{
			printf("Error: bad format of command.\n");
			return 1;
		}

		QString type = str.mid(0, n);
		QString rest = str.mid(n + 1);
		QStringList parts = rest.split(',');

		if(type == "q")
		{
			if(parts.count() < 2)
			{
				usage();
				return 1;
			}

			Command c;
			c.type = Command::Query;
			c.name = parts[0];
			c.rtype = parts[1].toInt();
			commands += c;
		}
		else if(type == "b")
		{
			if(parts.count() < 1)
			{
				usage();
				return 1;
			}

			Command c;
			c.type = Command::Browse;
			c.stype = parts[0];
			if(parts.count() >= 2)
				c.domain = parts[1];
			commands += c;
		}
		else if(type == "r")
		{
			if(parts.count() < 3)
			{
				usage();
				return 1;
			}

			Command c;
			c.type = Command::Resolve;
			c.name = parts[0];
			c.stype = parts[1];
			c.domain = parts[2];
			commands += c;
		}
		else if(type == "e")
		{
			if(parts.count() < 3)
			{
				usage();
				return 1;
			}

			Command c;
			c.type = Command::Reg;
			c.name = parts[0];
			c.stype = parts[1];
			c.port = parts[2].toInt();
			if(parts.count() >= 4)
				c.domain = parts[3];

			if(!txt.isEmpty())
			{
				QList<QByteArray> strings;
				foreach(const QString &str, txt)
					strings += str.toUtf8();

				QByteArray txtRecord = QDnsSd::createTxtRecord(strings);
				if(txtRecord.isEmpty())
				{
					printf("Error: failed to create TXT record, input too large or invalid\n");
					return 1;
				}

				c.txtRecord = txtRecord;
			}

			commands += c;
		}
		else
		{
			printf("Error: unknown command type '%s'.\n", qPrintable(type));
			return 1;
		}
	}

	App app;
	app.commands = commands;
	QObject::connect(&app, SIGNAL(quit()), &qapp, SLOT(quit()));
	QTimer::singleShot(0, &app, SLOT(start()));
	qapp.exec();
	return 0;
}
<|endoftext|>


<commit_before>#ifndef MAINSTATE_HPP
#define MAINSTATE_HPP

#include <memory>
#include <SFML/Graphics/RenderTarget.hpp>
#include "gamelib/GameState.hpp"
#include "gamelib/sprite/SpriteSet.hpp"
#include "gamelib/Scene/Scene.hpp"
#include "gamelib/tile/StaticRenderTilemap.hpp"
#include "gamelib/event/SFMLEvent.hpp"
#include "gamelib/utils/DebugGui.hpp"
#include "Player.hpp"

namespace gamelib
{
    class Game;
    class EventManager;
}

class MainState : public gamelib::GameState
{
    public:
        MainState();

        bool init(gamelib::Game* game);
        void quit();

        void update(float fps);
        void render(sf::RenderTarget& target);

        const gamelib::Game& getGame() const;
        const gamelib::SpriteSet& getSpriteSet() const;
        const gamelib::StaticTilemap<gamelib::SpriteData>& getCollisionMap() const;

    private:
        static void _eventCallback(MainState* me, gamelib::EventPtr ev);

    private:
        gamelib::Game* _game;
        gamelib::SpriteSet _spriteset;
        gamelib::StaticRenderTilemap _map;
        Player _player;
};

#endif
<commit_msg>Remove unused include<commit_after>#ifndef MAINSTATE_HPP
#define MAINSTATE_HPP

#include <memory>
#include <SFML/Graphics/RenderTarget.hpp>
#include "gamelib/GameState.hpp"
#include "gamelib/sprite/SpriteSet.hpp"
#include "gamelib/Scene/Scene.hpp"
#include "gamelib/tile/StaticRenderTilemap.hpp"
#include "gamelib/event/SFMLEvent.hpp"
#include "Player.hpp"

namespace gamelib
{
    class Game;
    class EventManager;
}

class MainState : public gamelib::GameState
{
    public:
        MainState();

        bool init(gamelib::Game* game);
        void quit();

        void update(float fps);
        void render(sf::RenderTarget& target);

        const gamelib::Game& getGame() const;
        const gamelib::SpriteSet& getSpriteSet() const;
        const gamelib::StaticTilemap<gamelib::SpriteData>& getCollisionMap() const;

    private:
        static void _eventCallback(MainState* me, gamelib::EventPtr ev);

    private:
        gamelib::Game* _game;
        gamelib::SpriteSet _spriteset;
        gamelib::StaticRenderTilemap _map;
        Player _player;
};

#endif
<|endoftext|>


<commit_before>#include <engine/ParamQuantity.hpp>
#include <app.hpp>
#include <engine/Engine.hpp>

namespace rack {
namespace engine {

engine::Param *ParamQuantity::getParam() {
	assert(module);
	return &module->params[paramId];
}

void ParamQuantity::setSmoothValue(float smoothValue) {
	if (!module)
		return;
	smoothValue = math::clampSafe(smoothValue, getMinValue(), getMaxValue());
	APP->engine->setSmoothParam(module, paramId, smoothValue);
}

float ParamQuantity::getSmoothValue() {
	if (!module)
		return 0.f;
	return APP->engine->getSmoothParam(module, paramId);
}

void ParamQuantity::setValue(float value) {
	if (!module)
		return;
	value = math::clampSafe(value, getMinValue(), getMaxValue());
	APP->engine->setParam(module, paramId, value);
}

float ParamQuantity::getValue() {
	if (!module)
		return 0.f;
	return APP->engine->getParam(module, paramId);
}

float ParamQuantity::getMinValue() {
	return minValue;
}

float ParamQuantity::getMaxValue() {
	return maxValue;
}

float ParamQuantity::getDefaultValue() {
	return defaultValue;
}

float ParamQuantity::getDisplayValue() {
	if (!module)
		return Quantity::getDisplayValue();
	float v = getSmoothValue();
	if (displayBase == 0.f) {
		// Linear
		// v is unchanged
	}
	else if (displayBase < 0.f) {
		// Logarithmic
		v = std::log(v) / std::log(-displayBase);
	}
	else {
		// Exponential
		v = std::pow(displayBase, v);
	}
	return v * displayMultiplier + displayOffset;
}

void ParamQuantity::setDisplayValue(float displayValue) {
	if (!module)
		return;
	float v = (displayValue - displayOffset) / displayMultiplier;
	if (displayBase == 0.f) {
		// Linear
		// v is unchanged
	}
	else if (displayBase < 0.f) {
		// Logarithmic
		v = std::pow(-displayBase, v);
	}
	else {
		// Exponential
		v = std::log(v) / std::log(displayBase);
	}
	setValue(v);
}

int ParamQuantity::getDisplayPrecision() {
	return Quantity::getDisplayPrecision();
}

std::string ParamQuantity::getDisplayValueString() {
	return Quantity::getDisplayValueString();
}

void ParamQuantity::setDisplayValueString(std::string s) {
	Quantity::setDisplayValueString(s);
}

std::string ParamQuantity::getLabel() {
	return label;
}

std::string ParamQuantity::getUnit() {
	return unit;
}

} // namespace engine
} // namespace rack
<commit_msg>Allow ParamQuantity::displayMultiplier to be 0.<commit_after>#include <engine/ParamQuantity.hpp>
#include <app.hpp>
#include <engine/Engine.hpp>

namespace rack {
namespace engine {

engine::Param *ParamQuantity::getParam() {
	assert(module);
	return &module->params[paramId];
}

void ParamQuantity::setSmoothValue(float smoothValue) {
	if (!module)
		return;
	smoothValue = math::clampSafe(smoothValue, getMinValue(), getMaxValue());
	APP->engine->setSmoothParam(module, paramId, smoothValue);
}

float ParamQuantity::getSmoothValue() {
	if (!module)
		return 0.f;
	return APP->engine->getSmoothParam(module, paramId);
}

void ParamQuantity::setValue(float value) {
	if (!module)
		return;
	value = math::clampSafe(value, getMinValue(), getMaxValue());
	APP->engine->setParam(module, paramId, value);
}

float ParamQuantity::getValue() {
	if (!module)
		return 0.f;
	return APP->engine->getParam(module, paramId);
}

float ParamQuantity::getMinValue() {
	return minValue;
}

float ParamQuantity::getMaxValue() {
	return maxValue;
}

float ParamQuantity::getDefaultValue() {
	return defaultValue;
}

float ParamQuantity::getDisplayValue() {
	if (!module)
		return Quantity::getDisplayValue();
	float v = getSmoothValue();
	if (displayBase == 0.f) {
		// Linear
		// v is unchanged
	}
	else if (displayBase < 0.f) {
		// Logarithmic
		v = std::log(v) / std::log(-displayBase);
	}
	else {
		// Exponential
		v = std::pow(displayBase, v);
	}
	return v * displayMultiplier + displayOffset;
}

void ParamQuantity::setDisplayValue(float displayValue) {
	if (!module)
		return;
	float v = displayValue - displayOffset;
	if (displayMultiplier == 0.f)
		v = 0.f;
	else
		v /= displayMultiplier;
	if (displayBase == 0.f) {
		// Linear
		// v is unchanged
	}
	else if (displayBase < 0.f) {
		// Logarithmic
		v = std::pow(-displayBase, v);
	}
	else {
		// Exponential
		v = std::log(v) / std::log(displayBase);
	}
	setValue(v);
}

int ParamQuantity::getDisplayPrecision() {
	return Quantity::getDisplayPrecision();
}

std::string ParamQuantity::getDisplayValueString() {
	return Quantity::getDisplayValueString();
}

void ParamQuantity::setDisplayValueString(std::string s) {
	Quantity::setDisplayValueString(s);
}

std::string ParamQuantity::getLabel() {
	return label;
}

std::string ParamQuantity::getUnit() {
	return unit;
}

} // namespace engine
} // namespace rack
<|endoftext|>


<commit_before>/* This file is part of Ingen.
 * Copyright (C) 2007-2009 Dave Robillard <http://drobilla.net>
 *
 * Ingen is free software; you can redistribute it and/or modify it under the
 * terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later
 * version.
 *
 * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include "raul/Maid.hpp"
#include "raul/Path.hpp"
#include "ClientBroadcaster.hpp"
#include "ControlBindings.hpp"
#include "Delete.hpp"
#include "DisconnectAll.hpp"
#include "Driver.hpp"
#include "Engine.hpp"
#include "EngineStore.hpp"
#include "NodeBase.hpp"
#include "PatchImpl.hpp"
#include "PluginImpl.hpp"
#include "PortImpl.hpp"
#include "Request.hpp"

using namespace std;

namespace Ingen {
namespace Events {

using namespace Shared;

Delete::Delete(Engine& engine, SharedPtr<Request> request, FrameTime time, const Raul::Path& path)
	: QueuedEvent(engine, request, time, true)
	, _path(path)
	, _store_iterator(engine.engine_store()->end())
	, _driver_port(NULL)
	, _patch_node_listnode(NULL)
	, _patch_port_listnode(NULL)
	, _ports_array(NULL)
	, _compiled_patch(NULL)
	, _disconnect_event(NULL)
{
	assert(request);
	assert(request->source());
}

Delete::~Delete()
{
	delete _disconnect_event;
}

void
Delete::pre_process()
{
	_removed_bindings = _engine.control_bindings()->remove(_path);

	_store_iterator = _engine.engine_store()->find(_path);

	if (_store_iterator != _engine.engine_store()->end())  {
		_node = PtrCast<NodeImpl>(_store_iterator->second);

		if (!_node)
			_port = PtrCast<PortImpl>(_store_iterator->second);
	}

	if (_store_iterator != _engine.engine_store()->end()) {
		_removed_table = _engine.engine_store()->remove(_store_iterator);
	}

	if (_node && !_path.is_root()) {
		assert(_node->parent_patch());
		_patch_node_listnode = _node->parent_patch()->remove_node(_path.symbol());
		if (_patch_node_listnode) {
			assert(_patch_node_listnode->elem() == _node.get());

			_disconnect_event = new DisconnectAll(_engine, _node->parent_patch(), _node.get());
			_disconnect_event->pre_process();

			if (_node->parent_patch()->enabled()) {
				// FIXME: is this called multiple times?
				_compiled_patch = _node->parent_patch()->compile();
#ifndef NDEBUG
				// Be sure node is removed from process order, so it can be deleted
				for (size_t i=0; i < _compiled_patch->size(); ++i) {
					assert(_compiled_patch->at(i).node() != _node.get());
					// FIXME: check providers/dependants too
				}
#endif
			}
		}
	} else if (_port) {
		assert(_port->parent_patch());
		_patch_port_listnode = _port->parent_patch()->remove_port(_path.symbol());
		if (_patch_port_listnode) {
			assert(_patch_port_listnode->elem() == _port.get());

			_disconnect_event = new DisconnectAll(_engine, _port->parent_patch(), _port.get());
			_disconnect_event->pre_process();

			if (_port->parent_patch()->enabled()) {
				// FIXME: is this called multiple times?
				_compiled_patch = _port->parent_patch()->compile();
				_ports_array   = _port->parent_patch()->build_ports_array();
				assert(_ports_array->size() == _port->parent_patch()->num_ports());
			}
		}

	}

	QueuedEvent::pre_process();
}

void
Delete::execute(ProcessContext& context)
{
	QueuedEvent::execute(context);

	if (_patch_node_listnode) {
		assert(_node);

		if (_disconnect_event)
			_disconnect_event->execute(context);

		if (_node->parent_patch()->compiled_patch())
			_engine.maid()->push(_node->parent_patch()->compiled_patch());

		_node->parent_patch()->compiled_patch(_compiled_patch);

	} else if (_patch_port_listnode) {
		assert(_port);

		if (_disconnect_event)
			_disconnect_event->execute(context);

		if (_port->parent_patch()->compiled_patch())
			_engine.maid()->push(_port->parent_patch()->compiled_patch());

		_port->parent_patch()->compiled_patch(_compiled_patch);

		if (_port->parent_patch()->external_ports())
			_engine.maid()->push(_port->parent_patch()->external_ports());

		_port->parent_patch()->external_ports(_ports_array);

		if ( ! _port->parent_patch()->parent()) {
			_driver_port = _engine.driver()->remove_port(_port->path());
		}
	}

	_request->unblock();
}

void
Delete::post_process()
{
	_removed_bindings.reset();

	if (!_node && !_port) {
		if (_path.is_root()) {
			_request->respond_error("You can not destroy the root patch (/)");
		} else {
			string msg = string("Could not find object ") + _path.str() + " to destroy";
			_request->respond_error(msg);
		}
	}

	if (_patch_node_listnode) {
		assert(_node);
		_node->deactivate();
		_request->respond_ok();
		_engine.broadcaster()->bundle_begin();
		if (_disconnect_event)
			_disconnect_event->post_process();
		_engine.broadcaster()->del(_path);
		_engine.broadcaster()->bundle_end();
		_engine.maid()->push(_patch_node_listnode);
	} else if (_patch_port_listnode) {
		assert(_port);
		_request->respond_ok();
		_engine.broadcaster()->bundle_begin();
		if (_disconnect_event)
			_disconnect_event->post_process();
		_engine.broadcaster()->del(_path);
		_engine.broadcaster()->bundle_end();
		_engine.maid()->push(_patch_port_listnode);
	} else {
		_request->respond_error("Unable to destroy object");
	}

	if (_driver_port) {
		_driver_port->elem()->destroy();
		_engine.maid()->push(_driver_port);
	}
}

} // namespace Ingen
} // namespace Events
<commit_msg>Refuse to delete /control_in or /control_out (fix crashes e.g. select-all + delete).<commit_after>/* This file is part of Ingen.
 * Copyright (C) 2007-2009 Dave Robillard <http://drobilla.net>
 *
 * Ingen is free software; you can redistribute it and/or modify it under the
 * terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later
 * version.
 *
 * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include "raul/Maid.hpp"
#include "raul/Path.hpp"
#include "ClientBroadcaster.hpp"
#include "ControlBindings.hpp"
#include "Delete.hpp"
#include "DisconnectAll.hpp"
#include "Driver.hpp"
#include "Engine.hpp"
#include "EngineStore.hpp"
#include "NodeBase.hpp"
#include "PatchImpl.hpp"
#include "PluginImpl.hpp"
#include "PortImpl.hpp"
#include "Request.hpp"

using namespace std;

namespace Ingen {
namespace Events {

using namespace Shared;

Delete::Delete(Engine& engine, SharedPtr<Request> request, FrameTime time, const Raul::Path& path)
	: QueuedEvent(engine, request, time, true)
	, _path(path)
	, _store_iterator(engine.engine_store()->end())
	, _driver_port(NULL)
	, _patch_node_listnode(NULL)
	, _patch_port_listnode(NULL)
	, _ports_array(NULL)
	, _compiled_patch(NULL)
	, _disconnect_event(NULL)
{
	assert(request);
	assert(request->source());
}

Delete::~Delete()
{
	delete _disconnect_event;
}

void
Delete::pre_process()
{
	if (_path.is_root() || _path == "path:/control_in" || _path == "path:/control_out") {
		QueuedEvent::pre_process();
		return;
	}

	_removed_bindings = _engine.control_bindings()->remove(_path);

	_store_iterator = _engine.engine_store()->find(_path);

	if (_store_iterator != _engine.engine_store()->end())  {
		_node = PtrCast<NodeImpl>(_store_iterator->second);

		if (!_node)
			_port = PtrCast<PortImpl>(_store_iterator->second);
	}

	if (_store_iterator != _engine.engine_store()->end()) {
		_removed_table = _engine.engine_store()->remove(_store_iterator);
	}

	if (_node && !_path.is_root()) {
		assert(_node->parent_patch());
		_patch_node_listnode = _node->parent_patch()->remove_node(_path.symbol());
		if (_patch_node_listnode) {
			assert(_patch_node_listnode->elem() == _node.get());

			_disconnect_event = new DisconnectAll(_engine, _node->parent_patch(), _node.get());
			_disconnect_event->pre_process();

			if (_node->parent_patch()->enabled()) {
				// FIXME: is this called multiple times?
				_compiled_patch = _node->parent_patch()->compile();
#ifndef NDEBUG
				// Be sure node is removed from process order, so it can be deleted
				for (size_t i=0; i < _compiled_patch->size(); ++i) {
					assert(_compiled_patch->at(i).node() != _node.get());
					// FIXME: check providers/dependants too
				}
#endif
			}
		}
	} else if (_port) {
		assert(_port->parent_patch());
		_patch_port_listnode = _port->parent_patch()->remove_port(_path.symbol());
		if (_patch_port_listnode) {
			assert(_patch_port_listnode->elem() == _port.get());

			_disconnect_event = new DisconnectAll(_engine, _port->parent_patch(), _port.get());
			_disconnect_event->pre_process();

			if (_port->parent_patch()->enabled()) {
				// FIXME: is this called multiple times?
				_compiled_patch = _port->parent_patch()->compile();
				_ports_array   = _port->parent_patch()->build_ports_array();
				assert(_ports_array->size() == _port->parent_patch()->num_ports());
			}
		}

	}

	QueuedEvent::pre_process();
}

void
Delete::execute(ProcessContext& context)
{
	QueuedEvent::execute(context);

	if (_patch_node_listnode) {
		assert(_node);

		if (_disconnect_event)
			_disconnect_event->execute(context);

		if (_node->parent_patch()->compiled_patch())
			_engine.maid()->push(_node->parent_patch()->compiled_patch());

		_node->parent_patch()->compiled_patch(_compiled_patch);

	} else if (_patch_port_listnode) {
		assert(_port);

		if (_disconnect_event)
			_disconnect_event->execute(context);

		if (_port->parent_patch()->compiled_patch())
			_engine.maid()->push(_port->parent_patch()->compiled_patch());

		_port->parent_patch()->compiled_patch(_compiled_patch);

		if (_port->parent_patch()->external_ports())
			_engine.maid()->push(_port->parent_patch()->external_ports());

		_port->parent_patch()->external_ports(_ports_array);

		if ( ! _port->parent_patch()->parent()) {
			_driver_port = _engine.driver()->remove_port(_port->path());
		}
	}

	_request->unblock();
}

void
Delete::post_process()
{
	_removed_bindings.reset();

	if (_path.is_root() || _path == "path:/control_in" || _path == "path:/control_out") {
		_request->respond_error(_path.chop_scheme() + " can not be deleted");
	} else if (!_node && !_port) {
		string msg = string("Could not find object ") + _path.chop_scheme() + " to delete";
		_request->respond_error(msg);
	} else if (_patch_node_listnode) {
		assert(_node);
		_node->deactivate();
		_request->respond_ok();
		_engine.broadcaster()->bundle_begin();
		if (_disconnect_event)
			_disconnect_event->post_process();
		_engine.broadcaster()->del(_path);
		_engine.broadcaster()->bundle_end();
		_engine.maid()->push(_patch_node_listnode);
	} else if (_patch_port_listnode) {
		assert(_port);
		_request->respond_ok();
		_engine.broadcaster()->bundle_begin();
		if (_disconnect_event)
			_disconnect_event->post_process();
		_engine.broadcaster()->del(_path);
		_engine.broadcaster()->bundle_end();
		_engine.maid()->push(_patch_port_listnode);
	} else {
		_request->respond_error("Unable to delete object " + _path.chop_scheme());
	}

	if (_driver_port) {
		_driver_port->elem()->destroy();
		_engine.maid()->push(_driver_port);
	}
}

} // namespace Ingen
} // namespace Events
<|endoftext|>


<commit_before>#include <glog/logging.h>
#include <util/util.h>
#include <mailer_pool.h>

using namespace std::placeholders;

namespace {

struct mailer_extra {
  const std::string server;
  const std::string from;
  const std::vector<std::string> to;
};

typedef std::pair<std::vector<char>, size_t> payload_t;

size_t payload_source(void *ptr, size_t size, size_t nmemb, void *userp)
{

  if((size == 0) || (nmemb == 0) || ((size * nmemb) < 1)) {
    return 0;
  }

  auto payload_data = static_cast<payload_t*>(userp);

  size_t copied = payload_data->second;
  size_t left = payload_data->first.size() - copied;
  size_t to_copy = std::min(size * nmemb, left);

  if (to_copy > 0) {

    memcpy(ptr, static_cast<void*>(&payload_data->first[copied]), to_copy);
    payload_data->second += to_copy;

    return to_copy;

  } else {
    return 0;
  }

}

std::vector<char> payload_text(const mailer_extra extra, const Event & e) {

  std::string to = "unknown";

  if (!extra.to.empty()) {
    to = extra.to[0];
  }

  std::string subject = e.host() + " " + e.service() + " is " + e.state()
                        + e.metric_to_str();

  std::string payload = "To: " + to + "\r\n" +
                        "From: " + extra.from + "\r\n" +
                        "Subject: " + subject + "\r\n" +
                        "\r\n" +
                        e.json_str();

  return std::vector<char>(payload.begin(), payload.end());
}

}

mailer_pool::mailer_pool(const size_t thread_num, const bool enable_debug)
  :
  curl_pool_(
      thread_num,
      std::bind(&mailer_pool::curl_event, this, _1, _2, _3)
  ),
  enable_debug_(enable_debug)
{
}

void mailer_pool::push_event(const std::string server, const std::string from,
                             const std::vector<std::string> to,
                             const Event & event)
{
  VLOG(3) << "push_event()  server: " << server << " from: " << from;

  mailer_extra extra = {server, from, to};
  curl_pool_.push_event(event, extra);

}

void mailer_pool::curl_event(const queued_event_t queued_event,
                             const std::shared_ptr<CURL> easy,
                             std::function<void()> & clean_fn)
{

  const auto extra = boost::any_cast<mailer_extra>(queued_event.extra);
  const auto & e = queued_event.event;

  std::shared_ptr<std::string> server(
      new std::string("smtp://" + extra.server));

  std::shared_ptr<std::string> from(new std::string(extra.from));

  struct curl_slist *recipients = NULL;
  for (const auto & to : extra.to) {
    recipients = curl_slist_append(recipients, to.c_str());
  }

  auto payload = std::make_shared<payload_t>(
                                      payload_t({payload_text(extra, e), 0}));

  curl_easy_setopt(easy.get(), CURLOPT_URL, server->c_str());
  curl_easy_setopt(easy.get(), CURLOPT_MAIL_FROM, from->c_str());
  curl_easy_setopt(easy.get(), CURLOPT_MAIL_RCPT, recipients);
  curl_easy_setopt(easy.get(), CURLOPT_UPLOAD, 1L);
  curl_easy_setopt(easy.get(), CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
  curl_easy_setopt(easy.get(), CURLOPT_READFUNCTION, payload_source);
  curl_easy_setopt(easy.get(), CURLOPT_READDATA, payload.get());
  curl_easy_setopt(easy.get(), CURLOPT_VERBOSE, enable_debug_);

  clean_fn = [=]()
  {
    UNUSED_VAR(server);
    UNUSED_VAR(from);
    UNUSED_VAR(payload);
    if (recipients) {
      curl_slist_free_all(recipients);
    }
  };

}

void mailer_pool::stop() {
  VLOG(3) << "stop()";

  curl_pool_.stop();
}
<commit_msg>Improve email subject<commit_after>#include <glog/logging.h>
#include <util/util.h>
#include <mailer_pool.h>

using namespace std::placeholders;

namespace {

struct mailer_extra {
  const std::string server;
  const std::string from;
  const std::vector<std::string> to;
};

typedef std::pair<std::vector<char>, size_t> payload_t;

size_t payload_source(void *ptr, size_t size, size_t nmemb, void *userp)
{

  if((size == 0) || (nmemb == 0) || ((size * nmemb) < 1)) {
    return 0;
  }

  auto payload_data = static_cast<payload_t*>(userp);

  size_t copied = payload_data->second;
  size_t left = payload_data->first.size() - copied;
  size_t to_copy = std::min(size * nmemb, left);

  if (to_copy > 0) {

    memcpy(ptr, static_cast<void*>(&payload_data->first[copied]), to_copy);
    payload_data->second += to_copy;

    return to_copy;

  } else {
    return 0;
  }

}

std::vector<char> payload_text(const mailer_extra extra, const Event & e) {

  std::string to = "unknown";

  if (!extra.to.empty()) {
    to = extra.to[0];
  }

  std::string subject = e.host() + " " + e.service() + " is " + e.state();

  if (e.has_metric()) {
    subject += " (" + e.metric_to_str() +  ")";
  }

  std::string payload = "To: " + to + "\r\n" +
                        "From: " + extra.from + "\r\n" +
                        "Subject: " + subject + "\r\n" +
                        "\r\n" +
                        e.json_str();

  return std::vector<char>(payload.begin(), payload.end());
}

}

mailer_pool::mailer_pool(const size_t thread_num, const bool enable_debug)
  :
  curl_pool_(
      thread_num,
      std::bind(&mailer_pool::curl_event, this, _1, _2, _3)
  ),
  enable_debug_(enable_debug)
{
}

void mailer_pool::push_event(const std::string server, const std::string from,
                             const std::vector<std::string> to,
                             const Event & event)
{
  VLOG(3) << "push_event()  server: " << server << " from: " << from;

  mailer_extra extra = {server, from, to};
  curl_pool_.push_event(event, extra);

}

void mailer_pool::curl_event(const queued_event_t queued_event,
                             const std::shared_ptr<CURL> easy,
                             std::function<void()> & clean_fn)
{

  const auto extra = boost::any_cast<mailer_extra>(queued_event.extra);
  const auto & e = queued_event.event;

  std::shared_ptr<std::string> server(
      new std::string("smtp://" + extra.server));

  std::shared_ptr<std::string> from(new std::string(extra.from));

  struct curl_slist *recipients = NULL;
  for (const auto & to : extra.to) {
    recipients = curl_slist_append(recipients, to.c_str());
  }

  auto payload = std::make_shared<payload_t>(
                                      payload_t({payload_text(extra, e), 0}));

  curl_easy_setopt(easy.get(), CURLOPT_URL, server->c_str());
  curl_easy_setopt(easy.get(), CURLOPT_MAIL_FROM, from->c_str());
  curl_easy_setopt(easy.get(), CURLOPT_MAIL_RCPT, recipients);
  curl_easy_setopt(easy.get(), CURLOPT_UPLOAD, 1L);
  curl_easy_setopt(easy.get(), CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
  curl_easy_setopt(easy.get(), CURLOPT_READFUNCTION, payload_source);
  curl_easy_setopt(easy.get(), CURLOPT_READDATA, payload.get());
  curl_easy_setopt(easy.get(), CURLOPT_VERBOSE, enable_debug_);

  clean_fn = [=]()
  {
    UNUSED_VAR(server);
    UNUSED_VAR(from);
    UNUSED_VAR(payload);
    if (recipients) {
      curl_slist_free_all(recipients);
    }
  };

}

void mailer_pool::stop() {
  VLOG(3) << "stop()";

  curl_pool_.stop();
}
<|endoftext|>


<commit_before>// Copyright (C) 2012-2015 Leap Motion, Inc. All rights reserved.
#include "stdafx.h"
#include "ProtobufUtil.hpp"
#include "Archive.h"
#include "Descriptor.h"
#include <iomanip>
#include <sstream>

using namespace leap;
using leap::internal::protobuf::WireType;

WireType leap::internal::protobuf::ToWireType(serial_atom atom) {
  switch (atom) {
  case serial_atom::boolean:
  case serial_atom::i8:
  case serial_atom::ui8:
  case serial_atom::i16:
  case serial_atom::ui16:
  case serial_atom::i32:
  case serial_atom::ui32:
  case serial_atom::i64:
  case serial_atom::ui64:
    return WireType::Varint;
  case serial_atom::f32:
    return WireType::DoubleWord;
  case serial_atom::f64:
    return WireType::QuadWord;
  case serial_atom::reference:
  case serial_atom::array:
    return WireType::LenDelimit;
  case serial_atom::string:
    return WireType::LenDelimit;
  case serial_atom::map:
    break;
  case serial_atom::descriptor:
    return WireType::LenDelimit;
  case serial_atom::finalized_descriptor:
    break;
  case serial_atom::ignored:
    throw std::invalid_argument("serial_atom::ignored is a utility type and should not be used in ordinary operations");
  }
  throw std::invalid_argument("Attempted to find a wire type for an unrecognized serial atom type");
}

const char* leap::internal::protobuf::ToProtobufField(serial_atom atom) {
  switch (atom) {
  case serial_atom::boolean:
    return "bool";
  case serial_atom::i8:
  case serial_atom::i16:
  case serial_atom::i32:
    return "sint32";
  case serial_atom::i64:
    return "sint64";
  case serial_atom::ui8:
  case serial_atom::ui16:
  case serial_atom::ui32:
    return "int32";
  case serial_atom::ui64:
    return "int64";
  case serial_atom::f32:
    return "float";
  case serial_atom::f64:
  case serial_atom::f80:
    return "double";
  case serial_atom::reference:
    break;
  case serial_atom::array:
  case serial_atom::string:
    return "string";
  case serial_atom::map:
    break;
  case serial_atom::descriptor:
  case serial_atom::finalized_descriptor:
    break;
  case serial_atom::ignored:
    throw std::invalid_argument("Invalid serial atom type");
  }
  throw std::invalid_argument("Attempted to obtain the protobuf field of a non-value type");
}

static std::string FormatError(const descriptor& descriptor) {
  std::stringstream ss;
  ss << "The OArchiveProtobuf requires that all entries have identifiers" << std::endl
    << "Fields at the following offsets do not have identifiers:" << std::endl;
  for (const auto& field_descriptor : descriptor.field_descriptors)
    ss << "[ " << std::left << std::setw(8) << ToString(field_descriptor.serializer.type()) << " ] @+" << field_descriptor.offset << std::endl;
  return ss.str();
}

internal::protobuf::serialization_error::serialization_error(std::string&& err) :
  ::leap::serialization_error(std::move(err))
{}

internal::protobuf::serialization_error::serialization_error(const descriptor& descriptor) :
  ::leap::serialization_error(FormatError(descriptor))
{}
<commit_msg>Add missing `f80` case statement<commit_after>// Copyright (C) 2012-2015 Leap Motion, Inc. All rights reserved.
#include "stdafx.h"
#include "ProtobufUtil.hpp"
#include "Archive.h"
#include "Descriptor.h"
#include <iomanip>
#include <sstream>

using namespace leap;
using leap::internal::protobuf::WireType;

WireType leap::internal::protobuf::ToWireType(serial_atom atom) {
  switch (atom) {
  case serial_atom::boolean:
  case serial_atom::i8:
  case serial_atom::ui8:
  case serial_atom::i16:
  case serial_atom::ui16:
  case serial_atom::i32:
  case serial_atom::ui32:
  case serial_atom::i64:
  case serial_atom::ui64:
    return WireType::Varint;
  case serial_atom::f32:
    return WireType::DoubleWord;
  case serial_atom::f64:
  case serial_atom::f80:
    return WireType::QuadWord;
  case serial_atom::reference:
  case serial_atom::array:
    return WireType::LenDelimit;
  case serial_atom::string:
    return WireType::LenDelimit;
  case serial_atom::map:
    break;
  case serial_atom::descriptor:
    return WireType::LenDelimit;
  case serial_atom::finalized_descriptor:
    break;
  case serial_atom::ignored:
    throw std::invalid_argument("serial_atom::ignored is a utility type and should not be used in ordinary operations");
  }
  throw std::invalid_argument("Attempted to find a wire type for an unrecognized serial atom type");
}

const char* leap::internal::protobuf::ToProtobufField(serial_atom atom) {
  switch (atom) {
  case serial_atom::boolean:
    return "bool";
  case serial_atom::i8:
  case serial_atom::i16:
  case serial_atom::i32:
    return "sint32";
  case serial_atom::i64:
    return "sint64";
  case serial_atom::ui8:
  case serial_atom::ui16:
  case serial_atom::ui32:
    return "int32";
  case serial_atom::ui64:
    return "int64";
  case serial_atom::f32:
    return "float";
  case serial_atom::f64:
  case serial_atom::f80:
    return "double";
  case serial_atom::reference:
    break;
  case serial_atom::array:
  case serial_atom::string:
    return "string";
  case serial_atom::map:
    break;
  case serial_atom::descriptor:
  case serial_atom::finalized_descriptor:
    break;
  case serial_atom::ignored:
    throw std::invalid_argument("Invalid serial atom type");
  }
  throw std::invalid_argument("Attempted to obtain the protobuf field of a non-value type");
}

static std::string FormatError(const descriptor& descriptor) {
  std::stringstream ss;
  ss << "The OArchiveProtobuf requires that all entries have identifiers" << std::endl
    << "Fields at the following offsets do not have identifiers:" << std::endl;
  for (const auto& field_descriptor : descriptor.field_descriptors)
    ss << "[ " << std::left << std::setw(8) << ToString(field_descriptor.serializer.type()) << " ] @+" << field_descriptor.offset << std::endl;
  return ss.str();
}

internal::protobuf::serialization_error::serialization_error(std::string&& err) :
  ::leap::serialization_error(std::move(err))
{}

internal::protobuf::serialization_error::serialization_error(const descriptor& descriptor) :
  ::leap::serialization_error(FormatError(descriptor))
{}
<|endoftext|>


<commit_before>// The libMesh Finite Element Library.
// Copyright (C) 2002-2016 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner

// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// C++ inlcludes

// Local includes
#include "libmesh/fe.h"
#include "libmesh/elem.h"
#include "libmesh/utility.h"

namespace
{
using namespace libMesh;

// Compute the static coefficients for an element
void hermite_compute_coefs(const Elem * elem, Real & d1xd1x, Real & d2xd2x)
{
  const Order mapping_order        (elem->default_order());
  const ElemType mapping_elem_type (elem->type());
  const int n_mapping_shape_functions =
    FE<1,LAGRANGE>::n_shape_functions(mapping_elem_type,
                                      mapping_order);

  // Degrees of freedom are at vertices and edge midpoints
  std::vector<Point> dofpt;
  dofpt.push_back(Point(-1));
  dofpt.push_back(Point(1));

  // Mapping functions - first derivatives at each dofpt
  std::vector<Real> dxdxi(2);
  std::vector<Real> dxidx(2);

  for (int p = 0; p != 2; ++p)
    {
      dxdxi[p] = 0;
      for (int i = 0; i != n_mapping_shape_functions; ++i)
        {
          const Real ddxi = FE<1,LAGRANGE>::shape_deriv
            (mapping_elem_type, mapping_order, i, 0, dofpt[p]);
          dxdxi[p] += elem->point(i)(0) * ddxi;
        }
    }

  // Calculate derivative scaling factors

  d1xd1x = dxdxi[0];
  d2xd2x = dxdxi[1];
}

} // end anonymous namespace

namespace libMesh
{

template<>
Real FEHermite<1>::hermite_raw_shape_second_deriv (const unsigned int i, const Real xi)
{
  using Utility::pow;

  switch (i)
    {
    case 0:
      return 1.5 * xi;
    case 1:
      return -1.5 * xi;
    case 2:
      return 0.5 * (-1. + 3.*xi);
    case 3:
      return 0.5 * (1. + 3.*xi);
    case 4:
      return (8.*xi*xi + 4.*(xi*xi-1.))/24.;
    case 5:
      return (8.*xi*xi*xi + 12.*xi*(xi*xi-1.))/120.;
      //      case 6:
      //        return (8.*pow<4>(xi) + 20.*xi*xi*(xi*xi-1.) +
      //          2.*(xi*xi-1)*(xi*xi-1))/720.;
    default:
      Real denominator = 720., xipower = 1.;
      for (unsigned n=6; n != i; ++n)
        {
          xipower *= xi;
          denominator *= (n+1);
        }
      return (8.*pow<4>(xi)*xipower +
              (8.*(i-4)+4.)*xi*xi*xipower*(xi*xi-1.) +
              (i-4)*(i-5)*xipower*(xi*xi-1.)*(xi*xi-1.))/denominator;
    }

  libmesh_error_msg("We'll never get here!");
  return 0.;
}

template<>
Real FEHermite<1>::hermite_raw_shape_deriv(const unsigned int i, const Real xi)
{
  switch (i)
    {
    case 0:
      return 0.75 * (-1. + xi*xi);
    case 1:
      return 0.75 * (1. - xi*xi);
    case 2:
      return 0.25 * (-1. - 2.*xi + 3.*xi*xi);
    case 3:
      return 0.25 * (-1. + 2.*xi + 3.*xi*xi);
    case 4:
      return 4.*xi * (xi*xi-1.)/24.;
    case 5:
      return (4*xi*xi*(xi*xi-1.) + (xi*xi-1.)*(xi*xi-1.))/120.;
      //      case 6:
      //        return (4*xi*xi*xi*(xi*xi-1.) + 2*xi*(xi*xi-1.)*(xi*xi-1.))/720.;
    default:
      Real denominator = 720., xipower = 1.;
      for (unsigned n=6; n != i; ++n)
        {
          xipower *= xi;
          denominator *= (n+1);
        }
      return (4*xi*xi*xi*xipower*(xi*xi-1.) +
              (i-4)*xi*xipower*(xi*xi-1.)*(xi*xi-1.))/denominator;
    }

  libmesh_error_msg("We'll never get here!");
  return 0.;
}

template<>
Real FEHermite<1>::hermite_raw_shape(const unsigned int i, const Real xi)
{
  switch (i)
    {
    case 0:
      return 0.25 * (2. - 3.*xi + xi*xi*xi);
    case 1:
      return 0.25 * (2. + 3.*xi - xi*xi*xi);
    case 2:
      return 0.25 * (1. - xi - xi*xi + xi*xi*xi);
    case 3:
      return 0.25 * (-1. - xi + xi*xi + xi*xi*xi);
      // All high order terms have the form x^(p-4)(x^2-1)^2/p!
    case 4:
      return (xi*xi-1.) * (xi*xi-1.)/24.;
    case 5:
      return xi * (xi*xi-1.) * (xi*xi-1.)/120.;
      //      case 6:
      //        return xi*xi * (xi*xi-1.) * (xi*xi-1.)/720.;
    default:
      Real denominator = 720., xipower = 1.;
      for (unsigned n=6; n != i; ++n)
        {
          xipower *= xi;
          denominator *= (n+1);
        }
      return (xi*xi*xipower*(xi*xi-1.)*(xi*xi-1.))/denominator;

    }

  libmesh_error_msg("We'll never get here!");
  return 0.;
}

template <>
Real FE<1,HERMITE>::shape(const ElemType,
                          const Order,
                          const unsigned int,
                          const Point &)
{
  libmesh_error_msg("Hermite elements require the real element \nto construct gradient-based degrees of freedom.");
  return 0.;
}

template <>
Real FE<1,HERMITE>::shape(const Elem * elem,
                          const Order order,
                          const unsigned int i,
                          const Point & p)
{
  libmesh_assert(elem);

  // Coefficient naming: d(1)d(2n) is the coefficient of the
  // global shape function corresponding to value 1 in terms of the
  // local shape function corresponding to normal derivative 2
  Real d1xd1x, d2xd2x;

  hermite_compute_coefs(elem, d1xd1x, d2xd2x);

  const ElemType type = elem->type();

  const Order totalorder = static_cast<Order>(order + elem->p_level());

  switch (totalorder)
    {
      // Hermite cubic shape functions
    case THIRD:
      {
        switch (type)
          {
            // C1 functions on the C1 cubic edge
          case EDGE2:
          case EDGE3:
            {
              libmesh_assert_less (i, 4);

              switch (i)
                {
                case 0:
                  return FEHermite<1>::hermite_raw_shape(0, p(0));
                case 1:
                  return d1xd1x * FEHermite<1>::hermite_raw_shape(2, p(0));
                case 2:
                  return FEHermite<1>::hermite_raw_shape(1, p(0));
                case 3:
                  return d2xd2x * FEHermite<1>::hermite_raw_shape(3, p(0));
                default:
                  return FEHermite<1>::hermite_raw_shape(i, p(0));
                }
            }
          default:
            libmesh_error_msg("ERROR: Unsupported element type = " << type);
          }
      }
      // by default throw an error
    default:
      libmesh_error_msg("ERROR: Unsupported polynomial order = " << totalorder);
    }

  libmesh_error_msg("We'll never get here!");
  return 0.;
}

template <>
Real FE<1,HERMITE>::shape_deriv(const ElemType,
                                const Order,
                                const unsigned int,
                                const unsigned int,
                                const Point &)
{
  libmesh_error_msg("Hermite elements require the real element \nto construct gradient-based degrees of freedom.");
  return 0.;
}

template <>
Real FE<1,HERMITE>::shape_deriv(const Elem * elem,
                                const Order order,
                                const unsigned int i,
                                const unsigned int,
                                const Point & p)
{
  libmesh_assert(elem);

  // Coefficient naming: d(1)d(2n) is the coefficient of the
  // global shape function corresponding to value 1 in terms of the
  // local shape function corresponding to normal derivative 2
  Real d1xd1x, d2xd2x;

  hermite_compute_coefs(elem, d1xd1x, d2xd2x);

  const ElemType type = elem->type();

  const Order totalorder = static_cast<Order>(order + elem->p_level());

  switch (totalorder)
    {
      // Hermite cubic shape functions
    case THIRD:
      {
        switch (type)
          {
            // C1 functions on the C1 cubic edge
          case EDGE2:
          case EDGE3:
            {
              switch (i)
                {
                case 0:
                  return FEHermite<1>::hermite_raw_shape_deriv(0, p(0));
                case 1:
                  return d1xd1x * FEHermite<1>::hermite_raw_shape_deriv(2, p(0));
                case 2:
                  return FEHermite<1>::hermite_raw_shape_deriv(1, p(0));
                case 3:
                  return d2xd2x * FEHermite<1>::hermite_raw_shape_deriv(3, p(0));
                default:
                  return FEHermite<1>::hermite_raw_shape_deriv(i, p(0));
                }
            }
          default:
            libmesh_error_msg("ERROR: Unsupported element type = " << type);
          }
      }
      // by default throw an error
    default:
      libmesh_error_msg("ERROR: Unsupported polynomial order = " << totalorder);
    }

  libmesh_error_msg("We'll never get here!");
  return 0.;
}

template <>
Real FE<1,HERMITE>::shape_second_deriv(const Elem * elem,
                                       const Order order,
                                       const unsigned int i,
                                       const unsigned int,
                                       const Point & p)
{
  libmesh_assert(elem);

  // Coefficient naming: d(1)d(2n) is the coefficient of the
  // global shape function corresponding to value 1 in terms of the
  // local shape function corresponding to normal derivative 2
  Real d1xd1x, d2xd2x;

  hermite_compute_coefs(elem, d1xd1x, d2xd2x);

  const ElemType type = elem->type();

  const Order totalorder = static_cast<Order>(order + elem->p_level());

  switch (totalorder)
    {
      // Hermite cubic shape functions
    case THIRD:
      {
        switch (type)
          {
            // C1 functions on the C1 cubic edge
          case EDGE2:
          case EDGE3:
            {
              switch (i)
                {
                case 0:
                  return FEHermite<1>::hermite_raw_shape_second_deriv(0, p(0));
                case 1:
                  return d1xd1x * FEHermite<1>::hermite_raw_shape_second_deriv(2, p(0));
                case 2:
                  return FEHermite<1>::hermite_raw_shape_second_deriv(1, p(0));
                case 3:
                  return d2xd2x * FEHermite<1>::hermite_raw_shape_second_deriv(3, p(0));
                default:
                  return FEHermite<1>::hermite_raw_shape_second_deriv(i, p(0));
                }
            }
          default:
            libmesh_error_msg("ERROR: Unsupported element type = " << type);
          }
      }
      // by default throw an error
    default:
      libmesh_error_msg("ERROR: Unsupported polynomial order = " << totalorder);
    }

  libmesh_error_msg("We'll never get here!");
  return 0.;
}

} // namespace libMesh
<commit_msg>Enable 1D HERMITE elements of arbitrary p<commit_after>// The libMesh Finite Element Library.
// Copyright (C) 2002-2016 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner

// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// C++ inlcludes

// Local includes
#include "libmesh/fe.h"
#include "libmesh/elem.h"
#include "libmesh/utility.h"

namespace
{
using namespace libMesh;

// Compute the static coefficients for an element
void hermite_compute_coefs(const Elem * elem, Real & d1xd1x, Real & d2xd2x)
{
  const Order mapping_order        (elem->default_order());
  const ElemType mapping_elem_type (elem->type());
  const int n_mapping_shape_functions =
    FE<1,LAGRANGE>::n_shape_functions(mapping_elem_type,
                                      mapping_order);

  // Degrees of freedom are at vertices and edge midpoints
  std::vector<Point> dofpt;
  dofpt.push_back(Point(-1));
  dofpt.push_back(Point(1));

  // Mapping functions - first derivatives at each dofpt
  std::vector<Real> dxdxi(2);
  std::vector<Real> dxidx(2);

  for (int p = 0; p != 2; ++p)
    {
      dxdxi[p] = 0;
      for (int i = 0; i != n_mapping_shape_functions; ++i)
        {
          const Real ddxi = FE<1,LAGRANGE>::shape_deriv
            (mapping_elem_type, mapping_order, i, 0, dofpt[p]);
          dxdxi[p] += elem->point(i)(0) * ddxi;
        }
    }

  // Calculate derivative scaling factors

  d1xd1x = dxdxi[0];
  d2xd2x = dxdxi[1];
}

} // end anonymous namespace

namespace libMesh
{

template<>
Real FEHermite<1>::hermite_raw_shape_second_deriv (const unsigned int i, const Real xi)
{
  using Utility::pow;

  switch (i)
    {
    case 0:
      return 1.5 * xi;
    case 1:
      return -1.5 * xi;
    case 2:
      return 0.5 * (-1. + 3.*xi);
    case 3:
      return 0.5 * (1. + 3.*xi);
    case 4:
      return (8.*xi*xi + 4.*(xi*xi-1.))/24.;
    case 5:
      return (8.*xi*xi*xi + 12.*xi*(xi*xi-1.))/120.;
      //      case 6:
      //        return (8.*pow<4>(xi) + 20.*xi*xi*(xi*xi-1.) +
      //          2.*(xi*xi-1)*(xi*xi-1))/720.;
    default:
      Real denominator = 720., xipower = 1.;
      for (unsigned n=6; n != i; ++n)
        {
          xipower *= xi;
          denominator *= (n+1);
        }
      return (8.*pow<4>(xi)*xipower +
              (8.*(i-4)+4.)*xi*xi*xipower*(xi*xi-1.) +
              (i-4)*(i-5)*xipower*(xi*xi-1.)*(xi*xi-1.))/denominator;
    }

  libmesh_error_msg("We'll never get here!");
  return 0.;
}

template<>
Real FEHermite<1>::hermite_raw_shape_deriv(const unsigned int i, const Real xi)
{
  switch (i)
    {
    case 0:
      return 0.75 * (-1. + xi*xi);
    case 1:
      return 0.75 * (1. - xi*xi);
    case 2:
      return 0.25 * (-1. - 2.*xi + 3.*xi*xi);
    case 3:
      return 0.25 * (-1. + 2.*xi + 3.*xi*xi);
    case 4:
      return 4.*xi * (xi*xi-1.)/24.;
    case 5:
      return (4*xi*xi*(xi*xi-1.) + (xi*xi-1.)*(xi*xi-1.))/120.;
      //      case 6:
      //        return (4*xi*xi*xi*(xi*xi-1.) + 2*xi*(xi*xi-1.)*(xi*xi-1.))/720.;
    default:
      Real denominator = 720., xipower = 1.;
      for (unsigned n=6; n != i; ++n)
        {
          xipower *= xi;
          denominator *= (n+1);
        }
      return (4*xi*xi*xi*xipower*(xi*xi-1.) +
              (i-4)*xi*xipower*(xi*xi-1.)*(xi*xi-1.))/denominator;
    }

  libmesh_error_msg("We'll never get here!");
  return 0.;
}

template<>
Real FEHermite<1>::hermite_raw_shape(const unsigned int i, const Real xi)
{
  switch (i)
    {
    case 0:
      return 0.25 * (2. - 3.*xi + xi*xi*xi);
    case 1:
      return 0.25 * (2. + 3.*xi - xi*xi*xi);
    case 2:
      return 0.25 * (1. - xi - xi*xi + xi*xi*xi);
    case 3:
      return 0.25 * (-1. - xi + xi*xi + xi*xi*xi);
      // All high order terms have the form x^(p-4)(x^2-1)^2/p!
    case 4:
      return (xi*xi-1.) * (xi*xi-1.)/24.;
    case 5:
      return xi * (xi*xi-1.) * (xi*xi-1.)/120.;
      //      case 6:
      //        return xi*xi * (xi*xi-1.) * (xi*xi-1.)/720.;
    default:
      Real denominator = 720., xipower = 1.;
      for (unsigned n=6; n != i; ++n)
        {
          xipower *= xi;
          denominator *= (n+1);
        }
      return (xi*xi*xipower*(xi*xi-1.)*(xi*xi-1.))/denominator;

    }

  libmesh_error_msg("We'll never get here!");
  return 0.;
}

template <>
Real FE<1,HERMITE>::shape(const ElemType,
                          const Order,
                          const unsigned int,
                          const Point &)
{
  libmesh_error_msg("Hermite elements require the real element \nto construct gradient-based degrees of freedom.");
  return 0.;
}

template <>
Real FE<1,HERMITE>::shape(const Elem * elem,
                          const Order order,
                          const unsigned int i,
                          const Point & p)
{
  libmesh_assert(elem);

  // Coefficient naming: d(1)d(2n) is the coefficient of the
  // global shape function corresponding to value 1 in terms of the
  // local shape function corresponding to normal derivative 2
  Real d1xd1x, d2xd2x;

  hermite_compute_coefs(elem, d1xd1x, d2xd2x);

  const ElemType type = elem->type();

#ifndef NDEBUG
  const unsigned int totalorder = order + elem->p_level();
#endif

  switch (type)
    {
      // C1 functions on the C1 cubic edge
    case EDGE2:
    case EDGE3:
      {
        libmesh_assert_less (i, totalorder+1);

        switch (i)
          {
          case 0:
            return FEHermite<1>::hermite_raw_shape(0, p(0));
          case 1:
            return d1xd1x * FEHermite<1>::hermite_raw_shape(2, p(0));
          case 2:
            return FEHermite<1>::hermite_raw_shape(1, p(0));
          case 3:
            return d2xd2x * FEHermite<1>::hermite_raw_shape(3, p(0));
          default:
            return FEHermite<1>::hermite_raw_shape(i, p(0));
          }
      }
    default:
      libmesh_error_msg("ERROR: Unsupported element type = " << type);
    }

  libmesh_error_msg("We'll never get here!");
  return 0.;
}

template <>
Real FE<1,HERMITE>::shape_deriv(const ElemType,
                                const Order,
                                const unsigned int,
                                const unsigned int,
                                const Point &)
{
  libmesh_error_msg("Hermite elements require the real element \nto construct gradient-based degrees of freedom.");
  return 0.;
}

template <>
Real FE<1,HERMITE>::shape_deriv(const Elem * elem,
                                const Order order,
                                const unsigned int i,
                                const unsigned int,
                                const Point & p)
{
  libmesh_assert(elem);

  // Coefficient naming: d(1)d(2n) is the coefficient of the
  // global shape function corresponding to value 1 in terms of the
  // local shape function corresponding to normal derivative 2
  Real d1xd1x, d2xd2x;

  hermite_compute_coefs(elem, d1xd1x, d2xd2x);

  const ElemType type = elem->type();

#ifndef NDEBUG
  const unsigned int totalorder = order + elem->p_level();
#endif

  switch (type)
    {
      // C1 functions on the C1 cubic edge
    case EDGE2:
    case EDGE3:
      {
        libmesh_assert_less (i, totalorder+1);

        switch (i)
          {
          case 0:
            return FEHermite<1>::hermite_raw_shape_deriv(0, p(0));
          case 1:
            return d1xd1x * FEHermite<1>::hermite_raw_shape_deriv(2, p(0));
          case 2:
            return FEHermite<1>::hermite_raw_shape_deriv(1, p(0));
          case 3:
            return d2xd2x * FEHermite<1>::hermite_raw_shape_deriv(3, p(0));
          default:
            return FEHermite<1>::hermite_raw_shape_deriv(i, p(0));
          }
      }
    default:
      libmesh_error_msg("ERROR: Unsupported element type = " << type);
    }

  libmesh_error_msg("We'll never get here!");
  return 0.;
}

template <>
Real FE<1,HERMITE>::shape_second_deriv(const Elem * elem,
                                       const Order order,
                                       const unsigned int i,
                                       const unsigned int,
                                       const Point & p)
{
  libmesh_assert(elem);

  // Coefficient naming: d(1)d(2n) is the coefficient of the
  // global shape function corresponding to value 1 in terms of the
  // local shape function corresponding to normal derivative 2
  Real d1xd1x, d2xd2x;

  hermite_compute_coefs(elem, d1xd1x, d2xd2x);

  const ElemType type = elem->type();

#ifndef NDEBUG
  const unsigned int totalorder = order + elem->p_level();
#endif

  switch (type)
    {
      // C1 functions on the C1 cubic edge
    case EDGE2:
    case EDGE3:
      {
        libmesh_assert_less (i, totalorder+1);

        switch (i)
          {
          case 0:
            return FEHermite<1>::hermite_raw_shape_second_deriv(0, p(0));
          case 1:
            return d1xd1x * FEHermite<1>::hermite_raw_shape_second_deriv(2, p(0));
          case 2:
            return FEHermite<1>::hermite_raw_shape_second_deriv(1, p(0));
          case 3:
            return d2xd2x * FEHermite<1>::hermite_raw_shape_second_deriv(3, p(0));
          default:
            return FEHermite<1>::hermite_raw_shape_second_deriv(i, p(0));
          }
      }
    default:
      libmesh_error_msg("ERROR: Unsupported element type = " << type);
    }

  libmesh_error_msg("We'll never get here!");
  return 0.;
}

} // namespace libMesh
<|endoftext|>