<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2021.  All rights reserved
 */
#include "Stroika/Frameworks/StroikaPreComp.h"

#include <iostream>

#include "Stroika/Foundation/Characters/FloatConversion.h"
#include "Stroika/Foundation/Characters/String2Int.h"
#include "Stroika/Foundation/Characters/ToString.h"
#include "Stroika/Foundation/DataExchange/InternetMediaTypeRegistry.h"
#include "Stroika/Foundation/IO/Network/HTTP/Exception.h"
#include "Stroika/Foundation/IO/Network/HTTP/Headers.h"
#include "Stroika/Foundation/IO/Network/HTTP/Methods.h"
#include "Stroika/Foundation/Streams/TextReader.h"

#include "Stroika/Frameworks/WebServer/ConnectionManager.h"
#include "Stroika/Frameworks/WebServer/Router.h"
#include "Stroika/Frameworks/WebService/Server/Basic.h"
#include "Stroika/Frameworks/WebService/Server/VariantValue.h"

#include "WebServer.h"

#include "AppVersion.h"

using namespace std;

using namespace Stroika::Foundation;
using namespace Stroika::Foundation::Characters;
using namespace Stroika::Foundation::IO::Network;
using namespace Stroika::Foundation::IO::Network::HTTP;
using namespace Stroika::Frameworks::WebServer;
using namespace Stroika::Frameworks::WebService;
using namespace Stroika::Frameworks::WebService::Server;
using namespace Stroika::Frameworks::WebService::Server::VariantValue;

using Memory::BLOB;

using namespace StroikaSample::WebServices;

/*
 *  It's often helpful to structure together, routes, special interceptors, with your connection manager, to package up
 *  all the logic /options for HTTP interface.
 *
 *  This particular organization also makes it easy to save instance variables with the webserver (like a pointer to a handler)
 *  and accesss them from the Route handler functions.
 */
class WebServer::Rep_ {
public:
    const Sequence<Route> kRoutes_;        // rules saying how to map urls to code
    shared_ptr<IWSAPI>    fWSImpl_;        // application logic actually handling webservices
    ConnectionManager     fConnectionMgr_; // manage http connection objects, thread pool, etc

    static const WebServiceMethodDescription kVariables_;

    static const WebServiceMethodDescription kPlus_;
    static const WebServiceMethodDescription kMinus;
    static const WebServiceMethodDescription kTimes;
    static const WebServiceMethodDescription kDivide;

    Rep_ (uint16_t portNumber, const shared_ptr<IWSAPI>& wsImpl)
        : kRoutes_{
              Route{L""_RegEx, DefaultPage_},

              Route{MethodsRegEx::kPost, L"SetAppState"_RegEx, SetAppState_},

              Route{L"FRED"_RegEx, [] (Request*, Response* response) {
                        response->write (L"FRED");
                        response->SetContentType (DataExchange::InternetMediaTypes::kText_PLAIN);
                    }},

              /*
               * the 'variable' API demonstrates a typical REST style CRUD usage - where the 'arguments' mainly come from
               * the URL itself.
               */
              Route{L"variables(/?)"_RegEx, [this] (Message* m) {
                        WriteResponse (&m->rwResponse (), kVariables_, kMapper.FromObject (fWSImpl_->Variables_GET ()));
                    }},
              Route{L"variables/(.+)"_RegEx, [this] (Message* m, const String& varName) {
                        WriteResponse (&m->rwResponse (), kVariables_, kMapper.FromObject (fWSImpl_->Variables_GET (varName)));
                    }},
              Route{MethodsRegEx::kPostOrPut, L"variables/(.+)"_RegEx, [this] (Message* m, const String& varName) {
                        optional<Number> number;
                        // demo getting argument from the body
                        if (not number) {
                            // read if content-type is text (not json)
                            if (m->request ().contentType () and DataExchange::InternetMediaTypeRegistry::Get ().IsA (DataExchange::InternetMediaTypes::kText_PLAIN, *m->request ().contentType ())) {
                                String argsAsString = Streams::TextReader::New (m->rwRequest ().GetBody ()).ReadAll ();
                                number              = kMapper.ToObject<Number> (DataExchange::VariantValue (argsAsString));
                            }
                        }
                        // demo getting argument from the query argument
                        if (not number) {
                            static const String                         kValueParamName_ = L"value"sv;
                            Mapping<String, DataExchange::VariantValue> args             = PickoutParamValuesFromURL (&m->request ());
                            number                                                       = Model::kMapper.ToObject<Number> (args.LookupValue (kValueParamName_));
                        }
                        // demo getting either query arg, or url encoded arg
                        if (not number) {
                            static const String kValueParamName_ = L"value"sv;
                            // NOTE - PickoutParamValues combines PickoutParamValuesFromURL, and PickoutParamValuesFromBody. You can use
                            // Either one of those instead. PickoutParamValuesFromURL assumes you know the name of the parameter, and its
                            // encoded in the query string. PickoutParamValuesFromBody assumes you have something equivilent you can parse ouf
                            // of the body, either json encoded or form-encoded (as of 2.1d23, only json encoded supported)
                            Mapping<String, DataExchange::VariantValue> args = PickoutParamValues (&m->rwRequest ());
                            number                                           = Model::kMapper.ToObject<Number> (args.LookupValue (kValueParamName_));
                        }
                        if (not number) {
                            Execution::Throw (ClientErrorException{L"Expected argument to PUT/POST variable"sv});
                        }
                        fWSImpl_->Variables_SET (varName, *number);
                        WriteResponse (&m->rwResponse (), kVariables_);
                    }},
              Route{MethodsRegEx::kDelete, L"variables/(.+)"_RegEx, [this] (Message* m, const String& varName) {
                        fWSImpl_->Variables_DELETE (varName);
                        WriteResponse (&m->rwResponse (), kVariables_);
                    }},

              /*
               *    plus, minus, times, and divide, test-void-return all all demonstrate passing in variables through either the POST body, or query-arguments.
               */
              Route{L"plus"_RegEx, mkRequestHandler (kPlus_, Model::kMapper, Traversal::Iterable<String>{L"arg1", L"arg2"}, function<Number (Number, Number)>{[this] (Number arg1, Number arg2) { return fWSImpl_->plus (arg1, arg2); }})},
              Route{L"minus"_RegEx, mkRequestHandler (kMinus, Model::kMapper, Traversal::Iterable<String>{L"arg1", L"arg2"}, function<Number (Number, Number)>{[this] (Number arg1, Number arg2) { return fWSImpl_->minus (arg1, arg2); }})},
              Route{L"times"_RegEx, mkRequestHandler (kTimes, Model::kMapper, Traversal::Iterable<String>{L"arg1", L"arg2"}, function<Number (Number, Number)>{[this] (Number arg1, Number arg2) { return fWSImpl_->times (arg1, arg2); }})},
              Route{L"divide"_RegEx, mkRequestHandler (kDivide, Model::kMapper, Traversal::Iterable<String>{L"arg1", L"arg2"}, function<Number (Number, Number)>{[this] (Number arg1, Number arg2) { return fWSImpl_->divide (arg1, arg2); }})},
              Route{L"test-void-return"_RegEx, mkRequestHandler (WebServiceMethodDescription{}, Model::kMapper, Traversal::Iterable<String>{L"err-if-more-than-10"}, function<void (double)>{[] (double check) {
                                    if (check > 10) {
                                        Execution::Throw (Execution::Exception (L"more than 10"sv));
                                    } }})},

          }
        , fWSImpl_
    {
        wsImpl
    }
#if __cpp_designated_initializers
    , fConnectionMgr_
    {
        SocketAddresses (InternetAddresses_Any (), portNumber), kRoutes_, ConnectionManager::Options { .fBindFlags = Socket::BindFlags{}, .fServerHeader = L"Stroika-Sample-WebServices/"_k + AppVersion::kVersion.AsMajorMinorString () }
    }
#else
    , fConnectionMgr_
    {
        SocketAddresses (InternetAddresses_Any (), portNumber), kRoutes_, ConnectionManager::Options { nullopt, nullopt, Socket::BindFlags{}, L"Stroika-Sample-WebServices/"_k + AppVersion::kVersion.AsMajorMinorString () }
    }
#endif
    {
        // @todo - move this to some framework-specific regtests...
        using VariantValue         = DataExchange::VariantValue;
        Sequence<VariantValue> tmp = OrderParamValues (Iterable<String>{L"page", L"xxx"}, PickoutParamValuesFromURL (URI{L"http://www.sophist.com?page=5"}));
        Assert (tmp.size () == 2);
        Assert (tmp[0] == 5);
        Assert (tmp[1] == nullptr);
    }
    // Can declare arguments as Request*,Response*
    static void DefaultPage_ (Request*, Response* response)
    {
        WriteDocsPage (
            response,
            Sequence<WebServiceMethodDescription>{
                kVariables_,
                kPlus_,
                kMinus,
                kTimes,
                kDivide,
            },
            DocsOptions{L"Stroika Sample WebService - Web Methods"_k});
    }
    static void SetAppState_ (Message* message)
    {
        String argsAsString = Streams::TextReader::New (message->rwRequest ().GetBody ()).ReadAll ();
        message->rwResponse ().writeln (L"
Hi SetAppState (" + argsAsString.As<wstring> () + L")
");
        message->rwResponse ().SetContentType (DataExchange::InternetMediaTypes::kHTML);
    }
};

/*
 *  Documentation on WSAPIs
 */
const WebServiceMethodDescription WebServer::Rep_::kVariables_{
    L"variables"_k,
    Set<String>{Methods::kGet, Methods::kPost, Methods::kDelete},
    DataExchange::InternetMediaTypes::kJSON,
    {},
    Sequence<String>{
        L"curl http://localhost:8080/variables -v --output -",
        L"curl http://localhost:8080/variables/x -v --output -",
        L"curl  -X POST http://localhost:8080/variables/x -v --output -",
        L"curl -H \"Content-Type: application/json\" -X POST -d '{\"value\": 3}' http://localhost:8080/variables/x --output -",
        L"curl -H \"Content-Type: text/plain\" -X POST -d '3' http://localhost:8080/variables/x --output -"},
    Sequence<String>{L"@todo - this is a rough draft (but functional). It could use alot of cleanup and review to see WHICH way I recommend using, and just provide the recommended ways in samples"},
};

const WebServiceMethodDescription WebServer::Rep_::kPlus_{
    L"plus"_k,
    Set<String>{Methods::kPost},
    DataExchange::InternetMediaTypes::kJSON,
    {},
    Sequence<String>{
        L"curl -H \"Content-Type: application/json\" -X POST -d '{\"arg1\": 3, \"arg2\": 5 }' http://localhost:8080/plus --output -",
    },
    Sequence<String>{L"add the two argument numbers"},
};
const WebServiceMethodDescription WebServer::Rep_::kMinus{
    L"minus"_k,
    Set<String>{Methods::kPost},
    DataExchange::InternetMediaTypes::kJSON,
    {},
    Sequence<String>{
        L"curl -H \"Content-Type: application/json\" -X POST -d '{\"arg1\": 4.5, \"arg2\": -3.23 }' http://localhost:8080/minus --output -",
    },
    Sequence<String>{L"subtract the two argument numbers"},
};
const WebServiceMethodDescription WebServer::Rep_::kTimes{
    L"times"_k,
    Set<String>{Methods::kPost},
    DataExchange::InternetMediaTypes::kJSON,
    {},
    Sequence<String>{
        L"curl -H \"Content-Type: application/json\" -X POST -d '{\"arg1\":\"2 + 4i\", \"arg2\": 3.2 }' http://localhost:8080/times --output -",
        L"curl -H \"Content-Type: application/json\" -X POST -d '{\"arg1\":\"2 + i\", \"arg2\": \"2 - i\" }' http://localhost:8080/times --output -",
    },
    Sequence<String>{L"multiply the two argument numbers"},
};
const WebServiceMethodDescription WebServer::Rep_::kDivide{
    L"divide"_k,
    Set<String>{Methods::kPost},
    DataExchange::InternetMediaTypes::kJSON,
    {},
    Sequence<String>{
        L"curl -H \"Content-Type: application/json\" -X POST -d '{\"arg1\":\"2 + i\", \"arg2\": 0 }' http://localhost:8080/divide --output -",
    },
    Sequence<String>{L"divide the two argument numbers"},
};

WebServer::WebServer (uint16_t portNumber, const shared_ptr<IWSAPI>& wsImpl)
    : fRep_ (make_shared<Rep_> (portNumber, wsImpl))
{
}
<commit_msg>minor cleanups<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2021.  All rights reserved
 */
#include "Stroika/Frameworks/StroikaPreComp.h"

#include <iostream>

#include "Stroika/Foundation/Characters/FloatConversion.h"
#include "Stroika/Foundation/Characters/String2Int.h"
#include "Stroika/Foundation/Characters/ToString.h"
#include "Stroika/Foundation/DataExchange/InternetMediaTypeRegistry.h"
#include "Stroika/Foundation/IO/Network/HTTP/Exception.h"
#include "Stroika/Foundation/IO/Network/HTTP/Headers.h"
#include "Stroika/Foundation/IO/Network/HTTP/Methods.h"
#include "Stroika/Foundation/Streams/TextReader.h"

#include "Stroika/Frameworks/WebServer/ConnectionManager.h"
#include "Stroika/Frameworks/WebServer/Router.h"
#include "Stroika/Frameworks/WebService/Server/Basic.h"
#include "Stroika/Frameworks/WebService/Server/VariantValue.h"

#include "WebServer.h"

#include "AppVersion.h"

using namespace std;

using namespace Stroika::Foundation;
using namespace Stroika::Foundation::Characters;
using namespace Stroika::Foundation::IO::Network;
using namespace Stroika::Foundation::IO::Network::HTTP;
using namespace Stroika::Frameworks::WebServer;
using namespace Stroika::Frameworks::WebService;
using namespace Stroika::Frameworks::WebService::Server;
using namespace Stroika::Frameworks::WebService::Server::VariantValue;

using Memory::BLOB;

using namespace StroikaSample::WebServices;

/*
 *  It's often helpful to structure together, routes, special interceptors, with your connection manager, to package up
 *  all the logic /options for HTTP interface.
 *
 *  This particular organization also makes it easy to save instance variables with the webserver (like a pointer to a handler)
 *  and accesss them from the Route handler functions.
 */
class WebServer::Rep_ {
public:
    const Sequence<Route> kRoutes_;        // rules saying how to map urls to code
    shared_ptr<IWSAPI>    fWSImpl_;        // application logic actually handling webservices
    ConnectionManager     fConnectionMgr_; // manage http connection objects, thread pool, etc

    static const WebServiceMethodDescription kVariables_;

    static const WebServiceMethodDescription kPlus_;
    static const WebServiceMethodDescription kMinus;
    static const WebServiceMethodDescription kTimes;
    static const WebServiceMethodDescription kDivide;

    Rep_ (uint16_t portNumber, const shared_ptr<IWSAPI>& wsImpl)
        : kRoutes_{
              Route{L""_RegEx, DefaultPage_},

              Route{MethodsRegEx::kPost, L"SetAppState"_RegEx, SetAppState_},

              Route{L"FRED"_RegEx, [] (Request*, Response* response) {
                        response->write (L"FRED");
                        response->SetContentType (DataExchange::InternetMediaTypes::kText_PLAIN);
                    }},

              /*
               * the 'variable' API demonstrates a typical REST style CRUD usage - where the 'arguments' mainly come from
               * the URL itself.
               */
              Route{L"variables(/?)"_RegEx, [this] (Message* m) {
                        WriteResponse (&m->rwResponse (), kVariables_, kMapper.FromObject (fWSImpl_->Variables_GET ()));
                    }},
              Route{L"variables/(.+)"_RegEx, [this] (Message* m, const String& varName) {
                        WriteResponse (&m->rwResponse (), kVariables_, kMapper.FromObject (fWSImpl_->Variables_GET (varName)));
                    }},
              Route{MethodsRegEx::kPostOrPut, L"variables/(.+)"_RegEx, [this] (Message* m, const String& varName) {
                        optional<Number> number;
                        // demo getting argument from the body
                        if (not number) {
                            // read if content-type is text (not json)
                            if (m->request ().contentType () and DataExchange::InternetMediaTypeRegistry::Get ().IsA (DataExchange::InternetMediaTypes::kText_PLAIN, *m->request ().contentType ())) {
                                String argsAsString = Streams::TextReader::New (m->rwRequest ().GetBody ()).ReadAll ();
                                number              = kMapper.ToObject<Number> (DataExchange::VariantValue (argsAsString));
                            }
                        }
                        // demo getting argument from the query argument
                        if (not number) {
                            static const String                         kValueParamName_ = L"value"sv;
                            Mapping<String, DataExchange::VariantValue> args             = PickoutParamValuesFromURL (&m->request ());
                            number                                                       = Model::kMapper.ToObject<Number> (args.LookupValue (kValueParamName_));
                        }
                        // demo getting either query arg, or url encoded arg
                        if (not number) {
                            static const String kValueParamName_ = L"value"sv;
                            // NOTE - PickoutParamValues combines PickoutParamValuesFromURL, and PickoutParamValuesFromBody. You can use
                            // Either one of those instead. PickoutParamValuesFromURL assumes you know the name of the parameter, and its
                            // encoded in the query string. PickoutParamValuesFromBody assumes you have something equivilent you can parse ouf
                            // of the body, either json encoded or form-encoded (as of 2.1d23, only json encoded supported)
                            Mapping<String, DataExchange::VariantValue> args = PickoutParamValues (&m->rwRequest ());
                            number                                           = Model::kMapper.ToObject<Number> (args.LookupValue (kValueParamName_));
                        }
                        if (not number) {
                            Execution::Throw (ClientErrorException{L"Expected argument to PUT/POST variable"sv});
                        }
                        fWSImpl_->Variables_SET (varName, *number);
                        WriteResponse (&m->rwResponse (), kVariables_);
                    }},
              Route{MethodsRegEx::kDelete, L"variables/(.+)"_RegEx, [this] (Message* m, const String& varName) {
                        fWSImpl_->Variables_DELETE (varName);
                        WriteResponse (&m->rwResponse (), kVariables_);
                    }},

              /*
               *    plus, minus, times, and divide, test-void-return all all demonstrate passing in variables through either the POST body, or query-arguments.
               */
              Route{L"plus"_RegEx, mkRequestHandler (kPlus_, Model::kMapper, Traversal::Iterable<String>{L"arg1", L"arg2"}, function<Number (Number, Number)>{[this] (Number arg1, Number arg2) { return fWSImpl_->plus (arg1, arg2); }})},
              Route{L"minus"_RegEx, mkRequestHandler (kMinus, Model::kMapper, Traversal::Iterable<String>{L"arg1", L"arg2"}, function<Number (Number, Number)>{[this] (Number arg1, Number arg2) { return fWSImpl_->minus (arg1, arg2); }})},
              Route{L"times"_RegEx, mkRequestHandler (kTimes, Model::kMapper, Traversal::Iterable<String>{L"arg1", L"arg2"}, function<Number (Number, Number)>{[this] (Number arg1, Number arg2) { return fWSImpl_->times (arg1, arg2); }})},
              Route{L"divide"_RegEx, mkRequestHandler (kDivide, Model::kMapper, Traversal::Iterable<String>{L"arg1", L"arg2"}, function<Number (Number, Number)>{[this] (Number arg1, Number arg2) { return fWSImpl_->divide (arg1, arg2); }})},
              Route{L"test-void-return"_RegEx, mkRequestHandler (WebServiceMethodDescription{}, Model::kMapper, Traversal::Iterable<String>{L"err-if-more-than-10"}, function<void (double)>{[] (double check) {
                                    if (check > 10) {
                                        Execution::Throw (Execution::Exception{L"more than 10"sv});
                                    } }})},

          }
        , fWSImpl_
    {
        wsImpl
    }
#if __cpp_designated_initializers
    , fConnectionMgr_
    {
        SocketAddresses (InternetAddresses_Any (), portNumber), kRoutes_, ConnectionManager::Options { .fBindFlags = Socket::BindFlags{}, .fServerHeader = L"Stroika-Sample-WebServices/"_k + AppVersion::kVersion.AsMajorMinorString () }
    }
#else
    , fConnectionMgr_
    {
        SocketAddresses (InternetAddresses_Any (), portNumber), kRoutes_, ConnectionManager::Options { nullopt, nullopt, Socket::BindFlags{}, L"Stroika-Sample-WebServices/"_k + AppVersion::kVersion.AsMajorMinorString () }
    }
#endif
    {
        // @todo - move this to some framework-specific regtests...
        using VariantValue         = DataExchange::VariantValue;
        Sequence<VariantValue> tmp = OrderParamValues (Iterable<String>{L"page", L"xxx"}, PickoutParamValuesFromURL (URI{L"http://www.sophist.com?page=5"}));
        Assert (tmp.size () == 2);
        Assert (tmp[0] == 5);
        Assert (tmp[1] == nullptr);
    }
    // Can declare arguments as Request*,Response*
    static void DefaultPage_ (Request*, Response* response)
    {
        WriteDocsPage (
            response,
            Sequence<WebServiceMethodDescription>{
                kVariables_,
                kPlus_,
                kMinus,
                kTimes,
                kDivide,
            },
            DocsOptions{L"Stroika Sample WebService - Web Methods"_k});
    }
    static void SetAppState_ (Message* message)
    {
        String argsAsString = Streams::TextReader::New (message->rwRequest ().GetBody ()).ReadAll ();
        message->rwResponse ().writeln (L"
Hi SetAppState (" + argsAsString.As<wstring> () + L")
");
        message->rwResponse ().SetContentType (DataExchange::InternetMediaTypes::kHTML);
    }
};

/*
 *  Documentation on WSAPIs
 */
const WebServiceMethodDescription WebServer::Rep_::kVariables_{
    L"variables"_k,
    Set<String>{Methods::kGet, Methods::kPost, Methods::kDelete},
    DataExchange::InternetMediaTypes::kJSON,
    {},
    Sequence<String>{
        L"curl http://localhost:8080/variables -v --output -",
        L"curl http://localhost:8080/variables/x -v --output -",
        L"curl  -X POST http://localhost:8080/variables/x -v --output -",
        L"curl -H \"Content-Type: application/json\" -X POST -d '{\"value\": 3}' http://localhost:8080/variables/x --output -",
        L"curl -H \"Content-Type: text/plain\" -X POST -d '3' http://localhost:8080/variables/x --output -"},
    Sequence<String>{L"@todo - this is a rough draft (but functional). It could use alot of cleanup and review to see WHICH way I recommend using, and just provide the recommended ways in samples"},
};

const WebServiceMethodDescription WebServer::Rep_::kPlus_{
    L"plus"_k,
    Set<String>{Methods::kPost},
    DataExchange::InternetMediaTypes::kJSON,
    {},
    Sequence<String>{
        L"curl -H \"Content-Type: application/json\" -X POST -d '{\"arg1\": 3, \"arg2\": 5 }' http://localhost:8080/plus --output -",
    },
    Sequence<String>{L"add the two argument numbers"},
};
const WebServiceMethodDescription WebServer::Rep_::kMinus{
    L"minus"_k,
    Set<String>{Methods::kPost},
    DataExchange::InternetMediaTypes::kJSON,
    {},
    Sequence<String>{
        L"curl -H \"Content-Type: application/json\" -X POST -d '{\"arg1\": 4.5, \"arg2\": -3.23 }' http://localhost:8080/minus --output -",
    },
    Sequence<String>{L"subtract the two argument numbers"},
};
const WebServiceMethodDescription WebServer::Rep_::kTimes{
    L"times"_k,
    Set<String>{Methods::kPost},
    DataExchange::InternetMediaTypes::kJSON,
    {},
    Sequence<String>{
        L"curl -H \"Content-Type: application/json\" -X POST -d '{\"arg1\":\"2 + 4i\", \"arg2\": 3.2 }' http://localhost:8080/times --output -",
        L"curl -H \"Content-Type: application/json\" -X POST -d '{\"arg1\":\"2 + i\", \"arg2\": \"2 - i\" }' http://localhost:8080/times --output -",
    },
    Sequence<String>{L"multiply the two argument numbers"},
};
const WebServiceMethodDescription WebServer::Rep_::kDivide{
    L"divide"_k,
    Set<String>{Methods::kPost},
    DataExchange::InternetMediaTypes::kJSON,
    {},
    Sequence<String>{
        L"curl -H \"Content-Type: application/json\" -X POST -d '{\"arg1\":\"2 + i\", \"arg2\": 0 }' http://localhost:8080/divide --output -",
    },
    Sequence<String>{L"divide the two argument numbers"},
};

WebServer::WebServer (uint16_t portNumber, const shared_ptr<IWSAPI>& wsImpl)
    : fRep_ (make_shared<Rep_> (portNumber, wsImpl))
{
}
<|endoftext|>


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

  Library:   CTK

  Copyright (c) Kitware Inc.

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

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

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

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

// Qt includes

// CTK includes
#include "ctkVTKScalarBarWidget.h"
#include "ui_ctkVTKScalarBarWidget.h"

// VTK includes
#include <vtkScalarBarActor.h>
#include <vtkScalarBarWidget.h>

//-----------------------------------------------------------------------------
class ctkVTKScalarBarWidgetPrivate: public Ui_ctkVTKScalarBarWidget
{
  Q_DECLARE_PUBLIC(ctkVTKScalarBarWidget);
protected:
  ctkVTKScalarBarWidget* const q_ptr;
public:
  ctkVTKScalarBarWidgetPrivate(ctkVTKScalarBarWidget& object);
  void init();
  void updateFromScalarBarWidget();

  vtkScalarBarWidget* ScalarBarWidget;
};

//-----------------------------------------------------------------------------
ctkVTKScalarBarWidgetPrivate::ctkVTKScalarBarWidgetPrivate(ctkVTKScalarBarWidget& object)
  :q_ptr(&object)
{
  this->ScalarBarWidget = 0;
}

//-----------------------------------------------------------------------------
void ctkVTKScalarBarWidgetPrivate::init()
{
  Q_Q(ctkVTKScalarBarWidget);
  this->setupUi(q);
  q->setEnabled(this->ScalarBarWidget != 0);
  QObject::connect(this->DisplayScalarBarCheckBox, SIGNAL(toggled(bool)),
                   q, SLOT(setDisplay(bool)));
  QObject::connect(this->MaxNumberOfColorsSpinBox, SIGNAL(valueChanged(int)),
                   q, SLOT(setMaxNumberOfColors(int)));
  QObject::connect(this->NumberOfLabelsSpinBox, SIGNAL(valueChanged(int)),
                   q, SLOT(setNumberOfLabels(int)));
  QObject::connect(this->TitleTextPropertyWidget, SIGNAL(textChanged(QString)),
                   q, SLOT(setTitle(QString)));

  QObject::connect(this->LabelsTextPropertyWidget, SIGNAL(textChanged(QString)),
                   q, SLOT(setLabelsFormat(QString)));
  QObject::connect(this->LabelsTextPropertyWidget, SIGNAL(colorChanged(QColor)),
                   q, SIGNAL(modified()));
  QObject::connect(this->LabelsTextPropertyWidget, SIGNAL(opacityChanged(double)),
                   q, SIGNAL(modified()));
  QObject::connect(this->LabelsTextPropertyWidget, SIGNAL(fontFamilyChanged(QString)),
                   q, SIGNAL(modified()));
  QObject::connect(this->LabelsTextPropertyWidget, SIGNAL(boldChanged(bool)),
                   q, SIGNAL(modified()));
  QObject::connect(this->LabelsTextPropertyWidget, SIGNAL(italicChanged(bool)),
                   q, SIGNAL(modified()));
  QObject::connect(this->LabelsTextPropertyWidget, SIGNAL(shadowChanged(bool)),
                   q, SIGNAL(modified()));
}

//-----------------------------------------------------------------------------
void ctkVTKScalarBarWidgetPrivate::updateFromScalarBarWidget()
{
  Q_Q(ctkVTKScalarBarWidget);

  vtkScalarBarActor* actor =
    this->ScalarBarWidget ? this->ScalarBarWidget->GetScalarBarActor() : 0;
  q->setEnabled(actor != 0);
  if (actor == 0)
    {
    return;
    }
  this->DisplayScalarBarCheckBox->setChecked(this->ScalarBarWidget->GetEnabled() != 0);
  this->MaxNumberOfColorsSpinBox->setValue(actor->GetMaximumNumberOfColors());
  this->NumberOfLabelsSpinBox->setValue(actor->GetNumberOfLabels());

  this->TitleTextPropertyWidget->setTextProperty(
    actor->GetTitleTextProperty());
  this->LabelsTextPropertyWidget->setTextProperty(
    actor->GetLabelTextProperty());
  this->TitleTextPropertyWidget->setText(actor->GetTitle());
  this->LabelsTextPropertyWidget->setText(actor->GetLabelFormat());
}

//-----------------------------------------------------------------------------
ctkVTKScalarBarWidget::ctkVTKScalarBarWidget(QWidget* parentWidget)
  :QWidget(parentWidget)
  , d_ptr(new ctkVTKScalarBarWidgetPrivate(*this))
{
  Q_D(ctkVTKScalarBarWidget);
  d->init();
}

//-----------------------------------------------------------------------------
ctkVTKScalarBarWidget::ctkVTKScalarBarWidget(vtkScalarBarWidget* scalarBarWidget, QWidget* parentWidget)
  :QWidget(parentWidget)
  , d_ptr(new ctkVTKScalarBarWidgetPrivate(*this))
{
  Q_D(ctkVTKScalarBarWidget);
  d->init();
  this->setScalarBarWidget(scalarBarWidget);
}

//-----------------------------------------------------------------------------
ctkVTKScalarBarWidget::~ctkVTKScalarBarWidget()
{
}

//-----------------------------------------------------------------------------
void ctkVTKScalarBarWidget::setScalarBarWidget(vtkScalarBarWidget* scalarBarWidget)
{
  Q_D(ctkVTKScalarBarWidget);
  if (scalarBarWidget == d->ScalarBarWidget)
    {
    return;
    }
  vtkScalarBarActor* oldActor =
    d->ScalarBarWidget ? d->ScalarBarWidget->GetScalarBarActor() : 0;
  vtkScalarBarActor* newActor =
    scalarBarWidget ? scalarBarWidget->GetScalarBarActor() : 0;
  qvtkReconnect(d->ScalarBarWidget, scalarBarWidget, vtkCommand::EnableEvent,
                this, SLOT(onScalarBarModified()));
  qvtkReconnect(d->ScalarBarWidget, scalarBarWidget, vtkCommand::DisableEvent,
                this, SLOT(onScalarBarModified()));
  qvtkReconnect(oldActor, newActor, vtkCommand::ModifiedEvent,
                this, SLOT(onScalarBarModified()));
  d->ScalarBarWidget = scalarBarWidget;
  this->onScalarBarModified();
}

//-----------------------------------------------------------------------------
vtkScalarBarWidget* ctkVTKScalarBarWidget::scalarBarWidget()const
{
  Q_D(const ctkVTKScalarBarWidget);
  return d->ScalarBarWidget;
}

//-----------------------------------------------------------------------------
void ctkVTKScalarBarWidget::onScalarBarModified()
{
  Q_D(ctkVTKScalarBarWidget);
  d->updateFromScalarBarWidget();
  emit modified();
}

//-----------------------------------------------------------------------------
void ctkVTKScalarBarWidget::setDisplay(bool visible)
{
  Q_D(ctkVTKScalarBarWidget);
  if (d->ScalarBarWidget == 0)
    {
    return;
    }
  d->ScalarBarWidget->SetEnabled(visible);
  // calling SetEnabled might fail, make sure the checkbox is up-to-date
  d->DisplayScalarBarCheckBox->setChecked(d->ScalarBarWidget->GetEnabled());
}

//-----------------------------------------------------------------------------
bool ctkVTKScalarBarWidget::display()const
{
  Q_D(const ctkVTKScalarBarWidget);
  return d->DisplayScalarBarCheckBox->isChecked();
}

//-----------------------------------------------------------------------------
void ctkVTKScalarBarWidget::setMaxNumberOfColors(int colorCount)
{
  Q_D(ctkVTKScalarBarWidget);
  vtkScalarBarActor* actor =
    d->ScalarBarWidget ? d->ScalarBarWidget->GetScalarBarActor() : 0;
  if (actor == 0)
    {
    return;
    }
  actor->SetMaximumNumberOfColors(colorCount);
}

//-----------------------------------------------------------------------------
int ctkVTKScalarBarWidget::maxNumberOfColors()const
{
  Q_D(const ctkVTKScalarBarWidget);
  return d->MaxNumberOfColorsSpinBox->value();
}

//-----------------------------------------------------------------------------
void ctkVTKScalarBarWidget::setNumberOfLabels(int labelCount)
{
  Q_D(ctkVTKScalarBarWidget);
  vtkScalarBarActor* actor =
    d->ScalarBarWidget ? d->ScalarBarWidget->GetScalarBarActor() : 0;
  if (actor == 0)
    {
    return;
    }
  actor->SetNumberOfLabels(labelCount);
}

//-----------------------------------------------------------------------------
int ctkVTKScalarBarWidget::numberOfLabels()const
{
  Q_D(const ctkVTKScalarBarWidget);
  return d->NumberOfLabelsSpinBox->value();
}

//-----------------------------------------------------------------------------
void ctkVTKScalarBarWidget::setTitle(const QString& title)
{
  Q_D(ctkVTKScalarBarWidget);
  vtkScalarBarActor* actor =
    d->ScalarBarWidget ? d->ScalarBarWidget->GetScalarBarActor() : 0;
  if (actor == 0)
    {
    return;
    }
  actor->SetTitle(title.toLatin1());
}

//-----------------------------------------------------------------------------
QString ctkVTKScalarBarWidget::title()const
{
  Q_D(const ctkVTKScalarBarWidget);
  return d->TitleTextPropertyWidget->text();
}

//-----------------------------------------------------------------------------
void ctkVTKScalarBarWidget::setLabelsFormat(const QString& format)
{
  Q_D(ctkVTKScalarBarWidget);
  vtkScalarBarActor* actor =
    d->ScalarBarWidget ? d->ScalarBarWidget->GetScalarBarActor() : 0;
  if (actor == 0)
    {
    return;
    }
  actor->SetLabelFormat(format.toLatin1());
}

//-----------------------------------------------------------------------------
QString ctkVTKScalarBarWidget::labelsFormat()const
{
  Q_D(const ctkVTKScalarBarWidget);
  return d->LabelsTextPropertyWidget->text();
}
<commit_msg>BUG: listen for unique signals from the title text property<commit_after>/*=========================================================================

  Library:   CTK

  Copyright (c) Kitware Inc.

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

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

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

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

// Qt includes

// CTK includes
#include "ctkVTKScalarBarWidget.h"
#include "ui_ctkVTKScalarBarWidget.h"

// VTK includes
#include <vtkScalarBarActor.h>
#include <vtkScalarBarWidget.h>

//-----------------------------------------------------------------------------
class ctkVTKScalarBarWidgetPrivate: public Ui_ctkVTKScalarBarWidget
{
  Q_DECLARE_PUBLIC(ctkVTKScalarBarWidget);
protected:
  ctkVTKScalarBarWidget* const q_ptr;
public:
  ctkVTKScalarBarWidgetPrivate(ctkVTKScalarBarWidget& object);
  void init();
  void updateFromScalarBarWidget();

  vtkScalarBarWidget* ScalarBarWidget;
};

//-----------------------------------------------------------------------------
ctkVTKScalarBarWidgetPrivate::ctkVTKScalarBarWidgetPrivate(ctkVTKScalarBarWidget& object)
  :q_ptr(&object)
{
  this->ScalarBarWidget = 0;
}

//-----------------------------------------------------------------------------
void ctkVTKScalarBarWidgetPrivate::init()
{
  Q_Q(ctkVTKScalarBarWidget);
  this->setupUi(q);
  q->setEnabled(this->ScalarBarWidget != 0);
  QObject::connect(this->DisplayScalarBarCheckBox, SIGNAL(toggled(bool)),
                   q, SLOT(setDisplay(bool)));
  QObject::connect(this->MaxNumberOfColorsSpinBox, SIGNAL(valueChanged(int)),
                   q, SLOT(setMaxNumberOfColors(int)));
  QObject::connect(this->NumberOfLabelsSpinBox, SIGNAL(valueChanged(int)),
                   q, SLOT(setNumberOfLabels(int)));

  QObject::connect(this->TitleTextPropertyWidget, SIGNAL(textChanged(QString)),
                   q, SLOT(setTitle(QString)));
  QObject::connect(this->TitleTextPropertyWidget, SIGNAL(colorChanged(QColor)),
                   q, SIGNAL(modified()));
  QObject::connect(this->TitleTextPropertyWidget, SIGNAL(opacityChanged(double)),
                   q, SIGNAL(modified()));
  QObject::connect(this->TitleTextPropertyWidget, SIGNAL(fontFamilyChanged(QString)),
                   q, SIGNAL(modified()));
  QObject::connect(this->TitleTextPropertyWidget, SIGNAL(boldChanged(bool)),
                   q, SIGNAL(modified()));
  QObject::connect(this->TitleTextPropertyWidget, SIGNAL(italicChanged(bool)),
                   q, SIGNAL(modified()));
  QObject::connect(this->TitleTextPropertyWidget, SIGNAL(shadowChanged(bool)),
                   q, SIGNAL(modified()));

  QObject::connect(this->LabelsTextPropertyWidget, SIGNAL(textChanged(QString)),
                   q, SLOT(setLabelsFormat(QString)));
  QObject::connect(this->LabelsTextPropertyWidget, SIGNAL(colorChanged(QColor)),
                   q, SIGNAL(modified()));
  QObject::connect(this->LabelsTextPropertyWidget, SIGNAL(opacityChanged(double)),
                   q, SIGNAL(modified()));
  QObject::connect(this->LabelsTextPropertyWidget, SIGNAL(fontFamilyChanged(QString)),
                   q, SIGNAL(modified()));
  QObject::connect(this->LabelsTextPropertyWidget, SIGNAL(boldChanged(bool)),
                   q, SIGNAL(modified()));
  QObject::connect(this->LabelsTextPropertyWidget, SIGNAL(italicChanged(bool)),
                   q, SIGNAL(modified()));
  QObject::connect(this->LabelsTextPropertyWidget, SIGNAL(shadowChanged(bool)),
                   q, SIGNAL(modified()));
}

//-----------------------------------------------------------------------------
void ctkVTKScalarBarWidgetPrivate::updateFromScalarBarWidget()
{
  Q_Q(ctkVTKScalarBarWidget);

  vtkScalarBarActor* actor =
    this->ScalarBarWidget ? this->ScalarBarWidget->GetScalarBarActor() : 0;
  q->setEnabled(actor != 0);
  if (actor == 0)
    {
    return;
    }
  this->DisplayScalarBarCheckBox->setChecked(this->ScalarBarWidget->GetEnabled() != 0);
  this->MaxNumberOfColorsSpinBox->setValue(actor->GetMaximumNumberOfColors());
  this->NumberOfLabelsSpinBox->setValue(actor->GetNumberOfLabels());

  this->TitleTextPropertyWidget->setTextProperty(
    actor->GetTitleTextProperty());
  this->LabelsTextPropertyWidget->setTextProperty(
    actor->GetLabelTextProperty());
  this->TitleTextPropertyWidget->setText(actor->GetTitle());
  this->LabelsTextPropertyWidget->setText(actor->GetLabelFormat());
}

//-----------------------------------------------------------------------------
ctkVTKScalarBarWidget::ctkVTKScalarBarWidget(QWidget* parentWidget)
  :QWidget(parentWidget)
  , d_ptr(new ctkVTKScalarBarWidgetPrivate(*this))
{
  Q_D(ctkVTKScalarBarWidget);
  d->init();
}

//-----------------------------------------------------------------------------
ctkVTKScalarBarWidget::ctkVTKScalarBarWidget(vtkScalarBarWidget* scalarBarWidget, QWidget* parentWidget)
  :QWidget(parentWidget)
  , d_ptr(new ctkVTKScalarBarWidgetPrivate(*this))
{
  Q_D(ctkVTKScalarBarWidget);
  d->init();
  this->setScalarBarWidget(scalarBarWidget);
}

//-----------------------------------------------------------------------------
ctkVTKScalarBarWidget::~ctkVTKScalarBarWidget()
{
}

//-----------------------------------------------------------------------------
void ctkVTKScalarBarWidget::setScalarBarWidget(vtkScalarBarWidget* scalarBarWidget)
{
  Q_D(ctkVTKScalarBarWidget);
  if (scalarBarWidget == d->ScalarBarWidget)
    {
    return;
    }
  vtkScalarBarActor* oldActor =
    d->ScalarBarWidget ? d->ScalarBarWidget->GetScalarBarActor() : 0;
  vtkScalarBarActor* newActor =
    scalarBarWidget ? scalarBarWidget->GetScalarBarActor() : 0;
  qvtkReconnect(d->ScalarBarWidget, scalarBarWidget, vtkCommand::EnableEvent,
                this, SLOT(onScalarBarModified()));
  qvtkReconnect(d->ScalarBarWidget, scalarBarWidget, vtkCommand::DisableEvent,
                this, SLOT(onScalarBarModified()));
  qvtkReconnect(oldActor, newActor, vtkCommand::ModifiedEvent,
                this, SLOT(onScalarBarModified()));
  d->ScalarBarWidget = scalarBarWidget;
  this->onScalarBarModified();
}

//-----------------------------------------------------------------------------
vtkScalarBarWidget* ctkVTKScalarBarWidget::scalarBarWidget()const
{
  Q_D(const ctkVTKScalarBarWidget);
  return d->ScalarBarWidget;
}

//-----------------------------------------------------------------------------
void ctkVTKScalarBarWidget::onScalarBarModified()
{
  Q_D(ctkVTKScalarBarWidget);
  d->updateFromScalarBarWidget();
  emit modified();
}

//-----------------------------------------------------------------------------
void ctkVTKScalarBarWidget::setDisplay(bool visible)
{
  Q_D(ctkVTKScalarBarWidget);
  if (d->ScalarBarWidget == 0)
    {
    return;
    }
  d->ScalarBarWidget->SetEnabled(visible);
  // calling SetEnabled might fail, make sure the checkbox is up-to-date
  d->DisplayScalarBarCheckBox->setChecked(d->ScalarBarWidget->GetEnabled());
}

//-----------------------------------------------------------------------------
bool ctkVTKScalarBarWidget::display()const
{
  Q_D(const ctkVTKScalarBarWidget);
  return d->DisplayScalarBarCheckBox->isChecked();
}

//-----------------------------------------------------------------------------
void ctkVTKScalarBarWidget::setMaxNumberOfColors(int colorCount)
{
  Q_D(ctkVTKScalarBarWidget);
  vtkScalarBarActor* actor =
    d->ScalarBarWidget ? d->ScalarBarWidget->GetScalarBarActor() : 0;
  if (actor == 0)
    {
    return;
    }
  actor->SetMaximumNumberOfColors(colorCount);
}

//-----------------------------------------------------------------------------
int ctkVTKScalarBarWidget::maxNumberOfColors()const
{
  Q_D(const ctkVTKScalarBarWidget);
  return d->MaxNumberOfColorsSpinBox->value();
}

//-----------------------------------------------------------------------------
void ctkVTKScalarBarWidget::setNumberOfLabels(int labelCount)
{
  Q_D(ctkVTKScalarBarWidget);
  vtkScalarBarActor* actor =
    d->ScalarBarWidget ? d->ScalarBarWidget->GetScalarBarActor() : 0;
  if (actor == 0)
    {
    return;
    }
  actor->SetNumberOfLabels(labelCount);
}

//-----------------------------------------------------------------------------
int ctkVTKScalarBarWidget::numberOfLabels()const
{
  Q_D(const ctkVTKScalarBarWidget);
  return d->NumberOfLabelsSpinBox->value();
}

//-----------------------------------------------------------------------------
void ctkVTKScalarBarWidget::setTitle(const QString& title)
{
  Q_D(ctkVTKScalarBarWidget);
  vtkScalarBarActor* actor =
    d->ScalarBarWidget ? d->ScalarBarWidget->GetScalarBarActor() : 0;
  if (actor == 0)
    {
    return;
    }
  actor->SetTitle(title.toLatin1());
}

//-----------------------------------------------------------------------------
QString ctkVTKScalarBarWidget::title()const
{
  Q_D(const ctkVTKScalarBarWidget);
  return d->TitleTextPropertyWidget->text();
}

//-----------------------------------------------------------------------------
void ctkVTKScalarBarWidget::setLabelsFormat(const QString& format)
{
  Q_D(ctkVTKScalarBarWidget);
  vtkScalarBarActor* actor =
    d->ScalarBarWidget ? d->ScalarBarWidget->GetScalarBarActor() : 0;
  if (actor == 0)
    {
    return;
    }
  actor->SetLabelFormat(format.toLatin1());
}

//-----------------------------------------------------------------------------
QString ctkVTKScalarBarWidget::labelsFormat()const
{
  Q_D(const ctkVTKScalarBarWidget);
  return d->LabelsTextPropertyWidget->text();
}
<|endoftext|>


<commit_before>#include "pfasst/quadrature/polynomial.hpp"

#include <algorithm>
#include <cassert>
#include <cmath>
#include <complex>
using namespace std;

namespace pfasst
{
  namespace quadrature
  {
    /**
     * @todo Consider issuing a warning/assertion when `n` is zero.
     */
    template<typename CoeffT>
    Polynomial<CoeffT>::Polynomial(size_t n)
      : c(n, CoeffT(0.0))
    {}

    template<typename CoeffT>
    size_t Polynomial<CoeffT>::order() const
    {
      return c.size() - 1;
    }

    template<typename CoeffT>
    CoeffT& Polynomial<CoeffT>::operator[](const size_t i)
    {
      return c.at(i);
    }

    template<typename CoeffT>
    Polynomial<CoeffT> Polynomial<CoeffT>::differentiate() const
    {
      Polynomial<CoeffT> p(c.size() - 1);
      for (size_t j = 1; j < c.size(); j++) {
        p[j - 1] = j * c[j];
      }
      return p;
    }

    template<typename CoeffT>
    Polynomial<CoeffT> Polynomial<CoeffT>::integrate() const
    {
      Polynomial<CoeffT> p(c.size() + 1);
      for (size_t j = 0; j < c.size(); j++) {
        p[j + 1] = c[j] / (j + 1);
      }
      return p;
    }

    template<typename CoeffT>
    Polynomial<CoeffT> Polynomial<CoeffT>::normalize() const
    {
      Polynomial<CoeffT> p(c.size());
      for (size_t j = 0; j < c.size(); j++) {
        p[j] = c[j] / c.back();
      }
      return p;
    }

    /**
     * @internals
     * @note Asserts this polynomial has at least order 1 if `NDEBUG` is not defined.
     * @endinternals
     */
    template<typename CoeffT>
    vector<CoeffT> Polynomial<CoeffT>::roots(size_t num_iterations, CoeffT ztol) const
    {
      assert(c.size() >= 1);
      size_t n = c.size() - 1;

      // initial guess
      vector<complex<CoeffT>> z0(n), z1(n);
      for (size_t j = 0; j < n; j++) {
        z0[j] = pow(complex<double>(0.4, 0.9), j);
        z1[j] = z0[j];
      }

      // durand-kerner-weierstrass iterations
      Polynomial<CoeffT> p = this->normalize();
      for (size_t k = 0; k < num_iterations; k++) {
        complex<CoeffT> num, den;
        for (size_t i = 0; i < n; i++) {
          num = p.evaluate(z0[i]);
          den = 1.0;
          for (size_t j = 0; j < n; j++) {
            if (j == i) { continue; }
            den = den * (z0[i] - z0[j]);
          }
          z0[i] = z0[i] - num / den;
        }
        z1 = z0;
      }

      vector<CoeffT> roots(n);
      for (size_t j = 0; j < n; j++) {
        roots[j] = abs(z0[j]) < ztol ? 0.0 : real(z0[j]);
      }

      sort(roots.begin(), roots.end());
      return roots;
    }

    template<typename CoeffT>
    Polynomial<CoeffT> Polynomial<CoeffT>::legendre(const size_t order)
    {
      if (order == 0) {
        Polynomial<CoeffT> p(1);
        p[0] = 1.0;
        return p;
      }

      if (order == 1) {
        Polynomial<CoeffT> p(2);
        p[0] = 0.0;
        p[1] = 1.0;
        return p;
      }

      Polynomial<CoeffT> p0(order + 1), p1(order + 1), p2(order + 1);
      p0[0] = 1.0; p1[1] = 1.0;

      // (n + 1) P_{n+1} = (2n + 1) x P_{n} - n P_{n-1}
      for (size_t m = 1; m < order; m++) {
        for (size_t j = 1; j < order + 1; j++) {
          p2[j] = ((2 * m + 1) * p1[j - 1] - m * p0[j]) / (m + 1);
        }
        p2[0] = - int(m) * p0[0] / (m + 1);

        for (size_t j = 0; j < order + 1; j++) {
          p0[j] = p1[j];
          p1[j] = p2[j];
        }
      }

      return p2;
    }
  }  // ::pfasst::quadrature
}  // ::pfasst
<commit_msg>Remove z1.<commit_after>#include "pfasst/quadrature/polynomial.hpp"

#include <algorithm>
#include <cassert>
#include <cmath>
#include <complex>
using namespace std;

namespace pfasst
{
  namespace quadrature
  {
    /**
     * @todo Consider issuing a warning/assertion when `n` is zero.
     */
    template<typename CoeffT>
    Polynomial<CoeffT>::Polynomial(size_t n)
      : c(n, CoeffT(0.0))
    {}

    template<typename CoeffT>
    size_t Polynomial<CoeffT>::order() const
    {
      return c.size() - 1;
    }

    template<typename CoeffT>
    CoeffT& Polynomial<CoeffT>::operator[](const size_t i)
    {
      return c.at(i);
    }

    template<typename CoeffT>
    Polynomial<CoeffT> Polynomial<CoeffT>::differentiate() const
    {
      Polynomial<CoeffT> p(c.size() - 1);
      for (size_t j = 1; j < c.size(); j++) {
        p[j - 1] = j * c[j];
      }
      return p;
    }

    template<typename CoeffT>
    Polynomial<CoeffT> Polynomial<CoeffT>::integrate() const
    {
      Polynomial<CoeffT> p(c.size() + 1);
      for (size_t j = 0; j < c.size(); j++) {
        p[j + 1] = c[j] / (j + 1);
      }
      return p;
    }

    template<typename CoeffT>
    Polynomial<CoeffT> Polynomial<CoeffT>::normalize() const
    {
      Polynomial<CoeffT> p(c.size());
      for (size_t j = 0; j < c.size(); j++) {
        p[j] = c[j] / c.back();
      }
      return p;
    }

    /**
     * @internals
     * @note Asserts this polynomial has at least order 1 if `NDEBUG` is not defined.
     * @endinternals
     */
    template<typename CoeffT>
    vector<CoeffT> Polynomial<CoeffT>::roots(size_t num_iterations, CoeffT ztol) const
    {
      assert(c.size() >= 1);
      size_t n = c.size() - 1;

      // initial guess
      vector<complex<CoeffT>> z0(n);
      for (size_t j = 0; j < n; j++) {
        z0[j] = pow(complex<double>(0.4, 0.9), j);
      }

      // durand-kerner-weierstrass iterations
      Polynomial<CoeffT> p = this->normalize();
      for (size_t k = 0; k < num_iterations; k++) {
        complex<CoeffT> num, den;
        for (size_t i = 0; i < n; i++) {
          num = p.evaluate(z0[i]);
          den = 1.0;
          for (size_t j = 0; j < n; j++) {
            if (j == i) { continue; }
            den = den * (z0[i] - z0[j]);
          }
          z0[i] = z0[i] - num / den;
        }
      }

      vector<CoeffT> roots(n);
      for (size_t j = 0; j < n; j++) {
        roots[j] = abs(z0[j]) < ztol ? 0.0 : real(z0[j]);
      }

      sort(roots.begin(), roots.end());
      return roots;
    }

    template<typename CoeffT>
    Polynomial<CoeffT> Polynomial<CoeffT>::legendre(const size_t order)
    {
      if (order == 0) {
        Polynomial<CoeffT> p(1);
        p[0] = 1.0;
        return p;
      }

      if (order == 1) {
        Polynomial<CoeffT> p(2);
        p[0] = 0.0;
        p[1] = 1.0;
        return p;
      }

      Polynomial<CoeffT> p0(order + 1), p1(order + 1), p2(order + 1);
      p0[0] = 1.0; p1[1] = 1.0;

      // (n + 1) P_{n+1} = (2n + 1) x P_{n} - n P_{n-1}
      for (size_t m = 1; m < order; m++) {
        for (size_t j = 1; j < order + 1; j++) {
          p2[j] = ((2 * m + 1) * p1[j - 1] - m * p0[j]) / (m + 1);
        }
        p2[0] = - int(m) * p0[0] / (m + 1);

        for (size_t j = 0; j < order + 1; j++) {
          p0[j] = p1[j];
          p1[j] = p2[j];
        }
      }

      return p2;
    }
  }  // ::pfasst::quadrature
}  // ::pfasst
<|endoftext|>


<commit_before>///
/// @file  PrintPrimes.hpp
///
/// Copyright (C) 2018 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#ifndef PRIMEGENERATOR_HPP
#define PRIMEGENERATOR_HPP

#include "Erat.hpp"
#include "PreSieve.hpp"
#include "PrimeSieve.hpp"
#include "types.hpp"

#include <stdint.h>
#include <vector>

namespace primesieve {

class Store;

/// After a segment has been sieved PrintPrimes is
/// used to reconstruct primes and prime k-tuplets from
/// 1 bits of the sieve array
///
class PrintPrimes : public Erat
{
public:
  PrintPrimes(PrimeSieve&);
  void sieve();
private:
  enum { END = 0xff + 1 };
  static const uint64_t bitmasks_[6][5];
  uint64_t low_ = 0;
  /// Count lookup tables for prime k-tuplets
  std::vector<byte_t> kCounts_[6];
  PreSieve preSieve_;
  counts_t& counts_;
  /// Reference to the associated PrimeSieve object
  PrimeSieve& ps_;
  void initCounts();
  void print();
  void countPrimes();
  void countkTuplets();
  void printPrimes() const;
  void printkTuplets() const;
};

} // namespace

#endif
<commit_msg>Fix include guards<commit_after>///
/// @file  PrintPrimes.hpp
///
/// Copyright (C) 2018 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#ifndef PRINTPRIMES_HPP
#define PRINTPRIMES_HPP

#include "Erat.hpp"
#include "PreSieve.hpp"
#include "PrimeSieve.hpp"
#include "types.hpp"

#include <stdint.h>
#include <vector>

namespace primesieve {

class Store;

/// After a segment has been sieved PrintPrimes is
/// used to reconstruct primes and prime k-tuplets from
/// 1 bits of the sieve array
///
class PrintPrimes : public Erat
{
public:
  PrintPrimes(PrimeSieve&);
  void sieve();
private:
  enum { END = 0xff + 1 };
  static const uint64_t bitmasks_[6][5];
  uint64_t low_ = 0;
  /// Count lookup tables for prime k-tuplets
  std::vector<byte_t> kCounts_[6];
  PreSieve preSieve_;
  counts_t& counts_;
  /// Reference to the associated PrimeSieve object
  PrimeSieve& ps_;
  void initCounts();
  void print();
  void countPrimes();
  void countkTuplets();
  void printPrimes() const;
  void printkTuplets() const;
};

} // namespace

#endif
<|endoftext|>


<commit_before>//
// Copyright (c) 2013-2014 Christoph Malek
// See LICENSE for more information.
//

#ifndef RJ_SHARED_INPUT_HPP
#define RJ_SHARED_INPUT_HPP

#include <rectojump/global/common.hpp>

#include <mlk/containers/container_utl.h>
#include <mlk/signals_slots/slot.h>
#include <mlk/tools/bitset.h>

#include <map>

namespace rj
{
	class game_window;

	using key_vec = std::vector<key>;

	class input
	{
		friend class game_window;

		mlk::bitset<btn, btn::ButtonCount> m_mousebtn_bits;
		mlk::bitset<key, key::KeyCount> m_key_bits;

	public:
		mlk::event_delegates<key> on_key_pressed;
		mlk::event_delegates<key_vec> on_keys_pressed;
		mlk::event_delegates<btn, const vec2f&> on_btn_pressed;

		input() = default;

		static input& get() noexcept
		{static input i; return i;}

		bool is_key_valid(key k) const noexcept
		{return k != key::Unknown;}

	private:
		void update(const vec2f& mousepos)
		{
			for(auto& a : on_btn_pressed)
				if(m_mousebtn_bits & a.first)
					a.second(mousepos);
		}

		void key_pressed(key k)
		{
			if(!this->is_key_valid(k))
				return;

			if(mlk::cnt::exists_if(
			[=](const std::pair<key, mlk::slot<>>& p)
			{return p.first == k;}, on_key_pressed))
				on_key_pressed[k]();

			m_key_bits |= k;
			for(auto& keys : on_keys_pressed)
			{
				auto all_pressed(false);
				for(auto& key : keys.first)
				{
					if(!this->is_key_valid(key))
						break;

					// check if key 'key' is currently pressed
					if(!(m_key_bits & key))
					{
						all_pressed = false;
						break;
					}
					all_pressed = true;
				}

				// not all keys were pressed
				if(!all_pressed)
					continue;

				// call slot
				keys.second();
			}
		}

		void key_released(key k)
		{
			if(!this->is_key_valid(k))
				return;
			m_key_bits.remove(k);
		}

		void btn_pressed(btn b)
		{m_mousebtn_bits |= b;}

		void btn_released(btn b)
		{m_mousebtn_bits.remove(b);}
	};

	inline auto on_key_pressed(key k)
	-> decltype(input::get().on_key_pressed[k])&
	{
		if(!input::get().is_key_valid(k))
			throw std::runtime_error{"invalid key passed"};
		return input::get().on_key_pressed[k];
	}

	template<typename... Keys>
	auto on_keys_pressed(Keys&&... keys)
	-> decltype(input::get().on_keys_pressed[key_vec{}])
	{
		key_vec keys_vec;
		mlk::cnt::make_vector(keys_vec, std::forward<Keys>(keys)...);
		return input::get().on_keys_pressed[keys_vec];
	}

	inline auto on_btn_pressed(btn b)
	-> decltype(input::get().on_btn_pressed[b])&
	{return input::get().on_btn_pressed[b];}
}

#endif // RJ_SHARED_INPUT_HPP
<commit_msg>input: added functions to test currently pressed keys/buttons<commit_after>//
// Copyright (c) 2013-2014 Christoph Malek
// See LICENSE for more information.
//

#ifndef RJ_SHARED_INPUT_HPP
#define RJ_SHARED_INPUT_HPP

#include <rectojump/global/common.hpp>

#include <mlk/containers/container_utl.h>
#include <mlk/signals_slots/slot.h>
#include <mlk/tools/bitset.h>

#include <map>

namespace rj
{
	class game_window;

	using key_vec = std::vector<key>;

	class input
	{
		friend class game_window;

		mlk::bitset<btn, btn::ButtonCount> m_mousebtn_bits;
		mlk::bitset<key, key::KeyCount> m_key_bits;

		mlk::event_delegates<key> m_on_key_pressed;
		mlk::event_delegates<key_vec> m_on_keys_pressed;
		mlk::event_delegates<btn, const vec2f&> m_on_btn_pressed;

	public:
		input() = default;

		static input& get() noexcept
		{static input i; return i;}

		bool is_key_valid(key k) const noexcept
		{return k != key::Unknown;}

	private:
		void update(const vec2f& mousepos)
		{
			for(auto& a : m_on_btn_pressed)
				if(m_mousebtn_bits & a.first)
					a.second(mousepos);
		}

		void key_pressed(key k)
		{
			if(!this->is_key_valid(k))
				return;

			if(mlk::cnt::exists_if(
			[=](const std::pair<key, mlk::slot<>>& p)
			{return p.first == k;}, m_on_key_pressed))
				m_on_key_pressed[k]();

			m_key_bits |= k;
			for(auto& keys : m_on_keys_pressed)
			{
				auto all_pressed(false);
				for(auto& key : keys.first)
				{
					if(!this->is_key_valid(key))
						break;

					// check if key 'key' is currently pressed
					if(!(m_key_bits & key))
					{
						all_pressed = false;
						break;
					}
					all_pressed = true;
				}

				// not all keys were pressed
				if(!all_pressed)
					continue;

				// call slot
				keys.second();
			}
		}

		void key_released(key k)
		{
			if(!this->is_key_valid(k))
				return;
			m_key_bits.remove(k);
		}

		void btn_pressed(btn b)
		{m_mousebtn_bits |= b;}

		void btn_released(btn b)
		{m_mousebtn_bits.remove(b);}

		friend auto on_key_pressed(key k)
		-> decltype(m_on_key_pressed[k])&;

		template<typename... Keys>
		friend auto on_keys_pressed(Keys&&...)
		-> decltype(m_on_keys_pressed[key_vec{}]);

		friend bool is_key_pressed(key);

		friend inline auto on_btn_pressed(btn b)
		-> decltype(m_on_btn_pressed[b])&;

		friend bool is_btn_pressed(btn);
	};

	inline auto on_key_pressed(key k)
	-> decltype(input::get().m_on_key_pressed[k])&
	{
		if(!input::get().is_key_valid(k))
			throw std::runtime_error{"invalid key passed"};
		return input::get().m_on_key_pressed[k];
	}

	template<typename... Keys>
	auto on_keys_pressed(Keys&&... keys)
	-> decltype(input::get().m_on_keys_pressed[key_vec{}])
	{
		key_vec keys_vec;
		mlk::cnt::make_vector(keys_vec, std::forward<Keys>(keys)...);
		return input::get().m_on_keys_pressed[keys_vec];
	}

	inline bool is_key_pressed(key k)
	{return input::get().m_key_bits & k;}

	inline auto on_btn_pressed(btn b)
	-> decltype(input::get().m_on_btn_pressed[b])&
	{return input::get().m_on_btn_pressed[b];}

	inline bool is_btn_pressed(btn b)
	{return input::get().m_mousebtn_bits & b;}
}

#endif // RJ_SHARED_INPUT_HPP
<|endoftext|>


<commit_before>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  You may not use this file except in compliance with the License.
 *
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
/*
 * Copyright (C) 2018 ScyllaDB
 */

#pragma once

#include <optional>
#include <string_view>
#include <variant>

#include <filesystem>

#include <memory_resource>

namespace seastar {

/// \cond internal

namespace compat {

using memory_resource = std::pmr::memory_resource;

template<typename T>
using polymorphic_allocator = std::pmr::polymorphic_allocator<T>;

static inline
memory_resource* pmr_get_default_resource() {
    return std::pmr::get_default_resource();
}

}

}

// Defining SEASTAR_ASAN_ENABLED in here is a bit of a hack, but
// convenient since it is build system independent and in practice
// everything includes this header.

#ifndef __has_feature
#define __has_feature(x) 0
#endif

// clang uses __has_feature, gcc defines __SANITIZE_ADDRESS__
#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
#define SEASTAR_ASAN_ENABLED
#endif

namespace seastar {

/// \cond internal

namespace compat {

template <typename T>
using optional = std::optional<T>;

using nullopt_t = std::nullopt_t;

inline constexpr auto nullopt = std::nullopt;

template <typename T>
inline constexpr optional<std::decay_t<T>> make_optional(T&& value) {
    return std::make_optional(std::forward<T>(value));
}

template <typename CharT, typename Traits = std::char_traits<CharT>>
using basic_string_view = std::basic_string_view<CharT, Traits>;

template <typename CharT, typename Traits = std::char_traits<CharT>>
std::string string_view_to_string(const basic_string_view<CharT, Traits>& v) {
    return std::string(v);
}

template <typename... Types>
using variant = std::variant<Types...>;

template <std::size_t I, typename... Types>
constexpr std::variant_alternative_t<I, variant<Types...>>& get(variant<Types...>& v) {
    return std::get<I>(v);
}

template <std::size_t I, typename... Types>
constexpr const std::variant_alternative_t<I, variant<Types...>>& get(const variant<Types...>& v) {
    return std::get<I>(v);
}

template <std::size_t I, typename... Types>
constexpr std::variant_alternative_t<I, variant<Types...>>&& get(variant<Types...>&& v) {
    return std::get<I>(v);
}

template <std::size_t I, typename... Types>
constexpr const std::variant_alternative_t<I, variant<Types...>>&& get(const variant<Types...>&& v) {
    return std::get<I>(v);
}

template <typename U, typename... Types>
constexpr U& get(variant<Types...>& v) {
    return std::get<U>(v);
}

template <typename U, typename... Types>
constexpr const U& get(const variant<Types...>& v) {
    return std::get<U>(v);
}

template <typename U, typename... Types>
constexpr U&& get(variant<Types...>&& v) {
    return std::get<U>(v);
}

template <typename U, typename... Types>
constexpr const U&& get(const variant<Types...>&& v) {
    return std::get<U>(v);
}

template <typename U, typename... Types>
constexpr U* get_if(variant<Types...>* v) {
    return std::get_if<U>(v);
}

template <typename U, typename... Types>
constexpr const U* get_if(const variant<Types...>* v) {
    return std::get_if<U>(v);
}

using string_view = basic_string_view<char>;

} // namespace compat

/// \endcond

} // namespace seastar

#define SEASTAR_COPY_ELISION(x) x
<commit_msg>std-compat: Delete SEASTAR_COPY_ELISION<commit_after>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  You may not use this file except in compliance with the License.
 *
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
/*
 * Copyright (C) 2018 ScyllaDB
 */

#pragma once

#include <optional>
#include <string_view>
#include <variant>

#include <filesystem>

#include <memory_resource>

namespace seastar {

/// \cond internal

namespace compat {

using memory_resource = std::pmr::memory_resource;

template<typename T>
using polymorphic_allocator = std::pmr::polymorphic_allocator<T>;

static inline
memory_resource* pmr_get_default_resource() {
    return std::pmr::get_default_resource();
}

}

}

// Defining SEASTAR_ASAN_ENABLED in here is a bit of a hack, but
// convenient since it is build system independent and in practice
// everything includes this header.

#ifndef __has_feature
#define __has_feature(x) 0
#endif

// clang uses __has_feature, gcc defines __SANITIZE_ADDRESS__
#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
#define SEASTAR_ASAN_ENABLED
#endif

namespace seastar {

/// \cond internal

namespace compat {

template <typename T>
using optional = std::optional<T>;

using nullopt_t = std::nullopt_t;

inline constexpr auto nullopt = std::nullopt;

template <typename T>
inline constexpr optional<std::decay_t<T>> make_optional(T&& value) {
    return std::make_optional(std::forward<T>(value));
}

template <typename CharT, typename Traits = std::char_traits<CharT>>
using basic_string_view = std::basic_string_view<CharT, Traits>;

template <typename CharT, typename Traits = std::char_traits<CharT>>
std::string string_view_to_string(const basic_string_view<CharT, Traits>& v) {
    return std::string(v);
}

template <typename... Types>
using variant = std::variant<Types...>;

template <std::size_t I, typename... Types>
constexpr std::variant_alternative_t<I, variant<Types...>>& get(variant<Types...>& v) {
    return std::get<I>(v);
}

template <std::size_t I, typename... Types>
constexpr const std::variant_alternative_t<I, variant<Types...>>& get(const variant<Types...>& v) {
    return std::get<I>(v);
}

template <std::size_t I, typename... Types>
constexpr std::variant_alternative_t<I, variant<Types...>>&& get(variant<Types...>&& v) {
    return std::get<I>(v);
}

template <std::size_t I, typename... Types>
constexpr const std::variant_alternative_t<I, variant<Types...>>&& get(const variant<Types...>&& v) {
    return std::get<I>(v);
}

template <typename U, typename... Types>
constexpr U& get(variant<Types...>& v) {
    return std::get<U>(v);
}

template <typename U, typename... Types>
constexpr const U& get(const variant<Types...>& v) {
    return std::get<U>(v);
}

template <typename U, typename... Types>
constexpr U&& get(variant<Types...>&& v) {
    return std::get<U>(v);
}

template <typename U, typename... Types>
constexpr const U&& get(const variant<Types...>&& v) {
    return std::get<U>(v);
}

template <typename U, typename... Types>
constexpr U* get_if(variant<Types...>* v) {
    return std::get_if<U>(v);
}

template <typename U, typename... Types>
constexpr const U* get_if(const variant<Types...>* v) {
    return std::get_if<U>(v);
}

using string_view = basic_string_view<char>;

} // namespace compat

/// \endcond

} // namespace seastar
<|endoftext|>


<commit_before>/***************************************************************************
 * Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *
 * Martin Renou                                                             *
 * Copyright (c) QuantStack                                                 *
 * Copyright (c) Serge Guelton                                              *
 *                                                                          *
 * Distributed under the terms of the BSD 3-Clause License.                 *
 *                                                                          *
 * The full license is in the file LICENSE, distributed with this software. *
 ****************************************************************************/

#ifndef XSIMD_SSSE3_HPP
#define XSIMD_SSSE3_HPP

#include <cstddef>
#include <type_traits>

#include "../types/xsimd_ssse3_register.hpp"
#include "../types/xsimd_utils.hpp"

namespace xsimd
{

    namespace kernel
    {
        using namespace types;

        // abs
        template <class A, class T, typename std::enable_if<std::is_integral<T>::value && std::is_signed<T>::value, void>::type>
        inline batch<T, A> abs(batch<T, A> const& self, requires_arch<ssse3>) noexcept
        {
            switch (sizeof(T))
            {
            case 1:
                return _mm_abs_epi8(self);
            case 2:
                return _mm_abs_epi16(self);
            case 4:
                return _mm_abs_epi32(self);
            case 8:
                return _mm_abs_epi64(self);
            default:
                assert(false && "unsupported arch/op combination");
                return {};
            }
        }

        // extract_pair
        namespace detail
        {

            template <class T, class A>
            inline batch<T, A> extract_pair(batch<T, A> const&, batch<T, A> const& other, std::size_t, ::xsimd::detail::index_sequence<>) noexcept
            {
                return other;
            }

            template <class T, class A, std::size_t I, std::size_t... Is>
            inline batch<T, A> extract_pair(batch<T, A> const& self, batch<T, A> const& other, std::size_t i, ::xsimd::detail::index_sequence<I, Is...>) noexcept
            {
                if (i == I)
                {
                    return _mm_alignr_epi8(self, other, sizeof(T) * I);
                }
                else
                    return extract_pair(self, other, i, ::xsimd::detail::index_sequence<Is...>());
            }
        }

        template <class A, class T, class _ = typename std::enable_if<std::is_integral<T>::value, void>::type>
        inline batch<T, A> extract_pair(batch<T, A> const& self, batch<T, A> const& other, std::size_t i, requires_arch<ssse3>) noexcept
        {
            constexpr std::size_t size = batch<T, A>::size;
            assert(0 <= i && i < size && "index in bounds");
            return detail::extract_pair(self, other, i, ::xsimd::detail::make_index_sequence<size>());
        }

        // hadd
        template <class A, class T, class = typename std::enable_if<std::is_integral<T>::value, void>::type>
        inline T hadd(batch<T, A> const& self, requires_arch<ssse3>) noexcept
        {
            switch (sizeof(T))
            {
            case 2:
            {
                __m128i tmp1 = _mm_hadd_epi16(self, self);
                __m128i tmp2 = _mm_hadd_epi16(tmp1, tmp1);
                __m128i tmp3 = _mm_hadd_epi16(tmp2, tmp2);
                return _mm_cvtsi128_si32(tmp3) & 0xFFFF;
            }
            case 4:
            {
                __m128i tmp1 = _mm_hadd_epi32(self, self);
                __m128i tmp2 = _mm_hadd_epi32(tmp1, tmp1);
                return _mm_cvtsi128_si32(tmp2);
            }
            default:
                return hadd(self, sse3 {});
            }
        }

        // swizzle
        template <class A, uint16_t V0, uint16_t V1, uint16_t V2, uint16_t V3, uint16_t V4, uint16_t V5, uint16_t V6, uint16_t V7>
        inline batch<uint16_t, A> swizzle(batch<uint16_t, A> const& self, batch_constant<batch<uint16_t, A>, V0, V1, V2, V3, V4, V5, V6, V7>, requires_arch<ssse3>) noexcept
        {
            constexpr batch_constant<batch<uint8_t, A>, 2 * V0, 2 * V0 + 1, 2 * V1, 2 * V1 + 1, 2 * V2, 2 * V2 + 1, 2 * V3, 2 * V3 + 1,
                                     2 * V4, 2 * V4 + 1, 2 * V5, 2 * V5 + 1, 2 * V6, 2 * V6 + 1, 2 * V7, 2 * V7 + 1>
                mask8;
            return _mm_shuffle_epi8(self, (batch<uint8_t, A>)mask8);
        }

        template <class A, uint16_t V0, uint16_t V1, uint16_t V2, uint16_t V3, uint16_t V4, uint16_t V5, uint16_t V6, uint16_t V7>
        inline batch<int16_t, A> swizzle(batch<int16_t, A> const& self, batch_constant<batch<uint16_t, A>, V0, V1, V2, V3, V4, V5, V6, V7> mask, requires_arch<ssse3>) noexcept
        {
            return bitwise_cast<int16_t>(swizzle(bitwise_cast<uint16_t>(self), mask, ssse3 {}));
        }

        template <class A, uint8_t V0, uint8_t V1, uint8_t V2, uint8_t V3, uint8_t V4, uint8_t V5, uint8_t V6, uint8_t V7,
                  uint8_t V8, uint8_t V9, uint8_t V10, uint8_t V11, uint8_t V12, uint8_t V13, uint8_t V14, uint8_t V15>
        inline batch<uint8_t, A> swizzle(batch<uint8_t, A> const& self, batch_constant<batch<uint8_t, A>, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15> mask, requires_arch<ssse3>) noexcept
        {
            return _mm_shuffle_epi8(self, (batch<uint8_t, A>)mask);
        }

        template <class A, uint8_t V0, uint8_t V1, uint8_t V2, uint8_t V3, uint8_t V4, uint8_t V5, uint8_t V6, uint8_t V7,
                  uint8_t V8, uint8_t V9, uint8_t V10, uint8_t V11, uint8_t V12, uint8_t V13, uint8_t V14, uint8_t V15>
        inline batch<int8_t, A> swizzle(batch<int8_t, A> const& self, batch_constant<batch<uint8_t, A>, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15> mask, requires_arch<ssse3>) noexcept
        {
            return bitwise_cast<int8_t>(swizzle(bitwise_cast<uint8_t>(self), mask, ssse3 {}));
        }

    }

}

#endif
<commit_msg>Converted the switch cases to XSIMD_IF in xsimd_ssse3.hpp<commit_after>/***************************************************************************
 * Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *
 * Martin Renou                                                             *
 * Copyright (c) QuantStack                                                 *
 * Copyright (c) Serge Guelton                                              *
 *                                                                          *
 * Distributed under the terms of the BSD 3-Clause License.                 *
 *                                                                          *
 * The full license is in the file LICENSE, distributed with this software. *
 ****************************************************************************/

#ifndef XSIMD_SSSE3_HPP
#define XSIMD_SSSE3_HPP

#include <cstddef>
#include <type_traits>

#include "../types/xsimd_ssse3_register.hpp"
#include "../types/xsimd_utils.hpp"

namespace xsimd
{

    namespace kernel
    {
        using namespace types;

        // abs
        template <class A, class T, typename std::enable_if<std::is_integral<T>::value && std::is_signed<T>::value, void>::type>
        inline batch<T, A> abs(batch<T, A> const& self, requires_arch<ssse3>) noexcept
        {
            XSIMD_IF(sizeof(T) == 1)
            {
                return _mm_abs_epi8(self);
            }
            else XSIMD_IF(sizeof(T) == 2)
            {
                return _mm_abs_epi16(self);
            }
            else XSIMD_IF(sizeof(T) == 4)
            {
                return _mm_abs_epi32(self);
            }
            else XSIMD_IF(sizeof(T) == 8)
            {
                return _mm_abs_epi64(self);
            }
            else
            {
                assert(false && "unsupported arch/op combination");
                return {};
            }
        }

        // extract_pair
        namespace detail
        {

            template <class T, class A>
            inline batch<T, A> extract_pair(batch<T, A> const&, batch<T, A> const& other, std::size_t, ::xsimd::detail::index_sequence<>) noexcept
            {
                return other;
            }

            template <class T, class A, std::size_t I, std::size_t... Is>
            inline batch<T, A> extract_pair(batch<T, A> const& self, batch<T, A> const& other, std::size_t i, ::xsimd::detail::index_sequence<I, Is...>) noexcept
            {
                if (i == I)
                {
                    return _mm_alignr_epi8(self, other, sizeof(T) * I);
                }
                else
                    return extract_pair(self, other, i, ::xsimd::detail::index_sequence<Is...>());
            }
        }

        template <class A, class T, class _ = typename std::enable_if<std::is_integral<T>::value, void>::type>
        inline batch<T, A> extract_pair(batch<T, A> const& self, batch<T, A> const& other, std::size_t i, requires_arch<ssse3>) noexcept
        {
            constexpr std::size_t size = batch<T, A>::size;
            assert(0 <= i && i < size && "index in bounds");
            return detail::extract_pair(self, other, i, ::xsimd::detail::make_index_sequence<size>());
        }

        // hadd
        template <class A, class T, class = typename std::enable_if<std::is_integral<T>::value, void>::type>
        inline T hadd(batch<T, A> const& self, requires_arch<ssse3>) noexcept
        {
            XSIMD_IF(sizeof(T) == 2)
            {
                __m128i tmp1 = _mm_hadd_epi16(self, self);
                __m128i tmp2 = _mm_hadd_epi16(tmp1, tmp1);
                __m128i tmp3 = _mm_hadd_epi16(tmp2, tmp2);
                return _mm_cvtsi128_si32(tmp3) & 0xFFFF;
            }
            else XSIMD_IF(sizeof(T) == 4)
            {
                __m128i tmp1 = _mm_hadd_epi32(self, self);
                __m128i tmp2 = _mm_hadd_epi32(tmp1, tmp1);
                return _mm_cvtsi128_si32(tmp2);
            }
            else
            {
                return hadd(self, sse3 {});
            }
        }

        // swizzle
        template <class A, uint16_t V0, uint16_t V1, uint16_t V2, uint16_t V3, uint16_t V4, uint16_t V5, uint16_t V6, uint16_t V7>
        inline batch<uint16_t, A> swizzle(batch<uint16_t, A> const& self, batch_constant<batch<uint16_t, A>, V0, V1, V2, V3, V4, V5, V6, V7>, requires_arch<ssse3>) noexcept
        {
            constexpr batch_constant<batch<uint8_t, A>, 2 * V0, 2 * V0 + 1, 2 * V1, 2 * V1 + 1, 2 * V2, 2 * V2 + 1, 2 * V3, 2 * V3 + 1,
                                     2 * V4, 2 * V4 + 1, 2 * V5, 2 * V5 + 1, 2 * V6, 2 * V6 + 1, 2 * V7, 2 * V7 + 1>
                mask8;
            return _mm_shuffle_epi8(self, (batch<uint8_t, A>)mask8);
        }

        template <class A, uint16_t V0, uint16_t V1, uint16_t V2, uint16_t V3, uint16_t V4, uint16_t V5, uint16_t V6, uint16_t V7>
        inline batch<int16_t, A> swizzle(batch<int16_t, A> const& self, batch_constant<batch<uint16_t, A>, V0, V1, V2, V3, V4, V5, V6, V7> mask, requires_arch<ssse3>) noexcept
        {
            return bitwise_cast<int16_t>(swizzle(bitwise_cast<uint16_t>(self), mask, ssse3 {}));
        }

        template <class A, uint8_t V0, uint8_t V1, uint8_t V2, uint8_t V3, uint8_t V4, uint8_t V5, uint8_t V6, uint8_t V7,
                  uint8_t V8, uint8_t V9, uint8_t V10, uint8_t V11, uint8_t V12, uint8_t V13, uint8_t V14, uint8_t V15>
        inline batch<uint8_t, A> swizzle(batch<uint8_t, A> const& self, batch_constant<batch<uint8_t, A>, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15> mask, requires_arch<ssse3>) noexcept
        {
            return _mm_shuffle_epi8(self, (batch<uint8_t, A>)mask);
        }

        template <class A, uint8_t V0, uint8_t V1, uint8_t V2, uint8_t V3, uint8_t V4, uint8_t V5, uint8_t V6, uint8_t V7,
                  uint8_t V8, uint8_t V9, uint8_t V10, uint8_t V11, uint8_t V12, uint8_t V13, uint8_t V14, uint8_t V15>
        inline batch<int8_t, A> swizzle(batch<int8_t, A> const& self, batch_constant<batch<uint8_t, A>, V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15> mask, requires_arch<ssse3>) noexcept
        {
            return bitwise_cast<int8_t>(swizzle(bitwise_cast<uint8_t>(self), mask, ssse3 {}));
        }

    }

}

#endif
<|endoftext|>


<commit_before>#ifndef MINIASCAPE_PERIODIC_BOUNDARY
#define MINIASCAPE_PERIODIC_BOUNDARY
#include <array>
#include "util/zip_iterator.hpp"
#include "Cell.hpp"

namespace miniascape
{

template<typename T_neighbor>
class PeriodicBoundary
{
  public:
    using neighbor_type   = T_neighbor;
    using cell_index_type = typename neighbor_type::cell_index_type;
    constexpr static std::size_t dimension = neighbor_type::dimension;

  public:
    PeriodicBoundary() = default;
    PeriodicBoundary(const cell_index_type& begin, const cell_index_type& end)
        :begin_(begin), end_(end)
    {}
    ~PeriodicBoundary() = default;

    template<typename T_world>
    typename T_world::cell_ptr const&
    access(const cell_index_type& id, const T_world& world) const;

    template<typename T_world>
    typename T_world::cell_ptr &
    access(const cell_index_type& id, T_world& container) const;

  private:
    // [begin, end)
    cell_index_type begin_; // = (0, ..., 0), normally
    cell_index_type end_;
};

template<typename T_neighbor>
template<typename T_world>
typename T_world::cell_ptr const&
PeriodicBoundary<T_neighbor>::access(
        const cell_index_type& id, const T_world& container) const
{
    cell_index_type index = id;
    for(auto iter = make_zip(index.begin(), begin_.cbegin(), end_.cbegin());
            iter != make_zip(index.end(), begin_.cend(), end_.cend());
            ++iter)
    {
        const std::size_t range = *get<2>(iter) - *get<1>(iter);
        if((*get<0>(iter) < *get<1>(iter)) /* index < begin */||
           (*get<0>(iter) >= *get<2>(iter))/* end <= index  */)
        {
            const int idx = *get<0>(iter) % range;
            *get<0>(iter) = (idx < 0) ? idx + range : idx;
        }
    }
    return container(index);
}

template<typename T_neighbor>
template<typename T_world>
typename T_world::cell_ptr &
PeriodicBoundary<T_neighbor>::access(
        const cell_index_type& id, T_world& container) const
{
    cell_index_type index = id;
    for(auto iter = make_zip(index.begin(), begin_.cbegin(), end_.cbegin());
            iter != make_zip(index.end(), begin_.cend(), end_.cend());
            ++iter)
    {
        const std::size_t range = *get<2>(iter) - *get<1>(iter);
        if((*get<0>(iter) < *get<1>(iter)) /* index < begin */||
           (*get<0>(iter) >= *get<2>(iter))/* end <= index  */)
        {
            const int idx = *get<0>(iter) % range;
            *get<0>(iter) = (idx < 0) ? idx + range : idx;
        }
    }
    return container(index);
}

}

#endif /* MINIASCAPE_PERIODIC_BOUNDARY */
<commit_msg>change type of range in Periodic<commit_after>#ifndef MINIASCAPE_PERIODIC_BOUNDARY
#define MINIASCAPE_PERIODIC_BOUNDARY
#include <array>
#include "util/zip_iterator.hpp"
#include "Cell.hpp"

namespace miniascape
{

template<typename T_neighbor>
class PeriodicBoundary
{
  public:
    using neighbor_type   = T_neighbor;
    using cell_index_type = typename neighbor_type::cell_index_type;
    constexpr static std::size_t dimension = neighbor_type::dimension;

  public:
    PeriodicBoundary() = default;
    PeriodicBoundary(const cell_index_type& begin, const cell_index_type& end)
        :begin_(begin), end_(end)
    {}
    ~PeriodicBoundary() = default;

    template<typename T_world>
    typename T_world::cell_ptr const&
    access(const cell_index_type& id, const T_world& world) const;

    template<typename T_world>
    typename T_world::cell_ptr &
    access(const cell_index_type& id, T_world& container) const;

  private:
    // [begin, end)
    cell_index_type begin_; // = (0, ..., 0), normally
    cell_index_type end_;
};

template<typename T_neighbor>
template<typename T_world>
typename T_world::cell_ptr const&
PeriodicBoundary<T_neighbor>::access(
        const cell_index_type& id, const T_world& container) const
{
    cell_index_type index = id;
    for(auto iter = make_zip(index.begin(), begin_.cbegin(), end_.cbegin());
            iter != make_zip(index.end(), begin_.cend(), end_.cend());
            ++iter)
    {
        const int range = *get<2>(iter) - *get<1>(iter);
        if((*get<0>(iter) < *get<1>(iter)) /* index < begin */||
           (*get<0>(iter) >= *get<2>(iter))/* end <= index  */)
        {
            const int idx = *get<0>(iter) % range;
            *get<0>(iter) = (idx < 0) ? idx + range : idx;
        }
    }
    return container(index);
}

template<typename T_neighbor>
template<typename T_world>
typename T_world::cell_ptr &
PeriodicBoundary<T_neighbor>::access(
        const cell_index_type& id, T_world& container) const
{
    cell_index_type index = id;
    for(auto iter = make_zip(index.begin(), begin_.cbegin(), end_.cbegin());
            iter != make_zip(index.end(), begin_.cend(), end_.cend());
            ++iter)
    {
        const int range = *get<2>(iter) - *get<1>(iter);
        if((*get<0>(iter) < *get<1>(iter)) /* index < begin */||
           (*get<0>(iter) >= *get<2>(iter))/* end <= index  */)
        {
            const int idx = *get<0>(iter) % range;
            *get<0>(iter) = (idx < 0) ? idx + range : idx;
        }
    }
    return container(index);
}

}

#endif /* MINIASCAPE_PERIODIC_BOUNDARY */
<|endoftext|>