<commit_before>#include <glog/logging.h>
#include <openssl/bio.h>
#include <openssl/ssl.h>
#include <openssl/x509.h>

#include "cert.h"
#include "cert_submission_handler.h"
#include "client.h"
#include "log_verifier.h"
#include "ssl_client.h"

using ct::SignedCertificateTimestamp;
using ct::CertificateEntry;
using std::string;

SSLClient::SSLClient(const string &server, uint16_t port,
                     const string &ca_dir, LogVerifier *verifier)
    : client_(server, port),
      ctx_(NULL),
      verify_args_(verifier),
      connected_(false) {
  ctx_ = SSL_CTX_new(TLSv1_client_method());
  CHECK_NOTNULL(ctx_);

  // SSL_VERIFY_PEER makes the connection abort immediately
  // if verification fails.
  SSL_CTX_set_verify(ctx_, SSL_VERIFY_PEER, NULL);
  // Set trusted CA certs.
  if (!ca_dir.empty()) {
    CHECK_EQ(1, SSL_CTX_load_verify_locations(ctx_, NULL, ca_dir.c_str()))
        << "Unable to load trusted CA certificates.";
  } else {
    LOG(WARNING) << "No trusted CA certificates given.";
  }

  // The verify callback gets called before the audit proof callback.
  SSL_CTX_set_cert_verify_callback(ctx_, &VerifyCallback, &verify_args_);
#ifdef TLSEXT_AUTHZDATAFORMAT_audit_proof
    SSL_CTX_set_tlsext_authz_server_audit_proof_cb(ctx_, &SCTTokenCallback);
    SSL_CTX_set_tlsext_authz_server_audit_proof_cb_arg(ctx_, &verify_args_);
#endif
}

SSLClient::~SSLClient() {
  Disconnect();
  if (ctx_ != NULL)
    SSL_CTX_free(ctx_);
  delete verify_args_.verifier;
}

bool SSLClient::Connected() const {
  return connected_;
}

void SSLClient::Disconnect() {
  if (ssl_ != NULL) {
    SSL_shutdown(ssl_);
    SSL_free(ssl_);
    ssl_ = NULL;
    LOG(INFO) << "SSL session finished";
  }
  client_.Disconnect();
  connected_ = false;
}

bool SSLClient::GetToken(SignedCertificateTimestamp *sct) const {
  CHECK(Connected());
  if (verify_args_.token_verified) {
    sct->CopyFrom(verify_args_.sct);
    return true;
  }
  return false;
}

// static
LogVerifier::VerifyResult
SSLClient::VerifySCT(const string &token, const CertChain &chain,
                     LogVerifier *verifier, SignedCertificateTimestamp *sct) {
  CertificateEntry entry;
  if (CertSubmissionHandler::X509ChainToEntry(chain, &entry) !=
      SubmissionHandler::OK)
    return LogVerifier::INVALID_FORMAT;

  SignedCertificateTimestamp local_sct;
  if (Deserializer::DeserializeSCTToken(token, &local_sct) != Deserializer::OK)
    return LogVerifier::INVALID_FORMAT;

  local_sct.mutable_entry()->CopyFrom(entry);

  LogVerifier::VerifyResult result =
      verifier->VerifySignedCertificateTimestamp(local_sct);
  if (result != LogVerifier::VERIFY_OK)
    return result;
  sct->CopyFrom(local_sct);
  return LogVerifier::VERIFY_OK;
}

// static
int SSLClient::VerifyCallback(X509_STORE_CTX *ctx, void *arg) {
  VerifyCallbackArgs *args = reinterpret_cast<VerifyCallbackArgs*>(arg);
  CHECK_NOTNULL(args);
  LogVerifier *verifier = args->verifier;
  CHECK_NOTNULL(verifier);

  int vfy = X509_verify_cert(ctx);
  if (vfy != 1) {
    LOG(ERROR) << "Certificate verification failed.";
    return vfy;
  }

  // If verify passed then surely we must have a cert.
  CHECK_NOTNULL(ctx->cert);

  CertChain chain;
  // ctx->untrusted is the chain of X509s, as passed in.
  // Let's hope OpenSSL keeps them in the order they were passed in.
  STACK_OF(X509) *sk = ctx->untrusted;
  CHECK_NOTNULL(sk);
  int chain_size = sk_X509_num(sk);
  // Should contain at least the leaf.
  CHECK_GE(chain_size, 1);
  for (int i = 0; i < chain_size; ++i)
    chain.AddCert(new Cert(sk_X509_value(sk, i)));

  string token;
  // First, see if the cert has an embedded proof.
  if (chain.LeafCert()->HasExtension(Cert::kEmbeddedProofExtensionOID)) {
    LOG(INFO) << "Embedded proof extension found in certificate, "
              << "verifying...";
    token = chain.LeafCert()->ExtensionData(Cert::kEmbeddedProofExtensionOID);
    // Else look for the proof in a superfluous cert.
    // Let's assume the superfluous cert is always last in the chain.
  } else if (chain.Length() > 1 && chain.LastCert()->HasExtension(
      Cert::kProofExtensionOID)) {
    LOG(INFO) << "Proof extension found in certificate, verifying...";
    token = chain.LastCert()->ExtensionData(
        Cert::kProofExtensionOID);
    chain.RemoveCert();
  }

  if (!token.empty()) {
    // Only writes the checkpoint if verification succeeds.
    // Note: an optimized client could only verify the signature if it's
    // a certificate it hasn't seen before.
    LogVerifier::VerifyResult result = VerifySCT(token, chain,
                                                 verifier, &args->sct);

    if (result == LogVerifier::VERIFY_OK) {
      LOG(INFO) << "Token verified";
      args->token_verified = true;
    } else {
      LOG(ERROR) << "Verification failed: "
                 << LogVerifier::VerifyResultString(result);
    }
  }

#ifndef TLSEXT_AUTHZDATAFORMAT_audit_proof
  // If we don't support the TLS extension, we fail here. Else we wait to see
  // if the extension callback finds a valid proof.
  if (!args->token_verified && args->require_token) {
    LOG(ERROR) << "No valid SCT found";
    return 0;
  }
#endif
  return 1;
}

#ifdef TLSEXT_AUTHZDATAFORMAT_audit_proof
// static
int SSLClient::SCTTokenCallback(SSL *s, void *arg) {
  VerifyCallbackArgs *args = reinterpret_cast<VerifyCallbackArgs*>(arg);
  CHECK_NOTNULL(args);
  // If we already received the proof in a superfluous cert, do nothing.
  if (args->token_verified)
    return 1;

  LogVerifier *verifier = args->verifier;
  CHECK_NOTNULL(verifier);

  SSL_SESSION *sess = SSL_get_session(s);
  // Get the leaf certificate.
  X509 *x509 = SSL_SESSION_get0_peer(sess);
  CHECK_NOTNULL(x509);

  // Get the token.
  size_t proof_length;
  unsigned char *proof =
      SSL_SESSION_get_tlsext_authz_server_audit_proof(sess, &proof_length);
  if (proof == NULL) {
    LOG(WARNING) << "No SCT received.";
    return args->require_token ? 0 : 1;
  }

  LOG(INFO) << "Found an SCT token in the TLS extension, verifying...";

  string token(reinterpret_cast<byte*>(proof), proof_length);
  Cert *leaf = new Cert(x509);
  CertChain chain;
  chain.AddCert(leaf);

  LogVerifier::VerifyResult result =
      VerifySCT(token, chain, verifier, &args->sct);

  if (result == LogVerifier::VERIFY_OK) {
    args->token_verified = true;
    LOG(INFO) << "Token verified";
    return 1;
  } else {
    LOG(ERROR) << "Verification failed: "
               << LogVerifier::VerifyResultString(result);
    return args->require_token ? 0 : 1;
  }
}
#endif

void SSLClient::ResetVerifyCallbackArgs(bool strict) {
  verify_args_.token_verified = false;
  verify_args_.require_token = strict;
  verify_args_.sct.CopyFrom(SignedCertificateTimestamp::default_instance());
}

SSLClient::HandshakeResult SSLClient::SSLConnect(bool strict) {
  if (!client_.Connect())
    return SERVER_UNAVAILABLE;

  ssl_ = SSL_new(ctx_);
  CHECK_NOTNULL(ssl_);
  BIO *bio = BIO_new_socket(client_.fd(), BIO_NOCLOSE);
  CHECK_NOTNULL(bio);
  // Takes ownership of bio.
  SSL_set_bio(ssl_, bio, bio);

  ResetVerifyCallbackArgs(strict);
  int ret = SSL_connect(ssl_);
  HandshakeResult result;
  if (ret == 1) {
    LOG(INFO) << "Handshake successful. SSL session started";
    connected_ = true;
    DCHECK(!verify_args_.require_token || verify_args_.token_verified);
    result = OK;
  } else {
    // TODO(ekasper): look into OpenSSL error stack to determine
    // the error reason. Could be unrelated to SCT verification.
    LOG(ERROR) << "SSL handshake failed";
    result = HANDSHAKE_FAILED;
    Disconnect();
  }
  return result;
}
<commit_msg>[mq]: Fix broken build<commit_after>#include <glog/logging.h>
#include <openssl/bio.h>
#include <openssl/ssl.h>
#include <openssl/x509.h>

#include "cert.h"
#include "cert_submission_handler.h"
#include "client.h"
#include "log_verifier.h"
#include "ssl_client.h"

using ct::SignedCertificateTimestamp;
using ct::CertificateEntry;
using std::string;

SSLClient::SSLClient(const string &server, uint16_t port,
                     const string &ca_dir, LogVerifier *verifier)
    : client_(server, port),
      ctx_(NULL),
      verify_args_(verifier),
      connected_(false) {
  ctx_ = SSL_CTX_new(TLSv1_client_method());
  CHECK_NOTNULL(ctx_);

  // SSL_VERIFY_PEER makes the connection abort immediately
  // if verification fails.
  SSL_CTX_set_verify(ctx_, SSL_VERIFY_PEER, NULL);
  // Set trusted CA certs.
  if (!ca_dir.empty()) {
    CHECK_EQ(1, SSL_CTX_load_verify_locations(ctx_, NULL, ca_dir.c_str()))
        << "Unable to load trusted CA certificates.";
  } else {
    LOG(WARNING) << "No trusted CA certificates given.";
  }

  // The verify callback gets called before the audit proof callback.
  SSL_CTX_set_cert_verify_callback(ctx_, &VerifyCallback, &verify_args_);
#ifdef TLSEXT_AUTHZDATAFORMAT_audit_proof
    SSL_CTX_set_tlsext_authz_server_audit_proof_cb(ctx_, &SCTTokenCallback);
    SSL_CTX_set_tlsext_authz_server_audit_proof_cb_arg(ctx_, &verify_args_);
#endif
}

SSLClient::~SSLClient() {
  Disconnect();
  if (ctx_ != NULL)
    SSL_CTX_free(ctx_);
  delete verify_args_.verifier;
}

bool SSLClient::Connected() const {
  return connected_;
}

void SSLClient::Disconnect() {
  if (ssl_ != NULL) {
    SSL_shutdown(ssl_);
    SSL_free(ssl_);
    ssl_ = NULL;
    LOG(INFO) << "SSL session finished";
  }
  client_.Disconnect();
  connected_ = false;
}

bool SSLClient::GetToken(SignedCertificateTimestamp *sct) const {
  CHECK(Connected());
  if (verify_args_.token_verified) {
    sct->CopyFrom(verify_args_.sct);
    return true;
  }
  return false;
}

// static
LogVerifier::VerifyResult
SSLClient::VerifySCT(const string &token, const CertChain &chain,
                     LogVerifier *verifier, SignedCertificateTimestamp *sct) {
  CertificateEntry entry;
  if (CertSubmissionHandler::X509ChainToEntry(chain, &entry) !=
      SubmissionHandler::OK)
    return LogVerifier::INVALID_FORMAT;

  SignedCertificateTimestamp local_sct;
  if (Deserializer::DeserializeSCTToken(token, &local_sct) != Deserializer::OK)
    return LogVerifier::INVALID_FORMAT;

  local_sct.mutable_entry()->CopyFrom(entry);

  LogVerifier::VerifyResult result =
      verifier->VerifySignedCertificateTimestamp(local_sct);
  if (result != LogVerifier::VERIFY_OK)
    return result;
  sct->CopyFrom(local_sct);
  return LogVerifier::VERIFY_OK;
}

// static
int SSLClient::VerifyCallback(X509_STORE_CTX *ctx, void *arg) {
  VerifyCallbackArgs *args = reinterpret_cast<VerifyCallbackArgs*>(arg);
  CHECK_NOTNULL(args);
  LogVerifier *verifier = args->verifier;
  CHECK_NOTNULL(verifier);

  int vfy = X509_verify_cert(ctx);
  if (vfy != 1) {
    LOG(ERROR) << "Certificate verification failed.";
    return vfy;
  }

  // If verify passed then surely we must have a cert.
  CHECK_NOTNULL(ctx->cert);

  CertChain chain;
  // ctx->untrusted is the chain of X509s, as passed in.
  // Let's hope OpenSSL keeps them in the order they were passed in.
  STACK_OF(X509) *sk = ctx->untrusted;
  CHECK_NOTNULL(sk);
  int chain_size = sk_X509_num(sk);
  // Should contain at least the leaf.
  CHECK_GE(chain_size, 1);
  for (int i = 0; i < chain_size; ++i)
    chain.AddCert(new Cert(sk_X509_value(sk, i)));

  string token;
  // First, see if the cert has an embedded proof.
  if (chain.LeafCert()->HasExtension(Cert::kEmbeddedProofExtensionOID)) {
    LOG(INFO) << "Embedded proof extension found in certificate, "
              << "verifying...";
    token = chain.LeafCert()->ExtensionData(Cert::kEmbeddedProofExtensionOID);
    // Else look for the proof in a superfluous cert.
    // Let's assume the superfluous cert is always last in the chain.
  } else if (chain.Length() > 1 && chain.LastCert()->HasExtension(
      Cert::kProofExtensionOID)) {
    LOG(INFO) << "Proof extension found in certificate, verifying...";
    token = chain.LastCert()->ExtensionData(
        Cert::kProofExtensionOID);
    chain.RemoveCert();
  }

  if (!token.empty()) {
    // Only writes the checkpoint if verification succeeds.
    // Note: an optimized client could only verify the signature if it's
    // a certificate it hasn't seen before.
    LogVerifier::VerifyResult result = VerifySCT(token, chain,
                                                 verifier, &args->sct);

    if (result == LogVerifier::VERIFY_OK) {
      LOG(INFO) << "Token verified";
      args->token_verified = true;
    } else {
      LOG(ERROR) << "Verification failed: "
                 << LogVerifier::VerifyResultString(result);
    }
  }

#ifndef TLSEXT_AUTHZDATAFORMAT_audit_proof
  // If we don't support the TLS extension, we fail here. Else we wait to see
  // if the extension callback finds a valid proof.
  if (!args->token_verified && args->require_token) {
    LOG(ERROR) << "No valid SCT found";
    return 0;
  }
#endif
  return 1;
}

#ifdef TLSEXT_AUTHZDATAFORMAT_audit_proof
// static
int SSLClient::SCTTokenCallback(SSL *s, void *arg) {
  VerifyCallbackArgs *args = reinterpret_cast<VerifyCallbackArgs*>(arg);
  CHECK_NOTNULL(args);
  // If we already received the proof in a superfluous cert, do nothing.
  if (args->token_verified)
    return 1;

  LogVerifier *verifier = args->verifier;
  CHECK_NOTNULL(verifier);

  SSL_SESSION *sess = SSL_get_session(s);
  // Get the leaf certificate.
  X509 *x509 = SSL_SESSION_get0_peer(sess);
  CHECK_NOTNULL(x509);

  // Get the token.
  size_t proof_length;
  unsigned char *proof =
      SSL_SESSION_get_tlsext_authz_server_audit_proof(sess, &proof_length);
  if (proof == NULL) {
    LOG(WARNING) << "No SCT received.";
    return args->require_token ? 0 : 1;
  }

  LOG(INFO) << "Found an SCT token in the TLS extension, verifying...";

  string token(reinterpret_cast<char*>(proof), proof_length);
  Cert *leaf = new Cert(x509);
  CertChain chain;
  chain.AddCert(leaf);

  LogVerifier::VerifyResult result =
      VerifySCT(token, chain, verifier, &args->sct);

  if (result == LogVerifier::VERIFY_OK) {
    args->token_verified = true;
    LOG(INFO) << "Token verified";
    return 1;
  } else {
    LOG(ERROR) << "Verification failed: "
               << LogVerifier::VerifyResultString(result);
    return args->require_token ? 0 : 1;
  }
}
#endif

void SSLClient::ResetVerifyCallbackArgs(bool strict) {
  verify_args_.token_verified = false;
  verify_args_.require_token = strict;
  verify_args_.sct.CopyFrom(SignedCertificateTimestamp::default_instance());
}

SSLClient::HandshakeResult SSLClient::SSLConnect(bool strict) {
  if (!client_.Connect())
    return SERVER_UNAVAILABLE;

  ssl_ = SSL_new(ctx_);
  CHECK_NOTNULL(ssl_);
  BIO *bio = BIO_new_socket(client_.fd(), BIO_NOCLOSE);
  CHECK_NOTNULL(bio);
  // Takes ownership of bio.
  SSL_set_bio(ssl_, bio, bio);

  ResetVerifyCallbackArgs(strict);
  int ret = SSL_connect(ssl_);
  HandshakeResult result;
  if (ret == 1) {
    LOG(INFO) << "Handshake successful. SSL session started";
    connected_ = true;
    DCHECK(!verify_args_.require_token || verify_args_.token_verified);
    result = OK;
  } else {
    // TODO(ekasper): look into OpenSSL error stack to determine
    // the error reason. Could be unrelated to SCT verification.
    LOG(ERROR) << "SSL handshake failed";
    result = HANDSHAKE_FAILED;
    Disconnect();
  }
  return result;
}
<|endoftext|>


<commit_before>#include "button.hpp"
#include "event.hpp"
#include "impl/opengl.h"

UI::Button::Button()
    : /* title_(), */ state_(false), hover_(false), button_(-1)
{
    // title_ = RasterText::create();
    bounds_.width = 150;
    bounds_.height = 30;
}

UI::Button::~Button()
{ }

void UI::Button::setLoc(int x, int y)
{
    bounds_.x = x;
    bounds_.y = y;
}

void UI::Button::setText(std::string const &text)
{
    (void) &text;
    // title_->setText(text);
}

void UI::Button::draw()
{
    glPushAttrib(GL_COLOR_BUFFER_BIT | GL_CURRENT_BIT);

    float x1 = (float) bounds_.x, x2 = (float) bounds_.x + bounds_.width;
    float y1 = (float) bounds_.y, y2 = (float) bounds_.y + bounds_.height;

    if (!state_)
        glColor3ub(32, 0, 0);
    else
        glColor3ub(255, 128, 0);
    glBegin(GL_TRIANGLE_STRIP);
    glVertex2f(x1, y1);
    glVertex2f(x1, y2);
    glVertex2f(x2, y1);
    glVertex2f(x2, y2);
    glEnd();

    if (!state_)
        glColor3ub(255, 64, 64);
    else
        glColor3ub(64, 0, 0);
    glBegin(GL_LINE_LOOP);
    glVertex2f(x1, y1);
    glVertex2f(x1, y2);
    glVertex2f(x2, y2);
    glVertex2f(x2, y1);
    glEnd();

    if (hover_ || button_ == ButtonLeft) {
        glColor3ub(255, 255, 255);
        glBegin(GL_LINE_LOOP);
        glVertex2f(x1 - 2.0f, y1 - 2.0f);
        glVertex2f(x1 - 2.0f, y2 + 2.0f);
        glVertex2f(x2 + 2.0f, y2 + 2.0f);
        glVertex2f(x2 + 2.0f, y1 - 2.0f);
        glEnd();
    }

    if (!state_)
        glColor3ub(255, 64, 64);
    else
        glColor3ub(64, 0, 0);
    glPushMatrix();
    glTranslatef(x1 + 5.0f, y1 + 10.0f, 0.0f);
    glEnable(GL_BLEND);
    glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR);
    // title_->draw();
    glPopMatrix();

    glPopAttrib();
}

void UI::Button::mouseEntered(UI::MouseEvent const &)
{
    if (button_ == ButtonLeft)
        state_ = true;
    hover_ = true;
}

void UI::Button::mouseExited(UI::MouseEvent const &)
{
    if (button_ == ButtonLeft)
        state_ = false;
    hover_ = false;
}

void UI::Button::mouseDown(UI::MouseEvent const &evt)
{
    if (button_ < 0) {
        button_ = evt.button;
        if (button_ == ButtonLeft)
            state_ = bounds().contains(evt.x, evt.y);
    }
}

void UI::Button::mouseUp(UI::MouseEvent const &evt)
{
    bool doAction;
    if (button_ == evt.button) {
        doAction = state_ && button_ == ButtonLeft;
        button_ = -1;
        state_ = false;
        if (doAction)
            action_();
    }
}

void UI::Button::setAction(UI::Action const &action)
{
    action_ = action;
}
<commit_msg>Fix button drawing glitches<commit_after>#include "button.hpp"
#include "event.hpp"
#include "impl/opengl.h"

UI::Button::Button()
    : /* title_(), */ state_(false), hover_(false), button_(-1)
{
    // title_ = RasterText::create();
    bounds_.width = 150;
    bounds_.height = 30;
}

UI::Button::~Button()
{ }

void UI::Button::setLoc(int x, int y)
{
    bounds_.x = x;
    bounds_.y = y;
}

void UI::Button::setText(std::string const &text)
{
    (void) &text;
    // title_->setText(text);
}

void UI::Button::draw()
{
    glPushAttrib(GL_COLOR_BUFFER_BIT | GL_CURRENT_BIT);

    float x1 = (float) bounds_.x, x2 = (float) bounds_.x + bounds_.width;
    float y1 = (float) bounds_.y, y2 = (float) bounds_.y + bounds_.height;

    if (!state_)
        glColor3ub(32, 0, 0);
    else
        glColor3ub(255, 128, 0);
    glBegin(GL_TRIANGLE_STRIP);
    glVertex2f(x1, y1);
    glVertex2f(x1, y2);
    glVertex2f(x2, y1);
    glVertex2f(x2, y2);
    glEnd();

    if (!state_)
        glColor3ub(255, 64, 64);
    else
        glColor3ub(64, 0, 0);
    glBegin(GL_LINE_LOOP);
    glVertex2f(x1-0.5f, y1-0.5f);
    glVertex2f(x1-0.5f, y2+0.5f);
    glVertex2f(x2+0.5f, y2+0.5f);
    glVertex2f(x2+0.5f, y1-0.5f);
    glEnd();

    if (hover_ || button_ == ButtonLeft) {
        glColor3ub(255, 255, 255);
        glBegin(GL_LINE_LOOP);
        glVertex2f(x1 - 2.5f, y1 - 2.5f);
        glVertex2f(x1 - 2.5f, y2 + 2.5f);
        glVertex2f(x2 + 2.5f, y2 + 2.5f);
        glVertex2f(x2 + 2.5f, y1 - 2.5f);
        glEnd();
    }

    if (!state_)
        glColor3ub(255, 64, 64);
    else
        glColor3ub(64, 0, 0);
    glPushMatrix();
    glTranslatef(x1 + 5.0f, y1 + 10.0f, 0.0f);
    glEnable(GL_BLEND);
    glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR);
    // title_->draw();
    glPopMatrix();

    glPopAttrib();
}

void UI::Button::mouseEntered(UI::MouseEvent const &)
{
    if (button_ == ButtonLeft)
        state_ = true;
    hover_ = true;
}

void UI::Button::mouseExited(UI::MouseEvent const &)
{
    if (button_ == ButtonLeft)
        state_ = false;
    hover_ = false;
}

void UI::Button::mouseDown(UI::MouseEvent const &evt)
{
    if (button_ < 0) {
        button_ = evt.button;
        if (button_ == ButtonLeft)
            state_ = bounds().contains(evt.x, evt.y);
    }
}

void UI::Button::mouseUp(UI::MouseEvent const &evt)
{
    bool doAction;
    if (button_ == evt.button) {
        doAction = state_ && button_ == ButtonLeft;
        button_ = -1;
        state_ = false;
        if (doAction)
            action_();
    }
}

void UI::Button::setAction(UI::Action const &action)
{
    action_ = action;
}
<|endoftext|>


<commit_before>///////////////////////////////////////////////////////////////////////////////
//
// File: BlockMatrix.hpp
//
// For more information, please see: http://www.nektar.info
//
// The MIT License
//
// Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
// Department of Aeronautics, Imperial College London (UK), and Scientific
// Computing and Imaging Institute, University of Utah (USA).
//
// License for the specific language governing rights and limitations under
// 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.
//
// Description:
//
///////////////////////////////////////////////////////////////////////////////

#ifndef NEKTAR_LIB_UTILITIES_LINEAR_ALGEBRA_BLOCK_MATRIX_HPP
#define NEKTAR_LIB_UTILITIES_LINEAR_ALGEBRA_BLOCK_MATRIX_HPP

#include <LibUtilities/LinearAlgebra/MatrixBase.hpp>
#include <LibUtilities/BasicUtils/BinaryExpressionTraits.hpp>
#include <LibUtilities/BasicUtils/SharedArray.hpp>

#include <boost/shared_ptr.hpp>

namespace Nektar
{
    template<typename DataType, typename StorageType, typename OwnedMatrixType>
    class NekMatrix<NekMatrix<DataType, StorageType, OwnedMatrixType>, StorageType, BlockMatrixTag> : public Matrix<DataType>
    {
        public:
            typedef Matrix<DataType> BaseType;
            typedef NekMatrix<DataType, StorageType, OwnedMatrixType> InnerMatrixType;
            typedef NekMatrix<InnerMatrixType, StorageType, ScaledMatrixTag> ThisType;
            typedef typename InnerMatrixType::GetValueType GetValueType;
            typedef typename InnerMatrixType::ConstGetValueType ConstGetValueType;

        public:
            NekMatrix(unsigned int numberOfBlockRows, unsigned int numberOfBlockColumns,
                      unsigned int rowsPerBlock, unsigned int columnsPerBlock) :
                BaseType(numberOfBlockRows*rowsPerBlock, numberOfBlockColumns*columnsPerBlock),
                m_data(numberOfBlockRows, numberOfBlockColumns, boost::shared_ptr<InnerMatrixType>()),
                m_rowSizes(numberOfBlockRows+1),
                m_columnSizes(numberOfBlockColumns+1),
                m_storageSize(this->GetRows()*this->GetColumns())
            {
                for(unsigned int i = 1; i <= numberOfBlockRows; ++i)
                {
                    m_rowSizes[i-1] = i*rowsPerBlock-1;
                }

                for(unsigned int i = 1; i <= numberOfBlockColumns; ++i)
                {
                    m_columnSizes[i-1] = i*columnsPerBlock-1;
                }
            }

            NekMatrix(unsigned int numberOfBlockRows, unsigned int numberOfBlockColumns,
                      unsigned int* rowsPerBlock, unsigned int* columnsPerBlock) :
                BaseType(std::accumulate(rowsPerBlock, rowsPerBlock + numberOfBlockRows, 0),
                         std::accumulate(columnsPerBlock, columnsPerBlock + numberOfBlockColumns, 0)),
                m_data(numberOfBlockRows, numberOfBlockColumns, boost::shared_ptr<InnerMatrixType>()),
                m_rowSizes(numberOfBlockRows+1),
                m_columnSizes(numberOfBlockColumns+1),
                m_storageSize(this->GetRows()*this->GetColumns())
            {
                m_rowSizes[0] = rowsPerBlock[0] - 1;
                for(unsigned int i = 1; i < numberOfBlockRows; ++i)
                {
                    m_rowSizes[i] = rowsPerBlock[i] + m_rowSizes[i-1];
                }

                m_columnSizes[0] = columnsPerBlock[0] - 1;
                for(unsigned int i = 1; i < numberOfBlockColumns; ++i)
                {
                    m_columnSizes[i] = columnsPerBlock[i] + m_columnSizes[i-1];
                }
            }

            boost::shared_ptr<const InnerMatrixType> GetBlock(unsigned int row, unsigned int column) const
            {
                ASSERTL2(row < m_data.GetRows(), std::string("Row ") + boost::lexical_cast<std::string>(row) +
                    std::string(" requested in a block matrix with a maximum of ") + boost::lexical_cast<std::string>(m_data.GetRows()) +
                    std::string(" rows"));
                ASSERTL2(column < m_data.GetColumns(), std::string("Column ") + boost::lexical_cast<std::string>(column) +
                    std::string(" requested in a block matrix with a maximum of ") + boost::lexical_cast<std::string>(m_data.GetColumns()) +
                    std::string(" columns"));
                return m_data[row][column];
            }

            boost::shared_ptr<InnerMatrixType> GetBlock(unsigned int row, unsigned int column)
            {
                ASSERTL2(row < m_data.GetRows(), std::string("Row ") + boost::lexical_cast<std::string>(row) +
                    std::string(" requested in a block matrix with a maximum of ") + boost::lexical_cast<std::string>(m_data.GetRows()) +
                    std::string(" rows"));
                ASSERTL2(column < m_data.GetColumns(), std::string("Column ") + boost::lexical_cast<std::string>(column) +
                    std::string(" requested in a block matrix with a maximum of ") + boost::lexical_cast<std::string>(m_data.GetColumns()) +
                    std::string(" columns"));
                return m_data[row][column];
            }

            void SetBlock(unsigned int row, unsigned int column, boost::shared_ptr<InnerMatrixType>& m)
            {
                ASSERTL2(row < m_data.GetRows(), std::string("Row ") + boost::lexical_cast<std::string>(row) +
                    std::string(" requested in a block matrix with a maximum of ") + boost::lexical_cast<std::string>(m_data.GetRows()) +
                    std::string(" rows"));
                ASSERTL2(column < m_data.GetColumns(), std::string("Column ") + boost::lexical_cast<std::string>(column) +
                    std::string(" requested in a block matrix with a maximum of ") + boost::lexical_cast<std::string>(m_data.GetColumns()) +
                    std::string(" columns"));
                m_data[row][column] = m;
            }

            ConstGetValueType operator()(unsigned int row, unsigned int col) const
            {
                ASSERTL2(row < this->GetRows(), std::string("Row ") + boost::lexical_cast<std::string>(row) +
                    std::string(" requested in a matrix with a maximum of ") + boost::lexical_cast<std::string>(this->GetRows()) +
                    std::string(" rows"));
                ASSERTL2(column < this->GetColumns(), std::string("Column ") + boost::lexical_cast<std::string>(column) +
                    std::string(" requested in a matrix with a maximum of ") + boost::lexical_cast<std::string>(this->GetColumns()) +
                    std::string(" columns"));

                unsigned int blockRow = std::lower_bound(m_rowSizes.begin(), m_rowSizes.end(), row) - m_rowSizes.begin();
                unsigned int blockColumn = std::lower_bound(m_columnSizes.begin(), m_columnSizes.end(), col) - m_columnSizes.begin();
                unsigned int actualRow = row-(m_rowSizes[blockRow]-1);
                unsigned int actualCol = col-(m_columnSizes[blockColumn]-1);

                ASSERTL2(GetBlock(blockRow, blockColumn), std::string("Attempting to access block (") +
                    boost::lexical_cast<std::string>(blockRow) + std::string(", ") +
                    boost::lexical_cast<std::string>(blockColumn) + std::string(") of a block matrix but it is null."));

                return GetBlock(blockRow, blockColumn)->operator()(actualRow, actualCol);
            }

            GetValueType operator()(unsigned int row, unsigned int col)
            {
                ASSERTL2(row < this->GetRows(), std::string("Row ") + boost::lexical_cast<std::string>(row) +
                    std::string(" requested in a matrix with a maximum of ") + boost::lexical_cast<std::string>(this->GetRows()) +
                    std::string(" rows"));
                ASSERTL2(column < this->GetColumns(), std::string("Column ") + boost::lexical_cast<std::string>(column) +
                    std::string(" requested in a matrix with a maximum of ") + boost::lexical_cast<std::string>(this->GetColumns()) +
                    std::string(" columns"));

                unsigned int blockRow = std::lower_bound(m_rowSizes.begin(), m_rowSizes.end(), row) - m_rowSizes.begin();
                unsigned int blockColumn = std::lower_bound(m_columnSizes.begin(), m_columnSizes.end(), col) - m_columnSizes.begin();
                unsigned int actualRow = row-(m_rowSizes[blockRow]-1);
                unsigned int actualCol = col-(m_columnSizes[blockColumn]-1);

                ASSERTL2(GetBlock(blockRow, blockColumn), std::string("Attempting to access block (") +
                    boost::lexical_cast<std::string>(blockRow) + std::string(", ") +
                    boost::lexical_cast<std::string>(blockColumn) + std::string(") of a block matrix but it is null."));

                return GetBlock(blockRow, blockColumn)->operator()(actualRow, actualCol);
            }

            unsigned int GetStorageSize() const
            {
                return m_storageSize;
            }

            MatrixStorage GetStorageType() const
            {
                return static_cast<MatrixStorage>(ConvertToMatrixStorageEnum<StorageType>::Value);
            }

        public:

        private:
            virtual typename boost::call_traits<DataType>::value_type v_GetValue(unsigned int row, unsigned int column) const
            {
                return (*this)(row, column);
            }

            virtual unsigned int v_GetStorageSize() const
            {
                return this->GetStorageSize();
            }

            virtual MatrixStorage v_GetStorageType() const
            {
                return this->GetStorageType();
            }

            virtual void v_SetValue(unsigned int row, unsigned int column, typename boost::call_traits<DataType>::const_reference d)
            {
                (*this)(row, column) = d;
            }

            Array<TwoD, boost::shared_ptr<InnerMatrixType> > m_data;
            Array<OneD, unsigned int> m_rowSizes;
            Array<OneD, unsigned int> m_columnSizes;
            unsigned int m_storageSize;
    };

}

#endif //NEKTAR_LIB_UTILITIES_LINEAR_ALGEBRA_BLOCK_MATRIX_HPP
<commit_msg>Made some clarifying changes to the typedefs.<commit_after>///////////////////////////////////////////////////////////////////////////////
//
// File: BlockMatrix.hpp
//
// For more information, please see: http://www.nektar.info
//
// The MIT License
//
// Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
// Department of Aeronautics, Imperial College London (UK), and Scientific
// Computing and Imaging Institute, University of Utah (USA).
//
// License for the specific language governing rights and limitations under
// 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.
//
// Description:
//
///////////////////////////////////////////////////////////////////////////////

#ifndef NEKTAR_LIB_UTILITIES_LINEAR_ALGEBRA_BLOCK_MATRIX_HPP
#define NEKTAR_LIB_UTILITIES_LINEAR_ALGEBRA_BLOCK_MATRIX_HPP

#include <LibUtilities/LinearAlgebra/MatrixBase.hpp>
#include <LibUtilities/BasicUtils/BinaryExpressionTraits.hpp>
#include <LibUtilities/BasicUtils/SharedArray.hpp>
#include <LibUtilities/LinearAlgebra/FullMatrixStoragePolicy.hpp>
#include <LibUtilities/LinearAlgebra/DiagonalMatrixStoragePolicy.hpp>

#include <boost/shared_ptr.hpp>

namespace Nektar
{
    template<typename DataType, typename InnerStorageType, typename InnerMatrixType, typename OuterStorageType>
    class NekMatrix<NekMatrix<DataType, InnerStorageType, InnerMatrixType>, OuterStorageType, BlockMatrixTag> : public Matrix<DataType>
    {
        public:
            typedef Matrix<DataType> BaseType;
            typedef NekMatrix<DataType, InnerStorageType, InnerMatrixType> InnerType;
            typedef NekMatrix<InnerType, OuterStorageType, BlockMatrixTag> ThisType;

            // Each inner matrix type can possible return references or value types from GetValue.
            // Query the type here to find out.
            typedef typename InnerType::GetValueType GetValueType;
            typedef typename InnerType::ConstGetValueType ConstGetValueType;

            typedef MatrixStoragePolicy<boost::shared_ptr<InnerType>, OuterStorageType> StoragePolicy;

        public:
            NekMatrix(unsigned int numberOfBlockRows, unsigned int numberOfBlockColumns,
                      unsigned int rowsPerBlock, unsigned int columnsPerBlock) :
                BaseType(numberOfBlockRows*rowsPerBlock, numberOfBlockColumns*columnsPerBlock),
                m_data(StoragePolicy::Initialize(numberOfBlockRows, numberOfBlockColumns, boost::shared_ptr<InnerType>())),
                m_rowSizes(numberOfBlockRows+1),
                m_columnSizes(numberOfBlockColumns+1),
                m_storageSize(this->GetRows()*this->GetColumns()),
                m_numberOfBlockRows(numberOfBlockRows),
                m_numberOfBlockColumns(numberOfBlockColumns)
            {
                for(unsigned int i = 1; i <= numberOfBlockRows; ++i)
                {
                    m_rowSizes[i-1] = i*rowsPerBlock-1;
                }

                for(unsigned int i = 1; i <= numberOfBlockColumns; ++i)
                {
                    m_columnSizes[i-1] = i*columnsPerBlock-1;
                }
            }

            NekMatrix(unsigned int numberOfBlockRows, unsigned int numberOfBlockColumns,
                      unsigned int* rowsPerBlock, unsigned int* columnsPerBlock) :
                BaseType(std::accumulate(rowsPerBlock, rowsPerBlock + numberOfBlockRows, 0),
                         std::accumulate(columnsPerBlock, columnsPerBlock + numberOfBlockColumns, 0)),
                m_data(StoragePolicy::Initialize(numberOfBlockRows, numberOfBlockColumns, boost::shared_ptr<InnerType>())),
                m_rowSizes(numberOfBlockRows+1),
                m_columnSizes(numberOfBlockColumns+1),
                m_storageSize(this->GetRows()*this->GetColumns()),
                m_numberOfBlockRows(numberOfBlockRows),
                m_numberOfBlockColumns(numberOfBlockColumns)
            {
                m_rowSizes[0] = rowsPerBlock[0] - 1;
                for(unsigned int i = 1; i < numberOfBlockRows; ++i)
                {
                    m_rowSizes[i] = rowsPerBlock[i] + m_rowSizes[i-1];
                }

                m_columnSizes[0] = columnsPerBlock[0] - 1;
                for(unsigned int i = 1; i < numberOfBlockColumns; ++i)
                {
                    m_columnSizes[i] = columnsPerBlock[i] + m_columnSizes[i-1];
                }
            }

            boost::shared_ptr<const InnerType> GetBlock(unsigned int row, unsigned int column) const
            {
                ASSERTL2(row < m_numberOfBlockRows, std::string("Row ") + boost::lexical_cast<std::string>(row) +
                    std::string(" requested in a block matrix with a maximum of ") + boost::lexical_cast<std::string>(m_numberOfBlockRows) +
                    std::string(" rows"));
                ASSERTL2(column < m_numberOfBlockColumns, std::string("Column ") + boost::lexical_cast<std::string>(column) +
                    std::string(" requested in a block matrix with a maximum of ") + boost::lexical_cast<std::string>(m_numberOfBlockColumns) +
                    std::string(" columns"));
                return StoragePolicy::GetValue(m_numberOfBlockRows, m_numberOfBlockColumns, row, column, m_data);
            }

            boost::shared_ptr<InnerType> GetBlock(unsigned int row, unsigned int column)
            {
                ASSERTL2(row < m_numberOfBlockRows, std::string("Row ") + boost::lexical_cast<std::string>(row) +
                    std::string(" requested in a block matrix with a maximum of ") + boost::lexical_cast<std::string>(m_numberOfBlockRows) +
                    std::string(" rows"));
                ASSERTL2(column < m_numberOfBlockColumns, std::string("Column ") + boost::lexical_cast<std::string>(column) +
                    std::string(" requested in a block matrix with a maximum of ") + boost::lexical_cast<std::string>(m_numberOfBlockColumns) +
                    std::string(" columns"));
                return StoragePolicy::GetValue(m_numberOfBlockRows, m_numberOfBlockColumns, row, column, m_data);
            }

            void SetBlock(unsigned int row, unsigned int column, boost::shared_ptr<InnerType>& m)
            {
                ASSERTL2(row < m_numberOfBlockRows, std::string("Row ") + boost::lexical_cast<std::string>(row) +
                    std::string(" requested in a block matrix with a maximum of ") + boost::lexical_cast<std::string>(m_numberOfBlockRows) +
                    std::string(" rows"));
                ASSERTL2(column < m_numberOfBlockColumns, std::string("Column ") + boost::lexical_cast<std::string>(column) +
                    std::string(" requested in a block matrix with a maximum of ") + boost::lexical_cast<std::string>(m_numberOfBlockColumns) +
                    std::string(" columns"));
                StoragePolicy::SetValue(m_numberOfBlockRows, m_numberOfBlockColumns, row, column, m_data, m);
            }

            ConstGetValueType operator()(unsigned int row, unsigned int col) const
            {
                ASSERTL2(row < this->GetRows(), std::string("Row ") + boost::lexical_cast<std::string>(row) +
                    std::string(" requested in a matrix with a maximum of ") + boost::lexical_cast<std::string>(this->GetRows()) +
                    std::string(" rows"));
                ASSERTL2(column < this->GetColumns(), std::string("Column ") + boost::lexical_cast<std::string>(column) +
                    std::string(" requested in a matrix with a maximum of ") + boost::lexical_cast<std::string>(this->GetColumns()) +
                    std::string(" columns"));

                unsigned int blockRow = std::lower_bound(m_rowSizes.begin(), m_rowSizes.end(), row) - m_rowSizes.begin();
                unsigned int blockColumn = std::lower_bound(m_columnSizes.begin(), m_columnSizes.end(), col) - m_columnSizes.begin();
                unsigned int actualRow = row-(m_rowSizes[blockRow]-1);
                unsigned int actualCol = col-(m_columnSizes[blockColumn]-1);

                ASSERTL2(GetBlock(blockRow, blockColumn), std::string("Attempting to access block (") +
                    boost::lexical_cast<std::string>(blockRow) + std::string(", ") +
                    boost::lexical_cast<std::string>(blockColumn) + std::string(") of a block matrix but it is null."));

                return GetBlock(blockRow, blockColumn)->operator()(actualRow, actualCol);
            }

            GetValueType operator()(unsigned int row, unsigned int col)
            {
                ASSERTL2(row < this->GetRows(), std::string("Row ") + boost::lexical_cast<std::string>(row) +
                    std::string(" requested in a matrix with a maximum of ") + boost::lexical_cast<std::string>(this->GetRows()) +
                    std::string(" rows"));
                ASSERTL2(column < this->GetColumns(), std::string("Column ") + boost::lexical_cast<std::string>(column) +
                    std::string(" requested in a matrix with a maximum of ") + boost::lexical_cast<std::string>(this->GetColumns()) +
                    std::string(" columns"));

                unsigned int blockRow = std::lower_bound(m_rowSizes.begin(), m_rowSizes.end(), row) - m_rowSizes.begin();
                unsigned int blockColumn = std::lower_bound(m_columnSizes.begin(), m_columnSizes.end(), col) - m_columnSizes.begin();
                unsigned int actualRow = row-(m_rowSizes[blockRow]-1);
                unsigned int actualCol = col-(m_columnSizes[blockColumn]-1);

                ASSERTL2(GetBlock(blockRow, blockColumn), std::string("Attempting to access block (") +
                    boost::lexical_cast<std::string>(blockRow) + std::string(", ") +
                    boost::lexical_cast<std::string>(blockColumn) + std::string(") of a block matrix but it is null."));

                return GetBlock(blockRow, blockColumn)->operator()(actualRow, actualCol);
            }

            unsigned int GetStorageSize() const
            {
                return m_storageSize;
            }

            MatrixStorage GetStorageType() const
            {
                return static_cast<MatrixStorage>(ConvertToMatrixStorageEnum<OuterStorageType>::Value);
            }

            unsigned int GetNumberOfBlockRows() const { return m_numberOfBlockRows; }
            unsigned int GetNumberOfBlockColumns() const { return m_numberOfBlockColumns; }

        public:

        private:
            virtual typename boost::call_traits<DataType>::value_type v_GetValue(unsigned int row, unsigned int column) const
            {
                return (*this)(row, column);
            }

            virtual unsigned int v_GetStorageSize() const
            {
                return this->GetStorageSize();
            }

            virtual MatrixStorage v_GetStorageType() const
            {
                return this->GetStorageType();
            }

            virtual void v_SetValue(unsigned int row, unsigned int column, typename boost::call_traits<DataType>::const_reference d)
            {
                (*this)(row, column) = d;
            }

            Array<OneD, boost::shared_ptr<InnerType> > m_data;
            Array<OneD, unsigned int> m_rowSizes;
            Array<OneD, unsigned int> m_columnSizes;
            unsigned int m_storageSize;
            unsigned int m_numberOfBlockRows;
            unsigned int m_numberOfBlockColumns;
    };

}

#endif //NEKTAR_LIB_UTILITIES_LINEAR_ALGEBRA_BLOCK_MATRIX_HPP
<|endoftext|>


<commit_before>//////////////////////////////////////////////////////////////////////////////
// oxygenargbhelper.h
// handle oxygen ARGB (translucent windows) support
// -------------------
//
// Copyright (c) 2010 Hugo Pereira Da Costa <hugo@oxygen-icons.org>
//
// Loosely inspired (and largely rewritten) from BeSpin style
// Copyright (C) 2007 Thomas Luebking <thomas.luebking@web.de>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//////////////////////////////////////////////////////////////////////////////

#include "oxygenargbhelper.h"
#include "oxygenargbhelper.moc"

#include <QtGui/QDialog>
#include <QtGui/QIcon>

namespace Oxygen
{

    //______________________________________________________________
    ArgbHelper::ArgbHelper( QObject* parent, StyleHelper& helper ):
        QObject( parent ),
        _helper( helper ),
        _applicationType( AppUnknown ),
        _enabled( false ),
        _opacity( 0xff )
    {}

    //______________________________________________________________
    void ArgbHelper::registerApplication( QApplication* app )
    {

        // get application full path
        if( app->argc() < 1 ) return;

        QString appName( app->argv()[0] );
        int position( appName.lastIndexOf( '/' ) );
        if( position >= 0 ) appName.remove( 0, position+1 );

        if( appName == "plasma" || appName.startsWith( "plasma-" ) )
        {

            /*
            HACK: need to detect if application is of type Plasma
            because applying translucency to some of its widgets creates
            painting issues which could not be identified with a 'generic'
            criteria.
            */
            _applicationType = AppPlasma;

        } else if( _blackList.contains( appName ) ) {

            // black-list application
            _applicationType = AppBlackListed;

        }

    }

    //______________________________________________________________
    bool ArgbHelper::registerWidget( QWidget *widget )
    {

        // check blacklisted applications
        if( _applicationType == AppBlackListed ) return false;

        // adjust flags for windows and dialogs
        switch( widget->windowFlags() & Qt::WindowType_Mask )
        {

            case Qt::Window:
            case Qt::Dialog:
            {

                // do not handle all kind of 'special background' widgets
                if( widget->windowType() == Qt::Desktop ||
                    widget->testAttribute(Qt::WA_X11NetWmWindowTypeDesktop) ||
                    widget->testAttribute(Qt::WA_NoSystemBackground) ||
                    widget->testAttribute(Qt::WA_PaintOnScreen)
                    ) break;

                // disable kde screensaver windows
                /*
                the kscreensaver widgets get a WA_PaintOnScreen flag set,
                which should have been covered by the above, but somehow the flag is set too late,
                and notably after polish is called. Or so it seems.
                */
                if( widget->inherits( "KScreenSaver" ) ) break;

                // Hack: stop here if application is of type Plasma
                /*
                Right now we need to reject window candidates if the application is of type plasma
                because it conflicts with some widgets embedded into the SysTray. Ideally one would
                rather find a "generic" reason, not to handle them
                */
                if( _applicationType == AppPlasma && !qobject_cast<QDialog*>(widget) ) break;

                // stop here if no translucent background selected/supported
                if( !( _helper.compositingActive() && enabled() ) ) break;

                // more tests
                if( !widget->isWindow() ) break;
                if(
                    widget->inherits( "QTipLabel") ||
                    widget->inherits( "QSplashScreen") ) break;

                if( widget->windowFlags().testFlag( Qt::FramelessWindowHint ) ) break;

                if( widget->testAttribute(Qt::WA_WState_Created) || widget->internalWinId() )
                { setupTransparency( widget ); }

                return true;
            }

            default: break;

        }

        return false;

    }

    //______________________________________________________________
    bool ArgbHelper::unregisterWidget( QWidget* widget )
    {

        if( _transparentWidgets.contains( widget ) )
        {
            widget->setAttribute(Qt::WA_NoSystemBackground, false);
            widget->setAttribute(Qt::WA_TranslucentBackground, false);
            return true;
        }

        return false;

    }

    //_______________________________________________________
    bool ArgbHelper::eventFilter( QObject* object, QEvent* event )
    {

        // check event type
        if( event->type() != QEvent::WinIdChange ) return false;

        // cast widget
        if( QWidget* widget = static_cast<QWidget*>( object ) )
        { setupTransparency( widget ); }

        return false;

    }

    //______________________________________________________________
    void ArgbHelper::setupTransparency( QWidget* widget )
    {

        if( _transparentWidgets.contains( widget ) ) return;

        // some extra protection
        if( !(widget->testAttribute(Qt::WA_WState_Created) || widget->internalWinId() )) return;

        // translucent background already set. Do nothing.
        if( widget->testAttribute(Qt::WA_TranslucentBackground) )
        {
            // set Argb xproperty
            _helper.setHasArgb( widget->winId(), true );
            return;
        }

        /*
        whenever you set the translucency flag, Qt will create a new widget under the hood, replacing the old
        Unfortunately some properties are lost, among them the window icon. We save it and restore it manually
        */

        // store icon
        QIcon icon(widget->windowIcon());

        // store position
        QPoint position( widget->x(), widget->y() );

        // set translucent flag
        widget->setAttribute( Qt::WA_TranslucentBackground );

        // re-install icon
        widget->setWindowIcon(icon);
        if( !widget->isVisible() ) widget->move( position );

        // add to set of transparent widgets and connect destruction signal
        _transparentWidgets.insert( widget );
        connect( widget, SIGNAL( destroyed( QObject* ) ), SLOT( unregisterTransparentWidget( QObject* ) ) );

        // set Argb xproperty
        _helper.setHasArgb( widget->winId(), true );

        return;
    }

}
<commit_msg>Partially reverted commit 5da27ddabfea100c91926b038a48ce0b06c06a38. CCBUG: 274285<commit_after>//////////////////////////////////////////////////////////////////////////////
// oxygenargbhelper.h
// handle oxygen ARGB (translucent windows) support
// -------------------
//
// Copyright (c) 2010 Hugo Pereira Da Costa <hugo@oxygen-icons.org>
//
// Loosely inspired (and largely rewritten) from BeSpin style
// Copyright (C) 2007 Thomas Luebking <thomas.luebking@web.de>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//////////////////////////////////////////////////////////////////////////////

#include "oxygenargbhelper.h"
#include "oxygenargbhelper.moc"

#include <QtGui/QDialog>
#include <QtGui/QIcon>

namespace Oxygen
{

    //______________________________________________________________
    ArgbHelper::ArgbHelper( QObject* parent, StyleHelper& helper ):
        QObject( parent ),
        _helper( helper ),
        _applicationType( AppUnknown ),
        _enabled( false ),
        _opacity( 0xff )
    {}

    //______________________________________________________________
    void ArgbHelper::registerApplication( QApplication* app )
    {

        // get application full path
        if( app->argc() < 1 ) return;

        QString appName( app->argv()[0] );
        int position( appName.lastIndexOf( '/' ) );
        if( position >= 0 ) appName.remove( 0, position+1 );

        if( appName == "plasma" || appName.startsWith( "plasma-" ) )
        {

            /*
            HACK: need to detect if application is of type Plasma
            because applying translucency to some of its widgets creates
            painting issues which could not be identified with a 'generic'
            criteria.
            */
            _applicationType = AppPlasma;

        } else if( _blackList.contains( appName ) ) {

            // black-list application
            _applicationType = AppBlackListed;

        }

    }

    //______________________________________________________________
    bool ArgbHelper::registerWidget( QWidget *widget )
    {

        // check blacklisted applications
        if( _applicationType == AppBlackListed ) return false;

        // adjust flags for windows and dialogs
        switch( widget->windowFlags() & Qt::WindowType_Mask )
        {

            case Qt::Window:
            case Qt::Dialog:
            {

                // do not handle all kind of 'special background' widgets
                if( widget->windowType() == Qt::Desktop ||
                    widget->testAttribute(Qt::WA_X11NetWmWindowTypeDesktop) ||
                    widget->testAttribute(Qt::WA_NoSystemBackground) ||
                    widget->testAttribute(Qt::WA_PaintOnScreen)
                    ) break;

                // disable kde screensaver windows
                /*
                the kscreensaver widgets get a WA_PaintOnScreen flag set,
                which should have been covered by the above, but somehow the flag is set too late,
                and notably after polish is called. Or so it seems.
                */
                if( widget->inherits( "KScreenSaver" ) ) break;

                // Hack: stop here if application is of type Plasma
                /*
                Right now we need to reject window candidates if the application is of type plasma
                because it conflicts with some widgets embedded into the SysTray. Ideally one would
                rather find a "generic" reason, not to handle them
                */
                if( _applicationType == AppPlasma && !qobject_cast<QDialog*>(widget) ) break;

                // stop here if no translucent background selected/supported
                if( !( _helper.compositingActive() && enabled() ) ) break;

                // more tests
                if( !widget->isWindow() ) break;
                if(
                    widget->inherits( "QTipLabel") ||
                    widget->inherits( "QSplashScreen") ) break;

                if( widget->windowFlags().testFlag( Qt::FramelessWindowHint ) ) break;

                if( widget->testAttribute(Qt::WA_WState_Created) || widget->internalWinId() )
                { setupTransparency( widget ); }

                return true;
            }

            default: break;

        }

        return false;

    }

    //______________________________________________________________
    bool ArgbHelper::unregisterWidget( QWidget* widget )
    {

        if( _transparentWidgets.contains( widget ) )
        {
            widget->setAttribute(Qt::WA_NoSystemBackground, false);
            widget->setAttribute(Qt::WA_TranslucentBackground, false);
            return true;
        }

        return false;

    }

    //_______________________________________________________
    bool ArgbHelper::eventFilter( QObject* object, QEvent* event )
    {

        // check event type
        if( event->type() != QEvent::WinIdChange ) return false;

        // cast widget
        if( QWidget* widget = static_cast<QWidget*>( object ) )
        { setupTransparency( widget ); }

        return false;

    }

    //______________________________________________________________
    void ArgbHelper::setupTransparency( QWidget* widget )
    {

        if( _transparentWidgets.contains( widget ) ) return;

        // some extra protection
        if( !(widget->testAttribute(Qt::WA_WState_Created) || widget->internalWinId() )) return;

        // translucent background already set. Do nothing.
        if( widget->testAttribute(Qt::WA_TranslucentBackground) )
        {
            // set Argb xproperty
            _helper.setHasArgb( widget->winId(), true );
            return;
        }

        /*
        whenever you set the translucency flag, Qt will create a new widget under the hood, replacing the old
        Unfortunately some properties are lost, among them the window icon. We save it and restore it manually
        */

        // store icon
        QIcon icon(widget->windowIcon());

        /*
        WORKAROUND (imported from bespin, thanks Thomas!):
        somehow the window gets repositioned to <1,<1 and thus always appears in the upper left corner
        we just move it faaaaar away so kwin will take back control and apply smart placement or whatever
        */
        QPoint position( 10000, 10000 );

        // set translucent flag
        widget->setAttribute( Qt::WA_TranslucentBackground );

        // re-install icon
        widget->setWindowIcon(icon);
        if( !widget->isVisible() ) widget->move( position );

        // add to set of transparent widgets and connect destruction signal
        _transparentWidgets.insert( widget );
        connect( widget, SIGNAL( destroyed( QObject* ) ), SLOT( unregisterTransparentWidget( QObject* ) ) );

        // set Argb xproperty
        _helper.setHasArgb( widget->winId(), true );

        return;
    }

}
<|endoftext|>


<commit_before>#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include "seriesanalyzer.h"

#define BUFFER_LENGTH 1280
#define OUTPUT_BUFFER_LENGTH 16

real str2real(const std::string &str);
int str2int(const std::string &str);

int main(int argc, char *argv[])
{
    std::ifstream fstream;
    SeriesAnalyzer analyzer;
    uint row = 0;
    uint column = 0;
    std::string str;
    char delim = '\t';
    bool f_output = false;
    std::ofstream ofstream;

    while( (--argc > 0) && ((*++argv)[0] == '-') ) {
            char option = *++argv[0];
            switch (option) {
            case 'i':
                fstream.open(++(*argv));
                break;
            case 'r':
                str = (++(*argv));
                row = str2int(str);
                break;
            case 'c':
                str = (++(*argv));
                column = str2int(str);
                break;
            case 'w':
                str = (++(*argv));
                analyzer.setWindowsize( str2int(str) );
                break;
            case 'o':
                str = (++(*argv));
                analyzer.setOverlaysize( str2int(str) );
                break;
            case 'k':
                str = (++(*argv));
                analyzer.setIntervalFactor( str2real(str) );
                break;
            case 'd':
                delim = *(++(*argv));
                break;
            case 'f':
                f_output = true;
                ofstream.open(++(*argv));
                break;
            case 'h':
                std::cout << APP_NAME << " v." << APP_VERS << "\n"
                          << "Options:\n"
                          << " -i[filename] - input filename\n"
                          << " -r[row] - set start row number\n"
                          << " -c[col] - set column\n"
                          << " -w[x] - set window size to x, default: " << SERIESANALYZER_WINDOWSIZE << "\n"
                          << " -o[x] - set overlay to x, default: " << SERIESANALYZER_OVERLAYSIZE << "\n"
                          << " -k[x] - set confidence interval koeffitient to x, default: " << SERIESANALYZER_INTERVALFACTOR << "\n"
                          << " -d[x] - deliminator symbol, default tabulation\n"
                          << " -f[filename] - output filename, output containes all counts with marks\n" << APP_DESIGNER;
                return 0;
            }
    }

    if(!fstream.is_open())   {
        std::cout << "Failed to open input file" << std::endl;
        return -1;
    }

    if(f_output)
        if(!ofstream.is_open()) {
            std::cout << "Failed to open output file" << std::endl;
            return -2;
        }

    char buffer[BUFFER_LENGTH];
    std::string tempstr;
    real tempvalue = 0.0;
    for(uint i = 0; i < row; i++)
        if(fstream)
            fstream.getline(buffer,BUFFER_LENGTH,'\n');
    while(fstream)  {
        for(uint j = 0; j < column; j++)
            fstream.getline(buffer,BUFFER_LENGTH, delim);
        fstream.getline(buffer,BUFFER_LENGTH,'\n');
        tempstr = buffer;
        tempvalue = str2real(tempstr);
        analyzer.enrollNextValue(tempvalue);
        //std::cout << buffer << std::endl;
    }
    analyzer.endAnalysis();

    int n = analyzer.getRecordsCount();
    std::cout << "File processed, " << n << " series found:" << std::endl;
    DataSeria seria;
    for(int i = 0; i < n; i++)  {
        seria = analyzer.getRecord(i);
        std::cout << "Seria" << i+1 << ":\t" << seria.startframe
                  << " - " << seria.endframe << ", type " << seria.type
                  << std::endl;
    }

    if(f_output) {
        char oline[OUTPUT_BUFFER_LENGTH];
        std::sprintf(oline, "Frame%cProctype", delim);
        ofstream.write(oline, 14);
        for(int i = 0; i < n; i++) {
            seria = analyzer.getRecord(i);
            for(int j = seria.startframe; j < seria.endframe; j++) {
                std::sprintf(oline,"\n%06d%c%d", j, delim, seria.type);
                ofstream.write(oline, 9);
            }
        }
        std::cout << "Output file recorded";
    }
    return 0;
}

real str2real(const std::string &str)
{
     std::istringstream ss(str);
     real result;
     return (ss >> result ? result : 0);
}

int str2int(const std::string &str)
{
     std::istringstream ss(str);
     int result;
     return (ss >> result ? result : 0);
}
<commit_msg>endframe fixed<commit_after>#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include "seriesanalyzer.h"

#define BUFFER_LENGTH 1280
#define OUTPUT_BUFFER_LENGTH 16

real str2real(const std::string &str);
int str2int(const std::string &str);

int main(int argc, char *argv[])
{
    std::ifstream fstream;
    SeriesAnalyzer analyzer;
    uint row = 0;
    uint column = 0;
    std::string str;
    char delim = '\t';
    bool f_output = false;
    std::ofstream ofstream;

    while( (--argc > 0) && ((*++argv)[0] == '-') ) {
            char option = *++argv[0];
            switch (option) {
            case 'i':
                fstream.open(++(*argv));
                break;
            case 'r':
                str = (++(*argv));
                row = str2int(str);
                break;
            case 'c':
                str = (++(*argv));
                column = str2int(str);
                break;
            case 'w':
                str = (++(*argv));
                analyzer.setWindowsize( str2int(str) );
                break;
            case 'o':
                str = (++(*argv));
                analyzer.setOverlaysize( str2int(str) );
                break;
            case 'k':
                str = (++(*argv));
                analyzer.setIntervalFactor( str2real(str) );
                break;
            case 'd':
                delim = *(++(*argv));
                break;
            case 'f':
                f_output = true;
                ofstream.open(++(*argv));
                break;
            case 'h':
                std::cout << APP_NAME << " v." << APP_VERS << "\n"
                          << "Options:\n"
                          << " -i[filename] - input filename\n"
                          << " -r[row] - set start row number\n"
                          << " -c[col] - set column\n"
                          << " -w[x] - set window size to x, default: " << SERIESANALYZER_WINDOWSIZE << "\n"
                          << " -o[x] - set overlay to x, default: " << SERIESANALYZER_OVERLAYSIZE << "\n"
                          << " -k[x] - set confidence interval koeffitient to x, default: " << SERIESANALYZER_INTERVALFACTOR << "\n"
                          << " -d[x] - deliminator symbol, default tabulation\n"
                          << " -f[filename] - output filename, output containes all counts with marks\n" << APP_DESIGNER;
                return 0;
            }
    }

    if(!fstream.is_open())   {
        std::cout << "Failed to open input file" << std::endl;
        return -1;
    }

    if(f_output)
        if(!ofstream.is_open()) {
            std::cout << "Failed to open output file" << std::endl;
            return -2;
        }

    char buffer[BUFFER_LENGTH];
    std::string tempstr;
    real tempvalue = 0.0;
    for(uint i = 0; i < row; i++)
        if(fstream)
            fstream.getline(buffer,BUFFER_LENGTH,'\n');
    while(fstream)  {
        for(uint j = 0; j < column; j++)
            fstream.getline(buffer,BUFFER_LENGTH, delim);
        fstream.getline(buffer,BUFFER_LENGTH,'\n');
        tempstr = buffer;
        tempvalue = str2real(tempstr);
        analyzer.enrollNextValue(tempvalue);
        //std::cout << buffer << std::endl;
    }
    analyzer.endAnalysis();

    int n = analyzer.getRecordsCount();
    std::cout << "File processed, " << n << " series found:" << std::endl;
    DataSeria seria;
    for(int i = 0; i < n; i++)  {
        seria = analyzer.getRecord(i);
        std::cout << "Seria" << i+1 << ":\t" << seria.startframe
                  << " - " << seria.endframe << ", type " << seria.type
                  << std::endl;
    }

    if(f_output) {
        char oline[OUTPUT_BUFFER_LENGTH];
        std::sprintf(oline, "Frame%cProctype", delim);
        ofstream.write(oline, 14);
        for(int i = 0; i < n; i++) {
            seria = analyzer.getRecord(i);
            for(int j = seria.startframe; j <= seria.endframe; j++) {
                std::sprintf(oline,"\n%06d%c%d", j, delim, seria.type);
                ofstream.write(oline, 9);
            }
        }
        std::cout << "Output file recorded";
    }
    return 0;
}

real str2real(const std::string &str)
{
     std::istringstream ss(str);
     real result;
     return (ss >> result ? result : 0);
}

int str2int(const std::string &str)
{
     std::istringstream ss(str);
     int result;
     return (ss >> result ? result : 0);
}
<|endoftext|>


<commit_before>// @(#)root/minuit2:$Id$
// Authors: M. Winkler, F. James, L. Moneta, A. Zsenei   2003-2005

/**********************************************************************
 *                                                                    *
 * Copyright (c) 2005 LCG ROOT Math team,  CERN/PH-SFT                *
 *                                                                    *
 **********************************************************************/

#include "Minuit2/Numerical2PGradientCalculator.h"
#include "Minuit2/InitialGradientCalculator.h"
#include "Minuit2/MnFcn.h"
#include "Minuit2/MnUserTransformation.h"
#include "Minuit2/MnMachinePrecision.h"
#include "Minuit2/MinimumParameters.h"
#include "Minuit2/FunctionGradient.h"
#include "Minuit2/MnStrategy.h"
#include "Minuit2/MnPrint.h"

#ifdef _OPENMP
#include <omp.h>
#endif

#include <cmath>
#include <cassert>
#include <iomanip>

#include "Minuit2/MPIProcess.h"

namespace ROOT {

namespace Minuit2 {

FunctionGradient Numerical2PGradientCalculator::operator()(const MinimumParameters &par) const
{
   // calculate gradient using Initial gradient calculator and from MinimumParameters object

   InitialGradientCalculator gc(fFcn, fTransformation, fStrategy);
   FunctionGradient gra = gc(par);

   return (*this)(par, gra);
}

// comment it, because it was added
FunctionGradient Numerical2PGradientCalculator::operator()(const std::vector<double> &params) const
{
   // calculate gradient from an std;:vector of paramteters

   int npar = params.size();

   MnAlgebraicVector par(npar);
   for (int i = 0; i < npar; ++i) {
      par(i) = params[i];
   }

   double fval = Fcn()(par);

   MinimumParameters minpars = MinimumParameters(par, fval);

   return (*this)(minpars);
}

FunctionGradient Numerical2PGradientCalculator::
operator()(const MinimumParameters &par, const FunctionGradient &Gradient) const
{
   // calculate numerical gradient from MinimumParameters object
   // the algorithm takes correctly care when the gradient is approximatly zero

   //    std::cout<<"########### Numerical2PDerivative"<<std::endl;
   //    std::cout<<"initial grd: "<<Gradient.Grad()<<std::endl;
   //    std::cout<<"position: "<<par.Vec()<<std::endl;
   MnPrint print("Numerical2PGradientCalculator");

   assert(par.IsValid());

   double fcnmin = par.Fval();
   //   std::cout<<"fval: "<<fcnmin<<std::endl;

   double eps2 = Precision().Eps2();
   double eps = Precision().Eps();

   print.Debug("Assumed precision eps", eps, "eps2", eps2);

   double dfmin = 8. * eps2 * (std::fabs(fcnmin) + Fcn().Up());
   double vrysml = 8. * eps * eps;
   //   double vrysml = std::max(1.e-4, eps2);
   //    std::cout<<"dfmin= "<<dfmin<<std::endl;
   //    std::cout<<"vrysml= "<<vrysml<<std::endl;
   //    std::cout << " ncycle " << Ncycle() << std::endl;

   unsigned int n = (par.Vec()).size();
   unsigned int ncycle = Ncycle();
   //   MnAlgebraicVector vgrd(n), vgrd2(n), vgstp(n);
   MnAlgebraicVector grd = Gradient.Grad();
   MnAlgebraicVector g2 = Gradient.G2();
   MnAlgebraicVector gstep = Gradient.Gstep();

   print.Debug("Calculating gradient around value", fcnmin, "at point", par.Vec());

#ifndef _OPENMP

   MPIProcess mpiproc(n, 0);

   // for serial execution this can be outside the loop
   MnAlgebraicVector x = par.Vec();

   unsigned int startElementIndex = mpiproc.StartElementIndex();
   unsigned int endElementIndex = mpiproc.EndElementIndex();

   for (unsigned int i = startElementIndex; i < endElementIndex; i++) {

#else

   // parallelize this loop using OpenMP
//#define N_PARALLEL_PAR 5
#pragma omp parallel
#pragma omp for
   //#pragma omp for schedule (static, N_PARALLEL_PAR)

   for (int i = 0; i < int(n); i++) {

#endif

#ifdef _OPENMP
      // create in loop since each thread will use its own copy
      MnAlgebraicVector x = par.Vec();
#endif

      double xtf = x(i);
      double epspri = eps2 + std::fabs(grd(i) * eps2);
      double stepb4 = 0.;
      for (unsigned int j = 0; j < ncycle; j++) {
         double optstp = std::sqrt(dfmin / (std::fabs(g2(i)) + epspri));
         double step = std::max(optstp, std::fabs(0.1 * gstep(i)));
         //       std::cout<<"step: "<<step;
         if (Trafo().Parameter(Trafo().ExtOfInt(i)).HasLimits()) {
            if (step > 0.5)
               step = 0.5;
         }
         double stpmax = 10. * std::fabs(gstep(i));
         if (step > stpmax)
            step = stpmax;
         //       std::cout<<" "<<step;
         double stpmin = std::max(vrysml, 8. * std::fabs(eps2 * x(i)));
         if (step < stpmin)
            step = stpmin;
         //       std::cout<<" "<<step<<std::endl;
         //       std::cout<<"step: "<<step<<std::endl;
         if (std::fabs((step - stepb4) / step) < StepTolerance()) {
            //    std::cout<<"(step-stepb4)/step"<<std::endl;
            //    std::cout<<"j= "<<j<<std::endl;
            //    std::cout<<"step= "<<step<<std::endl;
            break;
         }
         gstep(i) = step;
         stepb4 = step;
         //       MnAlgebraicVector pstep(n);
         //       pstep(i) = step;
         //       double fs1 = Fcn()(pstate + pstep);
         //       double fs2 = Fcn()(pstate - pstep);

         x(i) = xtf + step;
         double fs1 = Fcn()(x);
         x(i) = xtf - step;
         double fs2 = Fcn()(x);
         x(i) = xtf;

         double grdb4 = grd(i);
         grd(i) = 0.5 * (fs1 - fs2) / step;
         g2(i) = (fs1 + fs2 - 2. * fcnmin) / step / step;

#ifdef _OPENMP
#pragma omp critical
#endif
         {
#ifdef _OPENMP
            // must create thread-local MnPrint instances when printing inside threads
            MnPrint print("Numerical2PGradientCalculator[OpenMP]");
#endif
            if (i == 0 && j == 0) {
               print.Debug([&](std::ostream &os) {
                  os << std::setw(10) << "parameter" << std::setw(6) << "cycle" << std::setw(15) << "x" << std::setw(15)
                     << "step" << std::setw(15) << "f1" << std::setw(15) << "f2" << std::setw(15) << "grd"
                     << std::setw(15) << "g2" << std::endl;
               });
            }
            print.Debug([&](std::ostream &os) {
               const int pr = os.precision(13);
               const int iext = Trafo().ExtOfInt(i);
               os << std::setw(10) << Trafo().Name(iext) << std::setw(5) << j << "  " << x(i) << " " << step << " "
                  << fs1 << " " << fs2 << " " << grd(i) << " " << g2(i) << std::endl;
               os.precision(pr);
            });
         }

         if (std::fabs(grdb4 - grd(i)) / (std::fabs(grd(i)) + dfmin / step) < GradTolerance()) {
            //    std::cout<<"j= "<<j<<std::endl;
            //    std::cout<<"step= "<<step<<std::endl;
            //    std::cout<<"fs1, fs2: "<<fs1<<" "<<fs2<<std::endl;
            //    std::cout<<"fs1-fs2: "<<fs1-fs2<<std::endl;
            break;
         }
      }

      //     vgrd(i) = grd;
      //     vgrd2(i) = g2;
      //     vgstp(i) = gstep;
   }

#ifndef _OPENMP
   mpiproc.SyncVector(grd);
   mpiproc.SyncVector(g2);
   mpiproc.SyncVector(gstep);
#endif

   // print after parallel processing to avoid synchronization issues
   print.Debug([&](std::ostream &os) {
      const int pr = os.precision(13);
      os << std::endl;
      os << std::setw(14) << "Parameter" << std::setw(14) << "Gradient" << std::setw(14) << "g2 " << std::setw(14)
         << "step" << std::endl;
      for (int i = 0; i < int(n); i++) {
         const int iext = Trafo().ExtOfInt(i);
         os << std::setw(14) << Trafo().Name(iext) << " " << grd(i) << " " << g2(i) << " " << gstep(i) << std::endl;
      }
      os.precision(pr);
   });

   return FunctionGradient(grd, g2, gstep);
}

const MnMachinePrecision &Numerical2PGradientCalculator::Precision() const
{
   // return global precision (set in transformation)
   return fTransformation.Precision();
}

unsigned int Numerical2PGradientCalculator::Ncycle() const
{
   // return number of cycles for gradient calculation (set in strategy object)
   return Strategy().GradientNCycles();
}

double Numerical2PGradientCalculator::StepTolerance() const
{
   // return gradient step tolerance (set in strategy object)
   return Strategy().GradientStepTolerance();
}

double Numerical2PGradientCalculator::GradTolerance() const
{
   // return gradient tolerance (set in strategy object)
   return Strategy().GradientTolerance();
}

} // namespace Minuit2

} // namespace ROOT
<commit_msg>fix openmp shadowing declaration of MnPrint print thread-local variable<commit_after>// @(#)root/minuit2:$Id$
// Authors: M. Winkler, F. James, L. Moneta, A. Zsenei   2003-2005

/**********************************************************************
 *                                                                    *
 * Copyright (c) 2005 LCG ROOT Math team,  CERN/PH-SFT                *
 *                                                                    *
 **********************************************************************/

#include "Minuit2/Numerical2PGradientCalculator.h"
#include "Minuit2/InitialGradientCalculator.h"
#include "Minuit2/MnFcn.h"
#include "Minuit2/MnUserTransformation.h"
#include "Minuit2/MnMachinePrecision.h"
#include "Minuit2/MinimumParameters.h"
#include "Minuit2/FunctionGradient.h"
#include "Minuit2/MnStrategy.h"
#include "Minuit2/MnPrint.h"

#ifdef _OPENMP
#include <omp.h>
#endif

#include <cmath>
#include <cassert>
#include <iomanip>

#include "Minuit2/MPIProcess.h"

namespace ROOT {

namespace Minuit2 {

FunctionGradient Numerical2PGradientCalculator::operator()(const MinimumParameters &par) const
{
   // calculate gradient using Initial gradient calculator and from MinimumParameters object

   InitialGradientCalculator gc(fFcn, fTransformation, fStrategy);
   FunctionGradient gra = gc(par);

   return (*this)(par, gra);
}

// comment it, because it was added
FunctionGradient Numerical2PGradientCalculator::operator()(const std::vector<double> &params) const
{
   // calculate gradient from an std;:vector of paramteters

   int npar = params.size();

   MnAlgebraicVector par(npar);
   for (int i = 0; i < npar; ++i) {
      par(i) = params[i];
   }

   double fval = Fcn()(par);

   MinimumParameters minpars = MinimumParameters(par, fval);

   return (*this)(minpars);
}

FunctionGradient Numerical2PGradientCalculator::
operator()(const MinimumParameters &par, const FunctionGradient &Gradient) const
{
   // calculate numerical gradient from MinimumParameters object
   // the algorithm takes correctly care when the gradient is approximatly zero

   //    std::cout<<"########### Numerical2PDerivative"<<std::endl;
   //    std::cout<<"initial grd: "<<Gradient.Grad()<<std::endl;
   //    std::cout<<"position: "<<par.Vec()<<std::endl;
   MnPrint print("Numerical2PGradientCalculator");

   assert(par.IsValid());

   double fcnmin = par.Fval();
   //   std::cout<<"fval: "<<fcnmin<<std::endl;

   double eps2 = Precision().Eps2();
   double eps = Precision().Eps();

   print.Debug("Assumed precision eps", eps, "eps2", eps2);

   double dfmin = 8. * eps2 * (std::fabs(fcnmin) + Fcn().Up());
   double vrysml = 8. * eps * eps;
   //   double vrysml = std::max(1.e-4, eps2);
   //    std::cout<<"dfmin= "<<dfmin<<std::endl;
   //    std::cout<<"vrysml= "<<vrysml<<std::endl;
   //    std::cout << " ncycle " << Ncycle() << std::endl;

   unsigned int n = (par.Vec()).size();
   unsigned int ncycle = Ncycle();
   //   MnAlgebraicVector vgrd(n), vgrd2(n), vgstp(n);
   MnAlgebraicVector grd = Gradient.Grad();
   MnAlgebraicVector g2 = Gradient.G2();
   MnAlgebraicVector gstep = Gradient.Gstep();

   print.Debug("Calculating gradient around value", fcnmin, "at point", par.Vec());

#ifndef _OPENMP

   MPIProcess mpiproc(n, 0);

   // for serial execution this can be outside the loop
   MnAlgebraicVector x = par.Vec();

   unsigned int startElementIndex = mpiproc.StartElementIndex();
   unsigned int endElementIndex = mpiproc.EndElementIndex();

   for (unsigned int i = startElementIndex; i < endElementIndex; i++) {

#else

   // parallelize this loop using OpenMP
//#define N_PARALLEL_PAR 5
#pragma omp parallel
#pragma omp for
   //#pragma omp for schedule (static, N_PARALLEL_PAR)

   for (int i = 0; i < int(n); i++) {

#endif

#ifdef _OPENMP
      // create in loop since each thread will use its own copy
      MnAlgebraicVector x = par.Vec();
#endif

      double xtf = x(i);
      double epspri = eps2 + std::fabs(grd(i) * eps2);
      double stepb4 = 0.;
      for (unsigned int j = 0; j < ncycle; j++) {
         double optstp = std::sqrt(dfmin / (std::fabs(g2(i)) + epspri));
         double step = std::max(optstp, std::fabs(0.1 * gstep(i)));
         //       std::cout<<"step: "<<step;
         if (Trafo().Parameter(Trafo().ExtOfInt(i)).HasLimits()) {
            if (step > 0.5)
               step = 0.5;
         }
         double stpmax = 10. * std::fabs(gstep(i));
         if (step > stpmax)
            step = stpmax;
         //       std::cout<<" "<<step;
         double stpmin = std::max(vrysml, 8. * std::fabs(eps2 * x(i)));
         if (step < stpmin)
            step = stpmin;
         //       std::cout<<" "<<step<<std::endl;
         //       std::cout<<"step: "<<step<<std::endl;
         if (std::fabs((step - stepb4) / step) < StepTolerance()) {
            //    std::cout<<"(step-stepb4)/step"<<std::endl;
            //    std::cout<<"j= "<<j<<std::endl;
            //    std::cout<<"step= "<<step<<std::endl;
            break;
         }
         gstep(i) = step;
         stepb4 = step;
         //       MnAlgebraicVector pstep(n);
         //       pstep(i) = step;
         //       double fs1 = Fcn()(pstate + pstep);
         //       double fs2 = Fcn()(pstate - pstep);

         x(i) = xtf + step;
         double fs1 = Fcn()(x);
         x(i) = xtf - step;
         double fs2 = Fcn()(x);
         x(i) = xtf;

         double grdb4 = grd(i);
         grd(i) = 0.5 * (fs1 - fs2) / step;
         g2(i) = (fs1 + fs2 - 2. * fcnmin) / step / step;

#ifdef _OPENMP
#pragma omp critical
#endif
         {
#ifdef _OPENMP
            // must create thread-local MnPrint instances when printing inside threads
            MnPrint printtl("Numerical2PGradientCalculator[OpenMP]");
#endif
            if (i == 0 && j == 0) {
#ifdef _OPENMP
               printtl.Debug([&](std::ostream &os) {
#else
               print.Debug([&](std::ostream &os) {
#endif
                  os << std::setw(10) << "parameter" << std::setw(6) << "cycle" << std::setw(15) << "x" << std::setw(15)
                     << "step" << std::setw(15) << "f1" << std::setw(15) << "f2" << std::setw(15) << "grd"
                     << std::setw(15) << "g2" << std::endl;
               });
            }
#ifdef _OPENMP
            printtl.Debug([&](std::ostream &os) {
#else
            print.Debug([&](std::ostream &os) {
#endif
               const int pr = os.precision(13);
               const int iext = Trafo().ExtOfInt(i);
               os << std::setw(10) << Trafo().Name(iext) << std::setw(5) << j << "  " << x(i) << " " << step << " "
                  << fs1 << " " << fs2 << " " << grd(i) << " " << g2(i) << std::endl;
               os.precision(pr);
            });
         }

         if (std::fabs(grdb4 - grd(i)) / (std::fabs(grd(i)) + dfmin / step) < GradTolerance()) {
            //    std::cout<<"j= "<<j<<std::endl;
            //    std::cout<<"step= "<<step<<std::endl;
            //    std::cout<<"fs1, fs2: "<<fs1<<" "<<fs2<<std::endl;
            //    std::cout<<"fs1-fs2: "<<fs1-fs2<<std::endl;
            break;
         }
      }

      //     vgrd(i) = grd;
      //     vgrd2(i) = g2;
      //     vgstp(i) = gstep;
   }

#ifndef _OPENMP
   mpiproc.SyncVector(grd);
   mpiproc.SyncVector(g2);
   mpiproc.SyncVector(gstep);
#endif

   // print after parallel processing to avoid synchronization issues
   print.Debug([&](std::ostream &os) {
      const int pr = os.precision(13);
      os << std::endl;
      os << std::setw(14) << "Parameter" << std::setw(14) << "Gradient" << std::setw(14) << "g2 " << std::setw(14)
         << "step" << std::endl;
      for (int i = 0; i < int(n); i++) {
         const int iext = Trafo().ExtOfInt(i);
         os << std::setw(14) << Trafo().Name(iext) << " " << grd(i) << " " << g2(i) << " " << gstep(i) << std::endl;
      }
      os.precision(pr);
   });

   return FunctionGradient(grd, g2, gstep);
}

const MnMachinePrecision &Numerical2PGradientCalculator::Precision() const
{
   // return global precision (set in transformation)
   return fTransformation.Precision();
}

unsigned int Numerical2PGradientCalculator::Ncycle() const
{
   // return number of cycles for gradient calculation (set in strategy object)
   return Strategy().GradientNCycles();
}

double Numerical2PGradientCalculator::StepTolerance() const
{
   // return gradient step tolerance (set in strategy object)
   return Strategy().GradientStepTolerance();
}

double Numerical2PGradientCalculator::GradTolerance() const
{
   // return gradient tolerance (set in strategy object)
   return Strategy().GradientTolerance();
}

} // namespace Minuit2

} // namespace ROOT
<|endoftext|>