<commit_before>/* Copyright 2015 The TensorFlow Authors. All Rights Reserved.

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

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

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

// This module implements a common subexpression elimination pass.  We
// process the nodes in the graph in reverse postorder
// (i.e. inputs before their downstream dependencies).  The rough algorithm is
// as follows:
//
// std::unordered_map<size_t, Node*> available
// for each node n in forward topological order:
//   h = NodeHash(n)
//   if available[h] exists and Equivalent(available(h), h)
//     redirect downstream uses of outputs of n to available[h]
//     remove n from graph
//   else
//     if available[h] does not exist
//       available[h] = n
//
// This is similar to the global value number algorithm describe in this
// paper:
//
// "Global code motion/global value numbering", Cliff Click, PLDI '95
// Proceedings of the ACM SIGPLAN 1995 conference on Programming
// language design and implementation, Pages 246-257
//      http://dl.acm.org/citation.cfm?id=207154

#include "tensorflow/core/graph/optimizer_cse.h"

#include <unordered_map>
#include <utility>
#include <vector>

#include "tensorflow/core/graph/algorithm.h"
#include "tensorflow/core/lib/gtl/map_util.h"
#include "tensorflow/core/lib/hash/hash.h"
#include "tensorflow/core/platform/logging.h"

namespace tensorflow {

class OptimizerCSE {
 public:
  explicit OptimizerCSE(Graph* g) : g_(g) {}

  bool Optimize(const std::function<bool(const Node*)>& consider_fn);

 private:
  static size_t NodeHash(const Node* n);
  static bool Equivalent(const Node* a, const Node* b,
                         AttrSlice::Scratch* scratch);

  Graph* g_;
};

static void FillInputs(const Node* n,
                       gtl::InlinedVector<Node*, 4>* control_edges,
                       gtl::InlinedVector<std::pair<Node*, int>, 4>* in) {
  DCHECK_EQ(in->size(), n->num_inputs());
  control_edges->clear();
  for (const Edge* e : n->in_edges()) {
    if (e->IsControlEdge()) {
      control_edges->push_back(e->src());
    } else {
      (*in)[e->dst_input()] = std::make_pair(e->src(), e->src_output());
    }
  }
  std::sort(control_edges->begin(), control_edges->end());
  if (n->op_def().is_commutative()) {
    // For commutative inputs, we sort the input by the input Node*
    // to get a canonical ordering (so that add(a,b) and add(b, a) will
    // hash to the same value if is_commutative is true for 'add').
    std::sort(in->begin(), in->end());
  }
}

static size_t kIllegalNodeHash = 0;

size_t OptimizerCSE::NodeHash(const Node* n) {
  const DataTypeVector& out = n->output_types();
  string str_to_hash = strings::StrCat(n->type_string(), out.size());
  for (DataType dt : out) {
    strings::StrAppend(&str_to_hash, dt);
  }

  const int N_in = n->num_inputs();
  strings::StrAppend(&str_to_hash, N_in);
  gtl::InlinedVector<Node*, 4> control_edges;
  gtl::InlinedVector<std::pair<Node*, int>, 4> in(N_in);
  FillInputs(n, &control_edges, &in);
  for (const auto& edge : in) {
    strings::StrAppend(&str_to_hash, edge.first->id(), edge.second);
  }

  size_t h = Hash64(str_to_hash);

#if !defined(__ANDROID__)
  // Hash the attrs.  For example, this makes sure different constants
  // end up in different hash buckets.
  string tmp;
  for (const auto& attr : n->attrs()) {
    tmp = attr.first;
    attr.second.AppendToString(&tmp);
    // Add hashes of attrs, so the order of attrs doesn't matter.
    h += Hash32(tmp.data(), tmp.size(), 0x87341245);
  }
#endif

  if (h == kIllegalNodeHash) h = kIllegalNodeHash + 1;
  return h;
}

static bool HasRefInput(const Node* n) {
  for (auto dt : n->input_types()) {
    if (IsRefType(dt)) return true;
  }
  return false;
}

bool OptimizerCSE::Equivalent(const Node* a, const Node* b,
                              AttrSlice::Scratch* scratch) {
  // Different op names are different
  if (a->type_string() != b->type_string()) return false;

  // Never consider stateful nodes (such as non-const inputs) equivalent.
  if (a->op_def().is_stateful()) return false;

  // For now, we consider any node that takes a ref input to not be
  // equivalent to any other node.
  if (HasRefInput(a) || HasRefInput(b)) return false;

  // Compare attrs.  Note that equal attrs implies equal input and
  // output types.
  if (!a->attrs().EqualAttrs(b->attrs(), scratch)) return false;

  // Compare input sources
  if (a->num_inputs() != b->num_inputs()) return false;
  const int N_in = a->num_inputs();
  gtl::InlinedVector<Node*, 4> a_control_edges;
  gtl::InlinedVector<Node*, 4> b_control_edges;
  gtl::InlinedVector<std::pair<Node*, int>, 4> a_in(N_in);
  gtl::InlinedVector<std::pair<Node*, int>, 4> b_in(N_in);
  FillInputs(a, &a_control_edges, &a_in);
  FillInputs(b, &b_control_edges, &b_in);
  if (a_in != b_in) return false;
  if (a_control_edges != b_control_edges) return false;

  return true;
}

bool OptimizerCSE::Optimize(
    const std::function<bool(const Node*)>& consider_fn) {
  // This very simple implementation works if the whole graph is one
  // giant basic block (because we just traverse nodes in a
  // topological order). This simple implementation works well
  // with control flow/loops/etc. But we need to be careful about
  // control flow if we want to add more sophisticated CSE optimizations.

  // TODO(jeff): We need to handle Update nodes specially, but dealing
  // with more general control flow will also solve this issue, and for
  // now, our updates are almost always the most downstream nodes in
  // the graph.
  std::vector<Node*> order;
  GetReversePostOrder(*g_, &order);

  // Our value is just a single Node*, meaning we keep just a single
  // candidate for a given node hash value.  This may cause us to
  // (rarely) lose some optimization opportunities if there are
  // hash collisions, but it allows us to avoid having the value
  // be a set<Node*> (or equivalent).
  std::unordered_map<size_t, Node*> available;

  // Scratch space for Equivalent calls.  Allocated here and passed in to
  // Equivalent to avoid allocation inside the loop below.
  bool changed = false;
  AttrSlice::Scratch scratch;
  for (Node* n : order) {
    if (!n->IsOp()) continue;

    // See if we should consider this node at all
    if (consider_fn != nullptr && !consider_fn(n)) continue;

    size_t h = NodeHash(n);
    Node** candidate = &available[h];
    if (*candidate == nullptr) {
      // No existing match: insert "n" into the hash table under "h"
      *candidate = n;
    } else if (Equivalent(*candidate, n, &scratch)) {
      VLOG(1) << "CSE: equivalent: " << (*candidate)->name() << " and "
              << n->name();
      // *candidate and n are equivalent.  Therefore, we can replace
      // n with *candidate by fixing up outgoing edges from "n" to instead
      // come from "*candidate", and then delete n from the graph
      for (const Edge* e : n->out_edges()) {
        g_->AddEdge(*candidate, e->src_output(), e->dst(), e->dst_input());
      }
      g_->RemoveNode(n);
      changed = true;
    }
  }
  return changed;
}

bool OptimizeCSE(Graph* g,
                 const std::function<bool(const Node*)>& consider_fn) {
  OptimizerCSE opt(g);
  return opt.Optimize(consider_fn);
}

}  // namespace tensorflow
<commit_msg>Don't eliminate placeholders during constant subexpression elimination optimization.<commit_after>/* Copyright 2015 The TensorFlow Authors. All Rights Reserved.

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

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

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

// This module implements a common subexpression elimination pass.  We
// process the nodes in the graph in reverse postorder
// (i.e. inputs before their downstream dependencies).  The rough algorithm is
// as follows:
//
// std::unordered_map<size_t, Node*> available
// for each node n in forward topological order:
//   h = NodeHash(n)
//   if available[h] exists and Equivalent(available(h), h)
//     redirect downstream uses of outputs of n to available[h]
//     remove n from graph
//   else
//     if available[h] does not exist
//       available[h] = n
//
// This is similar to the global value number algorithm describe in this
// paper:
//
// "Global code motion/global value numbering", Cliff Click, PLDI '95
// Proceedings of the ACM SIGPLAN 1995 conference on Programming
// language design and implementation, Pages 246-257
//      http://dl.acm.org/citation.cfm?id=207154

#include "tensorflow/core/graph/optimizer_cse.h"

#include <unordered_map>
#include <utility>
#include <vector>

#include "tensorflow/core/graph/algorithm.h"
#include "tensorflow/core/lib/gtl/map_util.h"
#include "tensorflow/core/lib/hash/hash.h"
#include "tensorflow/core/platform/logging.h"

namespace tensorflow {

class OptimizerCSE {
 public:
  explicit OptimizerCSE(Graph* g) : g_(g) {}

  bool Optimize(const std::function<bool(const Node*)>& consider_fn);

 private:
  static size_t NodeHash(const Node* n);
  static bool Equivalent(const Node* a, const Node* b,
                         AttrSlice::Scratch* scratch);

  Graph* g_;
};

static void FillInputs(const Node* n,
                       gtl::InlinedVector<Node*, 4>* control_edges,
                       gtl::InlinedVector<std::pair<Node*, int>, 4>* in) {
  DCHECK_EQ(in->size(), n->num_inputs());
  control_edges->clear();
  for (const Edge* e : n->in_edges()) {
    if (e->IsControlEdge()) {
      control_edges->push_back(e->src());
    } else {
      (*in)[e->dst_input()] = std::make_pair(e->src(), e->src_output());
    }
  }
  std::sort(control_edges->begin(), control_edges->end());
  if (n->op_def().is_commutative()) {
    // For commutative inputs, we sort the input by the input Node*
    // to get a canonical ordering (so that add(a,b) and add(b, a) will
    // hash to the same value if is_commutative is true for 'add').
    std::sort(in->begin(), in->end());
  }
}

static size_t kIllegalNodeHash = 0;

size_t OptimizerCSE::NodeHash(const Node* n) {
  const DataTypeVector& out = n->output_types();
  string str_to_hash = strings::StrCat(n->type_string(), out.size());
  for (DataType dt : out) {
    strings::StrAppend(&str_to_hash, dt);
  }

  const int N_in = n->num_inputs();
  strings::StrAppend(&str_to_hash, N_in);
  gtl::InlinedVector<Node*, 4> control_edges;
  gtl::InlinedVector<std::pair<Node*, int>, 4> in(N_in);
  FillInputs(n, &control_edges, &in);
  for (const auto& edge : in) {
    strings::StrAppend(&str_to_hash, edge.first->id(), edge.second);
  }

  size_t h = Hash64(str_to_hash);

#if !defined(__ANDROID__)
  // Hash the attrs.  For example, this makes sure different constants
  // end up in different hash buckets.
  string tmp;
  for (const auto& attr : n->attrs()) {
    tmp = attr.first;
    attr.second.AppendToString(&tmp);
    // Add hashes of attrs, so the order of attrs doesn't matter.
    h += Hash32(tmp.data(), tmp.size(), 0x87341245);
  }
#endif

  if (h == kIllegalNodeHash) h = kIllegalNodeHash + 1;
  return h;
}

static bool HasRefInput(const Node* n) {
  for (auto dt : n->input_types()) {
    if (IsRefType(dt)) return true;
  }
  return false;
}

bool OptimizerCSE::Equivalent(const Node* a, const Node* b,
                              AttrSlice::Scratch* scratch) {
  // Different op names are different
  if (a->type_string() != b->type_string()) return false;

  // Never consider stateful nodes (such as non-const inputs) equivalent.
  if (a->op_def().is_stateful()) return false;

  // For now, we consider any node that takes a ref input to not be
  // equivalent to any other node.
  if (HasRefInput(a) || HasRefInput(b)) return false;

  // Compare attrs.  Note that equal attrs implies equal input and
  // output types.
  if (!a->attrs().EqualAttrs(b->attrs(), scratch)) return false;

  // Compare input sources
  if (a->num_inputs() != b->num_inputs()) return false;
  const int N_in = a->num_inputs();
  gtl::InlinedVector<Node*, 4> a_control_edges;
  gtl::InlinedVector<Node*, 4> b_control_edges;
  gtl::InlinedVector<std::pair<Node*, int>, 4> a_in(N_in);
  gtl::InlinedVector<std::pair<Node*, int>, 4> b_in(N_in);
  FillInputs(a, &a_control_edges, &a_in);
  FillInputs(b, &b_control_edges, &b_in);
  if (a_in != b_in) return false;
  if (a_control_edges != b_control_edges) return false;

  return true;
}

bool OptimizerCSE::Optimize(
    const std::function<bool(const Node*)>& consider_fn) {
  // This very simple implementation works if the whole graph is one
  // giant basic block (because we just traverse nodes in a
  // topological order). This simple implementation works well
  // with control flow/loops/etc. But we need to be careful about
  // control flow if we want to add more sophisticated CSE optimizations.

  // TODO(jeff): We need to handle Update nodes specially, but dealing
  // with more general control flow will also solve this issue, and for
  // now, our updates are almost always the most downstream nodes in
  // the graph.
  std::vector<Node*> order;
  GetReversePostOrder(*g_, &order);

  // Our value is just a single Node*, meaning we keep just a single
  // candidate for a given node hash value.  This may cause us to
  // (rarely) lose some optimization opportunities if there are
  // hash collisions, but it allows us to avoid having the value
  // be a set<Node*> (or equivalent).
  std::unordered_map<size_t, Node*> available;

  // Scratch space for Equivalent calls.  Allocated here and passed in to
  // Equivalent to avoid allocation inside the loop below.
  bool changed = false;
  AttrSlice::Scratch scratch;
  for (Node* n : order) {
    if (!n->IsOp()) continue;

    // Don't prune placeholder nodes.
    if (n->def().op() == "Placeholder" || n->def().op() == "PlaceholderV2" ||
        n->def().op() == "PlaceholderWithDefault") {
      continue;
    }

    // See if we should consider this node at all
    if (consider_fn != nullptr && !consider_fn(n)) continue;

    size_t h = NodeHash(n);
    Node** candidate = &available[h];
    if (*candidate == nullptr) {
      // No existing match: insert "n" into the hash table under "h"
      *candidate = n;
    } else if (Equivalent(*candidate, n, &scratch)) {
      VLOG(1) << "CSE: equivalent: " << (*candidate)->name() << " and "
              << n->name();
      // *candidate and n are equivalent.  Therefore, we can replace
      // n with *candidate by fixing up outgoing edges from "n" to instead
      // come from "*candidate", and then delete n from the graph
      for (const Edge* e : n->out_edges()) {
        g_->AddEdge(*candidate, e->src_output(), e->dst(), e->dst_input());
      }

      g_->RemoveNode(n);
      changed = true;
    }
  }
  return changed;
}

bool OptimizeCSE(Graph* g,
                 const std::function<bool(const Node*)>& consider_fn) {
  OptimizerCSE opt(g);
  return opt.Optimize(consider_fn);
}

}  // namespace tensorflow
<|endoftext|>


<commit_before>// Copyright 2014 Project Vogue. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <vector>

#include "elang/compiler/testing/compiler_test.h"

#include "base/logging.h"
#include "base/macros.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "elang/compiler/analyze/namespace_analyzer.h"
#include "elang/compiler/ast/class.h"
#include "elang/compiler/compilation_session.h"
#include "elang/compiler/compilation_unit.h"
#include "elang/compiler/public/compiler_error_code.h"
#include "elang/compiler/public/compiler_error_data.h"
#include "elang/compiler/syntax/parser.h"
#include "elang/compiler/qualified_name.h"
#include "elang/compiler/source_code_position.h"
#include "elang/compiler/string_source_code.h"
#include "elang/compiler/testing/formatter.h"
#include "elang/compiler/token.h"
#include "elang/compiler/token_type.h"

namespace elang {
namespace compiler {
namespace testing {

namespace {
std::string GetQualifiedName(ast::NamespaceMember* member) {
  std::vector<Token*> names;
  names.push_back(member->name());
  for (auto ns = member->outer(); ns && ns->outer(); ns = ns->outer())
    names.push_back(ns->name());
  std::reverse(names.begin(), names.end());
  std::stringstream stream;
  const char* separator = "";
  for (auto const name : names) {
    stream << separator << name;
    separator = ".";
  }
  return stream.str();
}
}  // namespace

//////////////////////////////////////////////////////////////////////
//
// CompilerTest
//
CompilerTest::CompilerTest() : session_(new CompilationSession()) {
}

CompilerTest::~CompilerTest() {
}

ast::Class* CompilerTest::FindClass(base::StringPiece name) {
  auto const member = FindMember(name);
  return member ? member->as<ast::Class>() : nullptr;
}

ast::NamespaceMember* CompilerTest::FindMember(base::StringPiece name) {
  auto enclosing = session_->global_namespace();
  auto found = static_cast<ast::NamespaceMember*>(nullptr);
  for (size_t pos = 0u; pos < name.length(); ++pos) {
    auto dot_pos = name.find('.', pos);
    if (dot_pos == base::StringPiece::npos)
      dot_pos = name.length();
    auto const simple_name = session_->GetOrCreateSimpleName(
        base::UTF8ToUTF16(name.substr(pos, dot_pos - pos)));
    found = enclosing->FindMember(simple_name);
    if (!found)
      return nullptr;
    enclosing = found->as<ast::Namespace>();
    if (!enclosing)
      return nullptr;
    pos = dot_pos;
  }
  return found;
}

std::string CompilerTest::GetBaseClasses(base::StringPiece name) {
  auto const member = FindMember(name);
  if (!member)
    return base::StringPrintf("No such class %s", name);
  auto const clazz = member->as<ast::Class>();
  if (!clazz)
    return base::StringPrintf("%s isn't class", name);
  std::stringstream stream;
  const char* separator = "";
  for (auto base_class : clazz->base_classes()) {
    stream << separator << GetQualifiedName(base_class);
    separator = ", ";
  }
  return stream.str();
}

std::string CompilerTest::GetErrors() {
  static const char* const error_messages[] = {
#define E(category, subcategory, name) #category "." #subcategory "." #name,
      COMPILER_ERROR_CODE_LIST(E, E)
#undef E
  };

  std::stringstream stream;
  for (auto const error : session_->errors()) {
    stream << error_messages[static_cast<int>(error->error_code())] << "("
           << error->location().start().offset() << ")";
    for (auto token : error->tokens())
      stream << " " << token;
    stream << std::endl;
  }
  return stream.str();
}

std::string CompilerTest::AnalyzeNamespace() {
  if (!Parse())
    return GetErrors();
  NamespaceAnalyzer resolver(session_.get());
  return resolver.Run() ? "" : GetErrors();
}

std::string CompilerTest::Format() {
  if (!Parse())
    return GetErrors();
  Formatter formatter;
  return formatter.Run(session_->global_namespace());
}

bool CompilerTest::Parse() {
  auto const compilation_unit =
      session_->NewCompilationUnit(source_code_.get());
  Parser parser(session_.get(), compilation_unit);
  return parser.Run();
}

void CompilerTest::Prepare(base::StringPiece source_text) {
  source_code_.reset(
      new StringSourceCode(L"testing", base::UTF8ToUTF16(source_text)));
}

}  // namespace testing
}  // namespace compiler
}  // namespace elang
<commit_msg>elang/compiler/testing: Avoid |DCHECK| of |ast::Class::base_classes()| in |CompilerTest::GetBaseClasses()|.<commit_after>// Copyright 2014 Project Vogue. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <vector>

#include "elang/compiler/testing/compiler_test.h"

#include "base/logging.h"
#include "base/macros.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "elang/compiler/analyze/namespace_analyzer.h"
#include "elang/compiler/ast/class.h"
#include "elang/compiler/compilation_session.h"
#include "elang/compiler/compilation_unit.h"
#include "elang/compiler/public/compiler_error_code.h"
#include "elang/compiler/public/compiler_error_data.h"
#include "elang/compiler/syntax/parser.h"
#include "elang/compiler/qualified_name.h"
#include "elang/compiler/source_code_position.h"
#include "elang/compiler/string_source_code.h"
#include "elang/compiler/testing/formatter.h"
#include "elang/compiler/token.h"
#include "elang/compiler/token_type.h"

namespace elang {
namespace compiler {
namespace testing {

namespace {
std::string GetQualifiedName(ast::NamespaceMember* member) {
  std::vector<Token*> names;
  names.push_back(member->name());
  for (auto ns = member->outer(); ns && ns->outer(); ns = ns->outer())
    names.push_back(ns->name());
  std::reverse(names.begin(), names.end());
  std::stringstream stream;
  const char* separator = "";
  for (auto const name : names) {
    stream << separator << name;
    separator = ".";
  }
  return stream.str();
}
}  // namespace

//////////////////////////////////////////////////////////////////////
//
// CompilerTest
//
CompilerTest::CompilerTest() : session_(new CompilationSession()) {
}

CompilerTest::~CompilerTest() {
}

ast::Class* CompilerTest::FindClass(base::StringPiece name) {
  auto const member = FindMember(name);
  return member ? member->as<ast::Class>() : nullptr;
}

ast::NamespaceMember* CompilerTest::FindMember(base::StringPiece name) {
  auto enclosing = session_->global_namespace();
  auto found = static_cast<ast::NamespaceMember*>(nullptr);
  for (size_t pos = 0u; pos < name.length(); ++pos) {
    auto dot_pos = name.find('.', pos);
    if (dot_pos == base::StringPiece::npos)
      dot_pos = name.length();
    auto const simple_name = session_->GetOrCreateSimpleName(
        base::UTF8ToUTF16(name.substr(pos, dot_pos - pos)));
    found = enclosing->FindMember(simple_name);
    if (!found)
      return nullptr;
    enclosing = found->as<ast::Namespace>();
    if (!enclosing)
      return nullptr;
    pos = dot_pos;
  }
  return found;
}

std::string CompilerTest::GetBaseClasses(base::StringPiece name) {
  auto const member = FindMember(name);
  if (!member)
    return base::StringPrintf("No such class %s", name);
  auto const clazz = member->as<ast::Class>();
  if (!clazz)
    return base::StringPrintf("%s isn't class", name);
  if (!clazz->is_fixed())
    return base::StringPrintf("class %s isn't fixed", name);
  std::stringstream stream;
  const char* separator = "";
  for (auto base_class : clazz->base_classes()) {
    stream << separator << GetQualifiedName(base_class);
    separator = ", ";
  }
  return stream.str();
}

std::string CompilerTest::GetErrors() {
  static const char* const error_messages[] = {
#define E(category, subcategory, name) #category "." #subcategory "." #name,
      COMPILER_ERROR_CODE_LIST(E, E)
#undef E
  };

  std::stringstream stream;
  for (auto const error : session_->errors()) {
    stream << error_messages[static_cast<int>(error->error_code())] << "("
           << error->location().start().offset() << ")";
    for (auto token : error->tokens())
      stream << " " << token;
    stream << std::endl;
  }
  return stream.str();
}

std::string CompilerTest::AnalyzeNamespace() {
  if (!Parse())
    return GetErrors();
  NamespaceAnalyzer resolver(session_.get());
  return resolver.Run() ? "" : GetErrors();
}

std::string CompilerTest::Format() {
  if (!Parse())
    return GetErrors();
  Formatter formatter;
  return formatter.Run(session_->global_namespace());
}

bool CompilerTest::Parse() {
  auto const compilation_unit =
      session_->NewCompilationUnit(source_code_.get());
  Parser parser(session_.get(), compilation_unit);
  return parser.Run();
}

void CompilerTest::Prepare(base::StringPiece source_text) {
  source_code_.reset(
      new StringSourceCode(L"testing", base::UTF8ToUTF16(source_text)));
}

}  // namespace testing
}  // namespace compiler
}  // namespace elang
<|endoftext|>


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

#ifndef SCRIPTING_BASSCRIPT_HXX
#define SCRIPTING_BASSCRIPT_HXX

#ifndef _COM_SUN_STAR_SCRIPT_PROVIDER_XSCRIPT_HPP_
#include <com/sun/star/script/provider/XScript.hpp>
#endif
#ifndef _COM_SUN_STAR_DOCUMENT_XSCRIPTINVOCATIONCONTEXT_HPP_
#include <com/sun/star/document/XScriptInvocationContext.hpp>
#endif
#ifndef _CPPUHELPER_IMPLBASE1_HXX_
#include <cppuhelper/implbase1.hxx>
#endif

#ifndef _SB_SBMETH_HXX
#include <basic/sbmeth.hxx>
#endif

class BasicManager;

//.........................................................................
namespace basprov
{
//.........................................................................

    //  ----------------------------------------------------
    //  class BasicScriptImpl
    //  ----------------------------------------------------

    typedef ::cppu::WeakImplHelper1<
        ::com::sun::star::script::provider::XScript > BasicScriptImpl_BASE;

    class BasicScriptImpl : public BasicScriptImpl_BASE
    {
    private:
        SbMethodRef         m_xMethod;
        ::rtl::OUString     m_funcName;
        BasicManager*       m_documentBasicManager;
        ::com::sun::star::uno::Reference< ::com::sun::star::document::XScriptInvocationContext >
                            m_xDocumentScriptContext;

    public:
        BasicScriptImpl(
            const ::rtl::OUString& funcName,
            SbMethodRef xMethod
        );
        BasicScriptImpl(
            const ::rtl::OUString& funcName,
            SbMethodRef xMethod,
            BasicManager& documentBasicManager,
            const ::com::sun::star::uno::Reference< ::com::sun::star::document::XScriptInvocationContext >& documentScriptContext
        );
        virtual ~BasicScriptImpl();

        // XScript
        virtual ::com::sun::star::uno::Any SAL_CALL invoke(
            const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aParams,
            ::com::sun::star::uno::Sequence< sal_Int16 >& aOutParamIndex,
            ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aOutParam )
            throw (
                    ::com::sun::star::script::provider::ScriptFrameworkErrorException,
                    ::com::sun::star::reflection::InvocationTargetException,
                    ::com::sun::star::uno::RuntimeException );
    };

//.........................................................................
}   // namespace basprov
//.........................................................................

#endif // SCRIPTING_BASSCRIPT_HXX
<commit_msg>INTEGRATION: CWS changefileheader (1.7.4); FILE MERGED 2008/04/01 15:31:47 thb 1.7.4.3: #i85898# Stripping all external header guards 2008/04/01 12:37:20 thb 1.7.4.2: #i85898# Stripping all external header guards 2008/03/31 13:35:59 rt 1.7.4.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: basscript.hxx,v $
 * $Revision: 1.8 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef SCRIPTING_BASSCRIPT_HXX
#define SCRIPTING_BASSCRIPT_HXX

#include <com/sun/star/script/provider/XScript.hpp>
#include <com/sun/star/document/XScriptInvocationContext.hpp>
#include <cppuhelper/implbase1.hxx>
#include <basic/sbmeth.hxx>

class BasicManager;

//.........................................................................
namespace basprov
{
//.........................................................................

    //  ----------------------------------------------------
    //  class BasicScriptImpl
    //  ----------------------------------------------------

    typedef ::cppu::WeakImplHelper1<
        ::com::sun::star::script::provider::XScript > BasicScriptImpl_BASE;

    class BasicScriptImpl : public BasicScriptImpl_BASE
    {
    private:
        SbMethodRef         m_xMethod;
        ::rtl::OUString     m_funcName;
        BasicManager*       m_documentBasicManager;
        ::com::sun::star::uno::Reference< ::com::sun::star::document::XScriptInvocationContext >
                            m_xDocumentScriptContext;

    public:
        BasicScriptImpl(
            const ::rtl::OUString& funcName,
            SbMethodRef xMethod
        );
        BasicScriptImpl(
            const ::rtl::OUString& funcName,
            SbMethodRef xMethod,
            BasicManager& documentBasicManager,
            const ::com::sun::star::uno::Reference< ::com::sun::star::document::XScriptInvocationContext >& documentScriptContext
        );
        virtual ~BasicScriptImpl();

        // XScript
        virtual ::com::sun::star::uno::Any SAL_CALL invoke(
            const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aParams,
            ::com::sun::star::uno::Sequence< sal_Int16 >& aOutParamIndex,
            ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aOutParam )
            throw (
                    ::com::sun::star::script::provider::ScriptFrameworkErrorException,
                    ::com::sun::star::reflection::InvocationTargetException,
                    ::com::sun::star::uno::RuntimeException );
    };

//.........................................................................
}   // namespace basprov
//.........................................................................

#endif // SCRIPTING_BASSCRIPT_HXX
<|endoftext|>


<commit_before>//==============================================================================
// Single cell view graph panels widget
//==============================================================================

#include "singlecellviewgraphpanelplotwidget.h"
#include "singlecellviewgraphpanelswidget.h"
#include "singlecellviewgraphpanelwidget.h"

//==============================================================================

#include <QSettings>
#include <QWheelEvent>

//==============================================================================

namespace OpenCOR {
namespace SingleCellView {

//==============================================================================

SingleCellViewGraphPanelsWidget::SingleCellViewGraphPanelsWidget(QWidget *pParent) :
    QSplitter(pParent),
    CommonWidget(pParent),
    mSplitterSizes(QList<int>()),
    mActiveGraphPanel(0)
{
    // Set our orientation

    setOrientation(Qt::Vertical);

    // Keep track of our movement
    // Note: we need to keep track of our movement so that saveSettings() can
    //       work fine even when we are not visible (which happens when a CellML
    //       file cannot be run for some reason or another)...

    connect(this, SIGNAL(splitterMoved(int,int)),
            this, SLOT(splitterMoved()));
}

//==============================================================================

static const QString SettingsGraphPanelsCount = "GraphPanelsCount";
static const QString SettingsGraphPanelSize   = "GraphPanelSize%1";
//static const QString SettingsActiveGraphPanel = "ActiveGraphPanel";
//---GRY--- WE DON'T CURRENTLY KEEP TRACK OF THE REQUIRED GRAPHS, SO NO POINT IN
//          KEEPING TRACK OF WHICH GRAPH PANEL IS ACTIVE...

//==============================================================================

void SingleCellViewGraphPanelsWidget::loadSettings(QSettings *pSettings)
{
    // Let the user know of a few default things about ourselves by emitting a
    // few signals

    emit removeGraphPanelsEnabled(false);

    // Retrieve the number of graph panels and create the corresponding number
    // of graphs

    int graphPanelsCount = pSettings->value(SettingsGraphPanelsCount, 1).toInt();

    if (!graphPanelsCount)
        // For some reason, the settings for the number of graph panels to be
        // created got messed up, so...

        graphPanelsCount = 1;

    for (int i = 0; i < graphPanelsCount; ++i)
        addGraphPanel();

    // Retrieve and set the size of each graph panel

    mSplitterSizes = QList<int>();

    for (int i = 0; i < graphPanelsCount; ++i)
        mSplitterSizes << pSettings->value(SettingsGraphPanelSize.arg(i)).toInt();

    setSizes(mSplitterSizes);

    // Select the graph panel that used to be active

//    qobject_cast<SingleCellViewGraphPanelWidget *>(widget(pSettings->value(SettingsActiveGraphPanel, 0).toInt()))->setActive(true);
qobject_cast<SingleCellViewGraphPanelWidget *>(widget(0))->setActive(true);
}

//==============================================================================

void SingleCellViewGraphPanelsWidget::saveSettings(QSettings *pSettings) const
{
    // Keep track of the number of graph panels, of the size of each graph panel
    // and of which graph panel is the active one

    pSettings->setValue(SettingsGraphPanelsCount, mSplitterSizes.count());

    for (int i = 0, iMax = mSplitterSizes.count(); i < iMax; ++i)
        pSettings->setValue(SettingsGraphPanelSize.arg(i), mSplitterSizes[i]);

//    for (int i = 0, iMax = mSplitterSizes.count(); i < iMax; ++i)
//        if (qobject_cast<SingleCellViewGraphPanelWidget *>(widget(i))->isActive()) {
//            // We found the active graph panel, so...

//            pSettings->setValue(SettingsActiveGraphPanel, i);

//            break;
//        }
}

//==============================================================================

QList<SingleCellViewGraphPanelWidget *> SingleCellViewGraphPanelsWidget::graphPanels() const
{
    // Return all our graph panels

    QList<SingleCellViewGraphPanelWidget *> res = QList<SingleCellViewGraphPanelWidget *>();

    for (int i = 0, iMax = count(); i < iMax; ++i)
        res << qobject_cast<SingleCellViewGraphPanelWidget *>(widget(i));

    return res;
}

//==============================================================================

SingleCellViewGraphPanelWidget * SingleCellViewGraphPanelsWidget::activeGraphPanel() const
{
    // Return the active graph panel

    for (int i = 0, iMax = count(); i < iMax; ++i) {
        SingleCellViewGraphPanelWidget *graphPanel = qobject_cast<SingleCellViewGraphPanelWidget *>(widget(i));

        if (graphPanel->isActive())
            // We found the active graph panel, so...

            return graphPanel;
    }

    // There are no graph panels, so...
    // Note: we should never reach this point since there should always be at
    //       least one graph panel...

    return 0;
}

//==============================================================================

SingleCellViewGraphPanelWidget * SingleCellViewGraphPanelsWidget::addGraphPanel()
{
    // Keep track of the graph panels' original size

    QList<int> origSizes = sizes();

    // Create a new graph panel

    SingleCellViewGraphPanelWidget *res = new SingleCellViewGraphPanelWidget(this);

    // Add the graph panel to ourselves

    addWidget(res);

    // Resize the graph panels, thus making sure that their size is what it
    // should be (see issue #58)

    double scalingFactor = double(count()-1)/count();

    for (int i = 0, iMax = origSizes.count(); i < iMax; ++i)
        origSizes[i] *= scalingFactor;

    setSizes(origSizes << height()/count());

    // Keep track of whenever a graph panel gets activated

    connect(res, SIGNAL(activated(SingleCellViewGraphPanelWidget *)),
            this, SIGNAL(graphPanelActivated(SingleCellViewGraphPanelWidget *)));

    connect(res, SIGNAL(activated(SingleCellViewGraphPanelWidget *)),
            this, SLOT(updateGraphPanels(SingleCellViewGraphPanelWidget *)));

    // Keep track of the addition and removal of a graph

    connect(res, SIGNAL(graphAdded(SingleCellViewGraphPanelPlotGraph *)),
            this, SIGNAL(graphAdded(SingleCellViewGraphPanelPlotGraph *)));
    connect(res, SIGNAL(graphRemoved(SingleCellViewGraphPanelPlotGraph *)),
            this, SIGNAL(graphRemoved(SingleCellViewGraphPanelPlotGraph *)));

    // Activate the graph panel

    res->setActive(true);

    // Keep track of our new sizes

    splitterMoved();

    // Let people know that we have added a graph panel

    emit graphPanelAdded(res);

    // Let people know whether graph panels can be removed

    emit removeGraphPanelsEnabled(count() > 1);

    // Return our newly created graph panel

    return res;
}

//==============================================================================

void SingleCellViewGraphPanelsWidget::removeGraphPanel(SingleCellViewGraphPanelWidget *pGraphPanel)
{
    if (!pGraphPanel)
        return;

    // Retrieve the index of the given graph panel

    int index = indexOf(pGraphPanel);

    // Hide the graph panel and then delete it

    pGraphPanel->hide();

    delete pGraphPanel;

    // Activate the next graph panel or the last one available, if any

    if (index < count())
        // There is a next graph panel, so activate it

        qobject_cast<SingleCellViewGraphPanelWidget *>(widget(index))->setActive(true);
    else
        // We were dealing with the last graph panel, so just activate the new
        // last graph panel

        qobject_cast<SingleCellViewGraphPanelWidget *>(widget(count()-1))->setActive(true);

    // Keep track of our new sizes

    splitterMoved();

    // Let people know that we have removed the given graph panel
    // Note: the reason we pass a pointer to a now non-existing graph panel is
    //       that some people interested in that signal might have used the
    //       pointer to keep track of some information, as is done in
    //       SingleCellViewInformationGraphsWidget for example...

    emit graphPanelRemoved(pGraphPanel);

    // Let people know whether graph panels can be removed

    emit removeGraphPanelsEnabled(count() > 1);
}

//==============================================================================

void SingleCellViewGraphPanelsWidget::removeCurrentGraphPanel()
{
    // Make sure that we don't have only one graph panel left

    if (count() == 1)
        return;

    // Remove the current graph panel

    removeGraphPanel(mActiveGraphPanel);
}

//==============================================================================

void SingleCellViewGraphPanelsWidget::removeAllGraphPanels()
{
    // Make sure that we don't have only one graph panel left

    if (count() == 1)
        return;

    // Remove all the graph panels but one
    // Note: the one we keep is the very first one since it may be the user's
    //       most important graph panel...

    while (count() > 1)
        removeGraphPanel(qobject_cast<SingleCellViewGraphPanelWidget *>(widget(count()-1)));
}

//==============================================================================

void SingleCellViewGraphPanelsWidget::splitterMoved()
{
    // Our splitter has been moved, so keep track of its new sizes

    mSplitterSizes = sizes();
}

//==============================================================================

void SingleCellViewGraphPanelsWidget::updateGraphPanels(SingleCellViewGraphPanelWidget *pGraphPanel)
{
    // Keep track of the newly activated graph panel

    mActiveGraphPanel = pGraphPanel;

    // Inactivate all the other graph panels

    for (int i = 0, iMax = count(); i < iMax; ++i) {
        SingleCellViewGraphPanelWidget *graphPanel = qobject_cast<SingleCellViewGraphPanelWidget *>(widget(i));

        if (graphPanel != pGraphPanel)
            // We are not dealing with the graph panel that just got activated,
            // so inactivate it

            graphPanel->setActive(false);
    }
}

//==============================================================================

}   // namespace SingleCellView
}   // namespace OpenCOR

//==============================================================================
// End of file
//==============================================================================
<commit_msg>Addressed an issue with removing a graph panel which contains at least one graph (#31).<commit_after>//==============================================================================
// Single cell view graph panels widget
//==============================================================================

#include "singlecellviewgraphpanelplotwidget.h"
#include "singlecellviewgraphpanelswidget.h"
#include "singlecellviewgraphpanelwidget.h"

//==============================================================================

#include <QSettings>
#include <QWheelEvent>

//==============================================================================

namespace OpenCOR {
namespace SingleCellView {

//==============================================================================

SingleCellViewGraphPanelsWidget::SingleCellViewGraphPanelsWidget(QWidget *pParent) :
    QSplitter(pParent),
    CommonWidget(pParent),
    mSplitterSizes(QList<int>()),
    mActiveGraphPanel(0)
{
    // Set our orientation

    setOrientation(Qt::Vertical);

    // Keep track of our movement
    // Note: we need to keep track of our movement so that saveSettings() can
    //       work fine even when we are not visible (which happens when a CellML
    //       file cannot be run for some reason or another)...

    connect(this, SIGNAL(splitterMoved(int,int)),
            this, SLOT(splitterMoved()));
}

//==============================================================================

static const QString SettingsGraphPanelsCount = "GraphPanelsCount";
static const QString SettingsGraphPanelSize   = "GraphPanelSize%1";
//static const QString SettingsActiveGraphPanel = "ActiveGraphPanel";
//---GRY--- WE DON'T CURRENTLY KEEP TRACK OF THE REQUIRED GRAPHS, SO NO POINT IN
//          KEEPING TRACK OF WHICH GRAPH PANEL IS ACTIVE...

//==============================================================================

void SingleCellViewGraphPanelsWidget::loadSettings(QSettings *pSettings)
{
    // Let the user know of a few default things about ourselves by emitting a
    // few signals

    emit removeGraphPanelsEnabled(false);

    // Retrieve the number of graph panels and create the corresponding number
    // of graphs

    int graphPanelsCount = pSettings->value(SettingsGraphPanelsCount, 1).toInt();

    if (!graphPanelsCount)
        // For some reason, the settings for the number of graph panels to be
        // created got messed up, so...

        graphPanelsCount = 1;

    for (int i = 0; i < graphPanelsCount; ++i)
        addGraphPanel();

    // Retrieve and set the size of each graph panel

    mSplitterSizes = QList<int>();

    for (int i = 0; i < graphPanelsCount; ++i)
        mSplitterSizes << pSettings->value(SettingsGraphPanelSize.arg(i)).toInt();

    setSizes(mSplitterSizes);

    // Select the graph panel that used to be active

//    qobject_cast<SingleCellViewGraphPanelWidget *>(widget(pSettings->value(SettingsActiveGraphPanel, 0).toInt()))->setActive(true);
qobject_cast<SingleCellViewGraphPanelWidget *>(widget(0))->setActive(true);
}

//==============================================================================

void SingleCellViewGraphPanelsWidget::saveSettings(QSettings *pSettings) const
{
    // Keep track of the number of graph panels, of the size of each graph panel
    // and of which graph panel is the active one

    pSettings->setValue(SettingsGraphPanelsCount, mSplitterSizes.count());

    for (int i = 0, iMax = mSplitterSizes.count(); i < iMax; ++i)
        pSettings->setValue(SettingsGraphPanelSize.arg(i), mSplitterSizes[i]);

//    for (int i = 0, iMax = mSplitterSizes.count(); i < iMax; ++i)
//        if (qobject_cast<SingleCellViewGraphPanelWidget *>(widget(i))->isActive()) {
//            // We found the active graph panel, so...

//            pSettings->setValue(SettingsActiveGraphPanel, i);

//            break;
//        }
}

//==============================================================================

QList<SingleCellViewGraphPanelWidget *> SingleCellViewGraphPanelsWidget::graphPanels() const
{
    // Return all our graph panels

    QList<SingleCellViewGraphPanelWidget *> res = QList<SingleCellViewGraphPanelWidget *>();

    for (int i = 0, iMax = count(); i < iMax; ++i)
        res << qobject_cast<SingleCellViewGraphPanelWidget *>(widget(i));

    return res;
}

//==============================================================================

SingleCellViewGraphPanelWidget * SingleCellViewGraphPanelsWidget::activeGraphPanel() const
{
    // Return the active graph panel

    for (int i = 0, iMax = count(); i < iMax; ++i) {
        SingleCellViewGraphPanelWidget *graphPanel = qobject_cast<SingleCellViewGraphPanelWidget *>(widget(i));

        if (graphPanel->isActive())
            // We found the active graph panel, so...

            return graphPanel;
    }

    // There are no graph panels, so...
    // Note: we should never reach this point since there should always be at
    //       least one graph panel...

    return 0;
}

//==============================================================================

SingleCellViewGraphPanelWidget * SingleCellViewGraphPanelsWidget::addGraphPanel()
{
    // Keep track of the graph panels' original size

    QList<int> origSizes = sizes();

    // Create a new graph panel

    SingleCellViewGraphPanelWidget *res = new SingleCellViewGraphPanelWidget(this);

    // Add the graph panel to ourselves

    addWidget(res);

    // Resize the graph panels, thus making sure that their size is what it
    // should be (see issue #58)

    double scalingFactor = double(count()-1)/count();

    for (int i = 0, iMax = origSizes.count(); i < iMax; ++i)
        origSizes[i] *= scalingFactor;

    setSizes(origSizes << height()/count());

    // Keep track of whenever a graph panel gets activated

    connect(res, SIGNAL(activated(SingleCellViewGraphPanelWidget *)),
            this, SIGNAL(graphPanelActivated(SingleCellViewGraphPanelWidget *)));

    connect(res, SIGNAL(activated(SingleCellViewGraphPanelWidget *)),
            this, SLOT(updateGraphPanels(SingleCellViewGraphPanelWidget *)));

    // Keep track of the addition and removal of a graph

    connect(res, SIGNAL(graphAdded(SingleCellViewGraphPanelPlotGraph *)),
            this, SIGNAL(graphAdded(SingleCellViewGraphPanelPlotGraph *)));
    connect(res, SIGNAL(graphRemoved(SingleCellViewGraphPanelPlotGraph *)),
            this, SIGNAL(graphRemoved(SingleCellViewGraphPanelPlotGraph *)));

    // Activate the graph panel

    res->setActive(true);

    // Keep track of our new sizes

    splitterMoved();

    // Let people know that we have added a graph panel

    emit graphPanelAdded(res);

    // Let people know whether graph panels can be removed

    emit removeGraphPanelsEnabled(count() > 1);

    // Return our newly created graph panel

    return res;
}

//==============================================================================

void SingleCellViewGraphPanelsWidget::removeGraphPanel(SingleCellViewGraphPanelWidget *pGraphPanel)
{
    if (!pGraphPanel)
        return;

    // Retrieve the index of the given graph panel

    int index = indexOf(pGraphPanel);

    // Hide the graph panel and then delete it

    pGraphPanel->hide();

    delete pGraphPanel;

    // Let people know that we have removed the given graph panel
    // Note: the reason we pass a pointer to a now non-existing graph panel is
    //       that some people interested in that signal might have used the
    //       pointer to keep track of some information, as is done in
    //       SingleCellViewInformationGraphsWidget for example...

    emit graphPanelRemoved(pGraphPanel);

    // Let people know whether graph panels can be removed

    emit removeGraphPanelsEnabled(count() > 1);

    // Activate the next graph panel or the last one available, if any

    if (index < count())
        // There is a next graph panel, so activate it

        qobject_cast<SingleCellViewGraphPanelWidget *>(widget(index))->setActive(true);
    else
        // We were dealing with the last graph panel, so just activate the new
        // last graph panel

        qobject_cast<SingleCellViewGraphPanelWidget *>(widget(count()-1))->setActive(true);

    // Keep track of our new sizes

    splitterMoved();
}

//==============================================================================

void SingleCellViewGraphPanelsWidget::removeCurrentGraphPanel()
{
    // Make sure that we don't have only one graph panel left

    if (count() == 1)
        return;

    // Remove the current graph panel

    removeGraphPanel(mActiveGraphPanel);
}

//==============================================================================

void SingleCellViewGraphPanelsWidget::removeAllGraphPanels()
{
    // Make sure that we don't have only one graph panel left

    if (count() == 1)
        return;

    // Remove all the graph panels but one
    // Note: the one we keep is the very first one since it may be the user's
    //       most important graph panel...

    while (count() > 1)
        removeGraphPanel(qobject_cast<SingleCellViewGraphPanelWidget *>(widget(count()-1)));
}

//==============================================================================

void SingleCellViewGraphPanelsWidget::splitterMoved()
{
    // Our splitter has been moved, so keep track of its new sizes

    mSplitterSizes = sizes();
}

//==============================================================================

void SingleCellViewGraphPanelsWidget::updateGraphPanels(SingleCellViewGraphPanelWidget *pGraphPanel)
{
    // Keep track of the newly activated graph panel

    mActiveGraphPanel = pGraphPanel;

    // Inactivate all the other graph panels

    for (int i = 0, iMax = count(); i < iMax; ++i) {
        SingleCellViewGraphPanelWidget *graphPanel = qobject_cast<SingleCellViewGraphPanelWidget *>(widget(i));

        if (graphPanel != pGraphPanel)
            // We are not dealing with the graph panel that just got activated,
            // so inactivate it

            graphPanel->setActive(false);
    }
}

//==============================================================================

}   // namespace SingleCellView
}   // namespace OpenCOR

//==============================================================================
// End of file
//==============================================================================
<|endoftext|>


<commit_before>#ifndef STAN_MATH_PRIM_FUN_LOWER_REG_INC_GAMMA_HPP
#define STAN_MATH_PRIM_FUN_LOWER_REG_INC_GAMMA_HPP

#include <stan/math/prim/meta.hpp>
#include <stan/math/prim/err.hpp>
#include <stan/math/prim/fun/digamma.hpp>
#include <stan/math/prim/fun/exp.hpp>
#include <stan/math/prim/fun/gamma_p.hpp>
#include <stan/math/prim/fun/grad_reg_inc_gamma.hpp>
#include <stan/math/prim/fun/is_any_nan.hpp>
#include <stan/math/prim/fun/is_inf.hpp>
#include <stan/math/prim/fun/lgamma.hpp>
#include <stan/math/prim/fun/log.hpp>
#include <stan/math/prim/fun/log1p.hpp>
#include <stan/math/prim/fun/sqrt.hpp>
#include <stan/math/prim/fun/tgamma.hpp>
#include <stan/math/prim/fun/value_of_rec.hpp>
#include <limits>
#include <cmath>

namespace stan {
namespace math {

/**
 * Computes the gradient of the lower regularized incomplete
 * gamma function.
 *
 * The lower incomplete gamma function
 * derivative w.r.t its first parameter (a) seems to have no
 * standard source.  It also appears to have no widely known
 * approximate implementation.  Gautschi (1979) has a thorough
 * discussion of the calculation of the lower regularized
 * incomplete gamma function itself and some stability issues.
 *
 * Reference: Gautschi, Walter (1979) ACM Transactions on
 * mathematical software. 5(4):466-481
 *
 * We implemented calculations for d(gamma_p)/da by taking
 * derivatives of formulas suggested by Gauschi and others and
 * testing them against an outside source (Mathematica). We
 * took three implementations which can cover the range {a:[0,20],
 * z:[0,30]} with absolute error < 1e-10 with the exception of
 * values near (0,0) where the error is near 1e-5.  Relative error
 * is also <<1e-6 except for regions where the gradient approaches
 * zero.
 *
 * Gautschi suggests calculating the lower incomplete gamma
 * function for small to moderate values of $z$ using the
 * approximation:
 *
 * \f[
 *  \frac{\gamma(a,z)}{\Gamma(a)}=z^a e^-z
 *    \sum_n=0^\infty \frac{z^n}{\Gamma(a+n+1)}
 * \f]
 *
 * We write the derivative in the form:
 *
 * \f[
 *   \frac{d\gamma(a,z)\Gamma(a)}{da} = \frac{\log z}{e^z}
 *     \sum_n=0^\infty \frac{z^{a+n}}{\Gamma(a+n+1)}
 *   - \frac{1}{e^z}
 *     \sum_n=0^\infty \frac{z^{a+n}}{\Gamma(a+n+1)}\psi^0(a+n+1)
 * \f]
 *
 * This calculation is sufficiently accurate for small $a$ and
 * small $z$.  For larger values and $a$ and $z$ we use it in its
 * log form:
 *
 * \f[
 *   \frac{d \gamma(a,z)\Gamma(a)}{da} = \frac{\log z}{e^z}
 *     \sum_n=0^\infty \exp[(a+n)\log z - \log\Gamma(a+n+1)]
 *   - \sum_n=0^\infty \exp[(a+n)\log z - \log\Gamma(a+n+1) +
 *       \log\psi^0(a+n+1)]
 * \f]
 *
 * For large $z$, Gauschi recommends using the upper incomplete
 * Gamma instead and the negative of its derivative turns out to be
 * more stable and accurate for larger $z$ and for some combinations
 * of $a$ and $z$. This is a log-scale implementation of the
 * derivative of the formulation suggested by Gauschi (1979). For
 * some values it defers to the negative of the gradient
 * for the gamma_q function. This is based on the suggestion by Gauschi
 * (1979) that for large values of $z$ it is better to
 * carry out calculations using the upper incomplete Gamma function.
 *
 * Branching for choice of implementation for the lower incomplete
 * regularized gamma function gradient. The derivative based on
 * Gautschi's formulation appears to be sufficiently accurate
 * everywhere except for large z and small to moderate a. The
 * intersection between the two regions is a radius 12 quarter circle
 * centered at a=0, z=30 although both implementations are
 * satisfactory near the intersection.
 *
 * Some limits that could be treated, e.g., infinite z should
 * return tgamma(a) * digamma(a), throw instead to match the behavior of,
 * e.g., boost::math::gamma_p
 *
 * @tparam T1 type of a
 * @tparam T2 type of z
 * @param[in] a shared with complete Gamma
 * @param[in] z value to integrate up to
 * @param[in] precision series terminates when increment falls below
 * this value.
 * @param[in] max_steps number of terms to sum before throwing
 * @throw std::domain_error if the series does not converge to
 * requested precision before max_steps.
 *
 */
template <typename T1, typename T2>
return_type_t<T1, T2> grad_reg_lower_inc_gamma(const T1& a, const T2& z,
                                               double precision = 1e-10,
                                               int max_steps = 1e5) {
  using std::exp;
  using std::log;
  using std::pow;
  using std::sqrt;

  using TP = return_type_t<T1, T2>;

  if (is_any_nan(a, z)) {
    return std::numeric_limits<TP>::quiet_NaN();
  }

  check_positive_finite("grad_reg_lower_inc_gamma", "a", a);

  if (z == 0.0) {
    return 0.0;
  }
  check_positive_finite("grad_reg_lower_inc_gamma", "z", z);

  if ((a < 0.8 && z > 15.0) || (a < 12.0 && z > 30.0)
      || a < sqrt(-756 - value_of_rec(z) * value_of_rec(z)
                  + 60 * value_of_rec(z))) {
    T1 tg = tgamma(a);
    T1 dig = digamma(a);
    return -grad_reg_inc_gamma(a, z, tg, dig, max_steps, precision);
  }

  T2 log_z = log(z);
  T2 emz = exp(-z);

  int n = 0;
  T1 a_plus_n = a;
  TP sum_a = 0.0;
  T1 lgamma_a_plus_1 = lgamma(a + 1);
  T1 lgamma_a_plus_n_plus_1 = lgamma_a_plus_1;
  TP term;
  while (true) {
    term = exp(a_plus_n * log_z - lgamma_a_plus_n_plus_1);
    sum_a += term;
    if (term <= precision) {
      break;
    }
    if (n >= max_steps) {
      throw_domain_error("grad_reg_lower_inc_gamma", "n (internal counter)",
                         max_steps, "exceeded ",
                         " iterations, gamma_p(a,z) gradient (a) "
                         "did not converge.");
    }
    ++n;
    lgamma_a_plus_n_plus_1 += log1p(a_plus_n);
    ++a_plus_n;
  }

  n = 1;
  a_plus_n = a + 1;
  TP sum_b = digamma(a + 1) * exp(a * log_z - lgamma_a_plus_1);
  lgamma_a_plus_n_plus_1 = lgamma_a_plus_1 + log(a_plus_n);
  while (true) {
    term = exp(a_plus_n * log_z - lgamma_a_plus_n_plus_1)
           * digamma(a_plus_n + 1);
    sum_b += term;
    if (term <= precision) {
      return emz * (log_z * sum_a - sum_b);
    }
    if (n >= max_steps) {
      throw_domain_error("grad_reg_lower_inc_gamma", "n (internal counter)",
                         max_steps, "exceeded ",
                         " iterations, gamma_p(a,z) gradient (a) "
                         "did not converge.");
    }
    ++n;
    lgamma_a_plus_n_plus_1 += log1p(a_plus_n);
    ++a_plus_n;
  }
}

}  // namespace math
}  // namespace stan

#endif
<commit_msg>make grad_reg_lower_inc_gamma faster<commit_after>#ifndef STAN_MATH_PRIM_FUN_LOWER_REG_INC_GAMMA_HPP
#define STAN_MATH_PRIM_FUN_LOWER_REG_INC_GAMMA_HPP

#include <stan/math/prim/meta.hpp>
#include <stan/math/prim/err.hpp>
#include <stan/math/prim/fun/digamma.hpp>
#include <stan/math/prim/fun/exp.hpp>
#include <stan/math/prim/fun/gamma_p.hpp>
#include <stan/math/prim/fun/grad_reg_inc_gamma.hpp>
#include <stan/math/prim/fun/is_any_nan.hpp>
#include <stan/math/prim/fun/is_inf.hpp>
#include <stan/math/prim/fun/lgamma.hpp>
#include <stan/math/prim/fun/log.hpp>
#include <stan/math/prim/fun/log1p.hpp>
#include <stan/math/prim/fun/sqrt.hpp>
#include <stan/math/prim/fun/tgamma.hpp>
#include <stan/math/prim/fun/value_of_rec.hpp>
#include <limits>
#include <cmath>

namespace stan {
namespace math {

/**
 * Computes the gradient of the lower regularized incomplete
 * gamma function.
 *
 * The lower incomplete gamma function
 * derivative w.r.t its first parameter (a) seems to have no
 * standard source.  It also appears to have no widely known
 * approximate implementation.  Gautschi (1979) has a thorough
 * discussion of the calculation of the lower regularized
 * incomplete gamma function itself and some stability issues.
 *
 * Reference: Gautschi, Walter (1979) ACM Transactions on
 * mathematical software. 5(4):466-481
 *
 * We implemented calculations for d(gamma_p)/da by taking
 * derivatives of formulas suggested by Gauschi and others and
 * testing them against an outside source (Mathematica). We
 * took three implementations which can cover the range {a:[0,20],
 * z:[0,30]} with absolute error < 1e-10 with the exception of
 * values near (0,0) where the error is near 1e-5.  Relative error
 * is also <<1e-6 except for regions where the gradient approaches
 * zero.
 *
 * Gautschi suggests calculating the lower incomplete gamma
 * function for small to moderate values of $z$ using the
 * approximation:
 *
 * \f[
 *  \frac{\gamma(a,z)}{\Gamma(a)}=z^a e^-z
 *    \sum_n=0^\infty \frac{z^n}{\Gamma(a+n+1)}
 * \f]
 *
 * We write the derivative in the form:
 *
 * \f[
 *   \frac{d\gamma(a,z)\Gamma(a)}{da} = \frac{\log z}{e^z}
 *     \sum_n=0^\infty \frac{z^{a+n}}{\Gamma(a+n+1)}
 *   - \frac{1}{e^z}
 *     \sum_n=0^\infty \frac{z^{a+n}}{\Gamma(a+n+1)}\psi^0(a+n+1)
 * \f]
 *
 * This calculation is sufficiently accurate for small $a$ and
 * small $z$.  For larger values and $a$ and $z$ we use it in its
 * log form:
 *
 * \f[
 *   \frac{d \gamma(a,z)\Gamma(a)}{da} = \frac{\log z}{e^z}
 *     \sum_n=0^\infty \exp[(a+n)\log z - \log\Gamma(a+n+1)]
 *   - \sum_n=0^\infty \exp[(a+n)\log z - \log\Gamma(a+n+1) +
 *       \log\psi^0(a+n+1)]
 * \f]
 *
 * For large $z$, Gauschi recommends using the upper incomplete
 * Gamma instead and the negative of its derivative turns out to be
 * more stable and accurate for larger $z$ and for some combinations
 * of $a$ and $z$. This is a log-scale implementation of the
 * derivative of the formulation suggested by Gauschi (1979). For
 * some values it defers to the negative of the gradient
 * for the gamma_q function. This is based on the suggestion by Gauschi
 * (1979) that for large values of $z$ it is better to
 * carry out calculations using the upper incomplete Gamma function.
 *
 * Branching for choice of implementation for the lower incomplete
 * regularized gamma function gradient. The derivative based on
 * Gautschi's formulation appears to be sufficiently accurate
 * everywhere except for large z and small to moderate a. The
 * intersection between the two regions is a radius 12 quarter circle
 * centered at a=0, z=30 although both implementations are
 * satisfactory near the intersection.
 *
 * Some limits that could be treated, e.g., infinite z should
 * return tgamma(a) * digamma(a), throw instead to match the behavior of,
 * e.g., boost::math::gamma_p
 *
 * @tparam T1 type of a
 * @tparam T2 type of z
 * @param[in] a shared with complete Gamma
 * @param[in] z value to integrate up to
 * @param[in] precision series terminates when increment falls below
 * this value.
 * @param[in] max_steps number of terms to sum before throwing
 * @throw std::domain_error if the series does not converge to
 * requested precision before max_steps.
 *
 */
template <typename T1, typename T2>
return_type_t<T1, T2> grad_reg_lower_inc_gamma(const T1& a, const T2& z,
                                               double precision = 1e-10,
                                               int max_steps = 1e5) {
  using std::exp;
  using std::log;
  using std::pow;
  using std::sqrt;

  using TP = return_type_t<T1, T2>;

  if (is_any_nan(a, z)) {
    return std::numeric_limits<TP>::quiet_NaN();
  }

  check_positive_finite("grad_reg_lower_inc_gamma", "a", a);

  if (z == 0.0) {
    return 0.0;
  }
  check_positive_finite("grad_reg_lower_inc_gamma", "z", z);

  if ((a < 0.8 && z > 15.0) || (a < 12.0 && z > 30.0)
      || a < sqrt(-756 - value_of_rec(z) * value_of_rec(z)
                  + 60 * value_of_rec(z))) {
    T1 tg = tgamma(a);
    T1 dig = digamma(a);
    return -grad_reg_inc_gamma(a, z, tg, dig, max_steps, precision);
  }

  T2 log_z = log(z);
  T2 emz = exp(-z);

  int n = 0;
  T1 a_plus_n = a;
  TP sum_a = 0.0;
  T1 lgamma_a_plus_1 = lgamma(a + 1);
  T1 lgamma_a_plus_n_plus_1 = lgamma_a_plus_1;
  TP term;
  while (true) {
    term = exp(a_plus_n * log_z - lgamma_a_plus_n_plus_1);
    sum_a += term;
    if (term <= precision) {
      break;
    }
    if (n >= max_steps) {
      throw_domain_error("grad_reg_lower_inc_gamma", "n (internal counter)",
                         max_steps, "exceeded ",
                         " iterations, gamma_p(a,z) gradient (a) "
                         "did not converge.");
    }
    ++n;
    lgamma_a_plus_n_plus_1 += log1p(a_plus_n);
    ++a_plus_n;
  }

  n = 1;
  a_plus_n = a + 1;
  TP digammap1 = digamma(a + 1);
  TP sum_b = digammap1 * exp(a * log_z - lgamma_a_plus_1);
  lgamma_a_plus_n_plus_1 = lgamma_a_plus_1 + log(a_plus_n);
  while (true) {
    digammap1 += 1 / a_plus_n;
    term = exp(a_plus_n * log_z - lgamma_a_plus_n_plus_1)
           * digammap1;
    sum_b += term;
    if (term <= precision) {
      return emz * (log_z * sum_a - sum_b);
    }
    if (n >= max_steps) {
      throw_domain_error("grad_reg_lower_inc_gamma", "n (internal counter)",
                         max_steps, "exceeded ",
                         " iterations, gamma_p(a,z) gradient (a) "
                         "did not converge.");
    }
    ++n;
    lgamma_a_plus_n_plus_1 += log1p(a_plus_n);
    ++a_plus_n;
  }
}

}  // namespace math
}  // namespace stan

#endif
<|endoftext|>


<commit_before>///////////////////////////////////////////////////////////////////////
// File:        input.cpp
// Description: Input layer class for neural network implementations.
// Author:      Ray Smith
// Created:     Thu Mar 13 09:10:34 PDT 2014
//
// (C) Copyright 2014, Google 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
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
///////////////////////////////////////////////////////////////////////

#include "input.h"

#include "allheaders.h"
#include "imagedata.h"
#include "pageres.h"
#include "scrollview.h"

namespace tesseract {

// Max height for variable height inputs before scaling anyway.
const int kMaxInputHeight = 48;

Input::Input(const STRING& name, int ni, int no)
    : Network(NT_INPUT, name, ni, no), cached_x_scale_(1) {}
Input::Input(const STRING& name, const StaticShape& shape)
    : Network(NT_INPUT, name, shape.height(), shape.depth()),
      shape_(shape),
      cached_x_scale_(1) {
  if (shape.height() == 1) ni_ = shape.depth();
}

Input::~Input() {
}

// Writes to the given file. Returns false in case of error.
bool Input::Serialize(TFile* fp) const {
  if (!Network::Serialize(fp)) return false;
  if (fp->FWrite(&shape_, sizeof(shape_), 1) != 1) return false;
  return true;
}

// Reads from the given file. Returns false in case of error.
// If swap is true, assumes a big/little-endian swap is needed.
bool Input::DeSerialize(bool swap, TFile* fp) {
  if (fp->FRead(&shape_, sizeof(shape_), 1) != 1) return false;
  // TODO(rays) swaps!
  return true;
}

// Returns an integer reduction factor that the network applies to the
// time sequence. Assumes that any 2-d is already eliminated. Used for
// scaling bounding boxes of truth data.
int Input::XScaleFactor() const {
  return 1;
}

// Provides the (minimum) x scale factor to the network (of interest only to
// input units) so they can determine how to scale bounding boxes.
void Input::CacheXScaleFactor(int factor) {
  cached_x_scale_ = factor;
}

// Runs forward propagation of activations on the input line.
// See Network for a detailed discussion of the arguments.
void Input::Forward(bool debug, const NetworkIO& input,
                    const TransposedArray* input_transpose,
                    NetworkScratch* scratch, NetworkIO* output) {
  *output = input;
}

// Runs backward propagation of errors on the deltas line.
// See NetworkCpp for a detailed discussion of the arguments.
bool Input::Backward(bool debug, const NetworkIO& fwd_deltas,
                     NetworkScratch* scratch,
                     NetworkIO* back_deltas) {
  tprintf("Input::Backward should not be called!!\n");
  return false;
}

// Creates and returns a Pix of appropriate size for the network from the
// image_data. If non-null, *image_scale returns the image scale factor used.
// Returns nullptr on error.
/* static */
Pix* Input::PrepareLSTMInputs(const ImageData& image_data,
                              const Network* network, int min_width,
                              TRand* randomizer, float* image_scale) {
  // Note that NumInputs() is defined as input image height.
  int target_height = network->NumInputs();
  int width, height;
  Pix* pix = image_data.PreScale(target_height, kMaxInputHeight, image_scale,
                                 &width, &height, nullptr);
  if (pix == nullptr) {
    tprintf("Bad pix from ImageData!\n");
    return nullptr;
  }
  if (width <= min_width || height < min_width) {
    tprintf("Image too small to scale!! (%dx%d vs min width of %d)\n", width,
            height, min_width);
    pixDestroy(&pix);
    return nullptr;
  }
  return pix;
}

// Converts the given pix to a NetworkIO of height and depth appropriate to the
// given StaticShape:
// If depth == 3, convert to 24 bit color, otherwise normalized grey.
// Scale to target height, if the shape's height is > 1, or its depth if the
// height == 1. If height == 0 then no scaling.
// NOTE: It isn't safe for multiple threads to call this on the same pix.
/* static */
void Input::PreparePixInput(const StaticShape& shape, const Pix* pix,
                            TRand* randomizer, NetworkIO* input) {
  bool color = shape.depth() == 3;
  Pix* var_pix = const_cast<Pix*>(pix);
  int depth = pixGetDepth(var_pix);
  Pix* normed_pix = nullptr;
  // On input to BaseAPI, an image is forced to be 1, 8 or 24 bit, without
  // colormap, so we just have to deal with depth conversion here.
  if (color) {
    // Force RGB.
    if (depth == 32)
      normed_pix = pixClone(var_pix);
    else
      normed_pix = pixConvertTo32(var_pix);
  } else {
    // Convert non-8-bit images to 8 bit.
    if (depth == 8)
      normed_pix = pixClone(var_pix);
    else
      normed_pix = pixConvertTo8(var_pix, false);
  }
  int width = pixGetWidth(normed_pix);
  int height = pixGetHeight(normed_pix);
  int target_height = shape.height();
  if (target_height == 1) target_height = shape.depth();
  if (target_height == 0) target_height = height;
  float im_factor = static_cast<float>(target_height) / height;
  if (im_factor != 1.0f) {
    // Get the scaled image.
    Pix* scaled_pix = pixScale(normed_pix, im_factor, im_factor);
    pixDestroy(&normed_pix);
    normed_pix = scaled_pix;
  }
  input->FromPix(shape, normed_pix, randomizer);
  pixDestroy(&normed_pix);
}

}  // namespace tesseract.
<commit_msg>lstm: Remove unused variable<commit_after>///////////////////////////////////////////////////////////////////////
// File:        input.cpp
// Description: Input layer class for neural network implementations.
// Author:      Ray Smith
// Created:     Thu Mar 13 09:10:34 PDT 2014
//
// (C) Copyright 2014, Google 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
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
///////////////////////////////////////////////////////////////////////

#include "input.h"

#include "allheaders.h"
#include "imagedata.h"
#include "pageres.h"
#include "scrollview.h"

namespace tesseract {

// Max height for variable height inputs before scaling anyway.
const int kMaxInputHeight = 48;

Input::Input(const STRING& name, int ni, int no)
    : Network(NT_INPUT, name, ni, no), cached_x_scale_(1) {}
Input::Input(const STRING& name, const StaticShape& shape)
    : Network(NT_INPUT, name, shape.height(), shape.depth()),
      shape_(shape),
      cached_x_scale_(1) {
  if (shape.height() == 1) ni_ = shape.depth();
}

Input::~Input() {
}

// Writes to the given file. Returns false in case of error.
bool Input::Serialize(TFile* fp) const {
  if (!Network::Serialize(fp)) return false;
  if (fp->FWrite(&shape_, sizeof(shape_), 1) != 1) return false;
  return true;
}

// Reads from the given file. Returns false in case of error.
// If swap is true, assumes a big/little-endian swap is needed.
bool Input::DeSerialize(bool swap, TFile* fp) {
  if (fp->FRead(&shape_, sizeof(shape_), 1) != 1) return false;
  // TODO(rays) swaps!
  return true;
}

// Returns an integer reduction factor that the network applies to the
// time sequence. Assumes that any 2-d is already eliminated. Used for
// scaling bounding boxes of truth data.
int Input::XScaleFactor() const {
  return 1;
}

// Provides the (minimum) x scale factor to the network (of interest only to
// input units) so they can determine how to scale bounding boxes.
void Input::CacheXScaleFactor(int factor) {
  cached_x_scale_ = factor;
}

// Runs forward propagation of activations on the input line.
// See Network for a detailed discussion of the arguments.
void Input::Forward(bool debug, const NetworkIO& input,
                    const TransposedArray* input_transpose,
                    NetworkScratch* scratch, NetworkIO* output) {
  *output = input;
}

// Runs backward propagation of errors on the deltas line.
// See NetworkCpp for a detailed discussion of the arguments.
bool Input::Backward(bool debug, const NetworkIO& fwd_deltas,
                     NetworkScratch* scratch,
                     NetworkIO* back_deltas) {
  tprintf("Input::Backward should not be called!!\n");
  return false;
}

// Creates and returns a Pix of appropriate size for the network from the
// image_data. If non-null, *image_scale returns the image scale factor used.
// Returns nullptr on error.
/* static */
Pix* Input::PrepareLSTMInputs(const ImageData& image_data,
                              const Network* network, int min_width,
                              TRand* randomizer, float* image_scale) {
  // Note that NumInputs() is defined as input image height.
  int target_height = network->NumInputs();
  int width, height;
  Pix* pix = image_data.PreScale(target_height, kMaxInputHeight, image_scale,
                                 &width, &height, nullptr);
  if (pix == nullptr) {
    tprintf("Bad pix from ImageData!\n");
    return nullptr;
  }
  if (width <= min_width || height < min_width) {
    tprintf("Image too small to scale!! (%dx%d vs min width of %d)\n", width,
            height, min_width);
    pixDestroy(&pix);
    return nullptr;
  }
  return pix;
}

// Converts the given pix to a NetworkIO of height and depth appropriate to the
// given StaticShape:
// If depth == 3, convert to 24 bit color, otherwise normalized grey.
// Scale to target height, if the shape's height is > 1, or its depth if the
// height == 1. If height == 0 then no scaling.
// NOTE: It isn't safe for multiple threads to call this on the same pix.
/* static */
void Input::PreparePixInput(const StaticShape& shape, const Pix* pix,
                            TRand* randomizer, NetworkIO* input) {
  bool color = shape.depth() == 3;
  Pix* var_pix = const_cast<Pix*>(pix);
  int depth = pixGetDepth(var_pix);
  Pix* normed_pix = nullptr;
  // On input to BaseAPI, an image is forced to be 1, 8 or 24 bit, without
  // colormap, so we just have to deal with depth conversion here.
  if (color) {
    // Force RGB.
    if (depth == 32)
      normed_pix = pixClone(var_pix);
    else
      normed_pix = pixConvertTo32(var_pix);
  } else {
    // Convert non-8-bit images to 8 bit.
    if (depth == 8)
      normed_pix = pixClone(var_pix);
    else
      normed_pix = pixConvertTo8(var_pix, false);
  }
  int height = pixGetHeight(normed_pix);
  int target_height = shape.height();
  if (target_height == 1) target_height = shape.depth();
  if (target_height == 0) target_height = height;
  float im_factor = static_cast<float>(target_height) / height;
  if (im_factor != 1.0f) {
    // Get the scaled image.
    Pix* scaled_pix = pixScale(normed_pix, im_factor, im_factor);
    pixDestroy(&normed_pix);
    normed_pix = scaled_pix;
  }
  input->FromPix(shape, normed_pix, randomizer);
  pixDestroy(&normed_pix);
}

}  // namespace tesseract.
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: pcrcommon.cxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: kz $ $Date: 2008-03-05 17:13:05 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_extensions.hxx"

#ifndef _EXTENSIONS_PROPCTRLR_PCRCOMMON_HXX_
#include "pcrcommon.hxx"
#endif
#ifndef _EXTENSIONS_PROPCTRLR_MODULEPRC_HXX_
#include "modulepcr.hxx"
#endif
#ifndef EXTENSIONS_PROPRESID_HRC
#include "propresid.hrc"
#endif

/** === begin UNO includes === **/
#ifndef _COM_SUN_STAR_UTIL_MEASUREUNIT_HPP_
#include <com/sun/star/util/MeasureUnit.hpp>
#endif
/** === end UNO includes === **/

#ifndef _RTL_USTRBUF_HXX_
#include <rtl/ustrbuf.hxx>
#endif

//............................................................................
namespace pcr
{
//............................................................................

    using namespace ::com::sun::star::util;

    //========================================================================
    //= HelpIdUrl
    //========================================================================
    //------------------------------------------------------------------------
    SmartId HelpIdUrl::getHelpId( const ::rtl::OUString& _rHelpURL )
    {
        SmartId aSmartHelpId( _rHelpURL );
        if ( 0 == _rHelpURL.compareToAscii( RTL_CONSTASCII_STRINGPARAM( "HID:" ) ) )
            aSmartHelpId = SmartId( _rHelpURL.copy( sizeof( "HID:" ) - 1 ).toInt32() );
        return aSmartHelpId;
    }

    //------------------------------------------------------------------------
    ::rtl::OUString HelpIdUrl::getHelpURL( sal_uInt32 _nHelpId )
    {
        ::rtl::OUStringBuffer aBuffer;
        aBuffer.appendAscii( "HID:" );
        aBuffer.append( (sal_Int32)_nHelpId );
        return aBuffer.makeStringAndClear();
    }
//............................................................................
} // namespace pcr
//............................................................................

<commit_msg>INTEGRATION: CWS changefileheader (1.8.14); FILE MERGED 2008/04/01 15:15:19 thb 1.8.14.3: #i85898# Stripping all external header guards 2008/04/01 12:29:50 thb 1.8.14.2: #i85898# Stripping all external header guards 2008/03/31 12:31:51 rt 1.8.14.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: pcrcommon.cxx,v $
 * $Revision: 1.9 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_extensions.hxx"
#include "pcrcommon.hxx"
#ifndef _EXTENSIONS_PROPCTRLR_MODULEPRC_HXX_
#include "modulepcr.hxx"
#endif
#ifndef EXTENSIONS_PROPRESID_HRC
#include "propresid.hrc"
#endif

/** === begin UNO includes === **/
#include <com/sun/star/util/MeasureUnit.hpp>
/** === end UNO includes === **/
#include <rtl/ustrbuf.hxx>

//............................................................................
namespace pcr
{
//............................................................................

    using namespace ::com::sun::star::util;

    //========================================================================
    //= HelpIdUrl
    //========================================================================
    //------------------------------------------------------------------------
    SmartId HelpIdUrl::getHelpId( const ::rtl::OUString& _rHelpURL )
    {
        SmartId aSmartHelpId( _rHelpURL );
        if ( 0 == _rHelpURL.compareToAscii( RTL_CONSTASCII_STRINGPARAM( "HID:" ) ) )
            aSmartHelpId = SmartId( _rHelpURL.copy( sizeof( "HID:" ) - 1 ).toInt32() );
        return aSmartHelpId;
    }

    //------------------------------------------------------------------------
    ::rtl::OUString HelpIdUrl::getHelpURL( sal_uInt32 _nHelpId )
    {
        ::rtl::OUStringBuffer aBuffer;
        aBuffer.appendAscii( "HID:" );
        aBuffer.append( (sal_Int32)_nHelpId );
        return aBuffer.makeStringAndClear();
    }
//............................................................................
} // namespace pcr
//............................................................................

<|endoftext|>


<commit_before>/* -*- mode: C++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
// vim:sts=4:sw=4:ts=4:noet:sr:cino=>s,f0,{0,g0,(0,\:0,t0,+0,=s
/*
 * Copyright (C) 2014 the FFLAS-FFPACK group
 *
 * Written by   Bastien Vialla<bastien.vialla@lirmm.fr>
 * Brice Boyer (briceboyer) <boyer.brice@gmail.com>
 *
 *
 * ========LICENCE========
 * This file is part of the library FFLAS-FFPACK.
 *
 * FFLAS-FFPACK is free software: you can redistribute it and/or modify
 * it under the terms of the  GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 * ========LICENCE========
 *.
 */

#ifndef __FFLASFFPACK_fflas_ffpack_utils_simd256_INL
#define __FFLASFFPACK_fflas_ffpack_utils_simd256_INL

struct Simd256fp_base {
#if defined(__FFLASFFPACK_HAVE_AVX2_INSTRUCTIONS)  or defined(__FFLASFFPACK_HAVE_AVX_INSTRUCTIONS)

	/*
	* Shuffle 128-bits selected by imm8 from a and b, and store the results in dst.
	* Args   :	[a0, a1]
	*			[b0, b1]
	* Return : [s[0..3]?a0:a1:b0:b1, s[4..7]?a0:a1:b0:b1]
	*/
	template<int s>
	static INLINE CONST __m256d permute128(const __m256d a, const __m256d b) {
		return _mm256_permute2f128_pd(a, b, s);
	}

	template<int s>
	static INLINE CONST __m256 permute128(const __m256 a, const __m256 b) {
		return _mm256_permute2f128_ps(a, b, s);
	}

	/*
	* Unpack and interleave 128-bit integers from the low half of a and b, and store the results in dst.
	* Args   : [a0, a1] int128_t
			   [b0, b1] int128_t
	* Return : [a0, b0] int128_t
	*/
	static INLINE CONST __m256d unpacklo128(const __m256d a, const __m256d b) { return permute128<0x20>(a, b); }
	static INLINE CONST __m256 unpacklo128(const __m256 a, const __m256 b) { return permute128<0x20>(a, b); }

	/*
	* Unpack and interleave 128-bit integers from the high half of a and b, and store the results in dst.
	* Args   : [a0, a1] int128_t
			   [b0, b1] int128_t
	* Return : [a1, b1] int128_t
	*/
	static INLINE CONST __m256d unpackhi128(const __m256d a, const __m256d b) { return permute128<0x31>(a, b); }
	static INLINE CONST __m256 unpackhi128(const __m256 a, const __m256 b) { return permute128<0x31>(a, b); }

#endif
};

struct Simd256i_base {

	/*
	* alias to 256 bit simd register
	*/
	using vect_t = __m256i;

	/*
	*  Return vector of type vect_t with all elements set to zero
	*  Return [0, ...,0]
	*/
	static INLINE CONST vect_t zero() { return _mm256_setzero_si256(); }

#if defined(__FFLASFFPACK_HAVE_AVX2_INSTRUCTIONS) or defined(__FFLASFFPACK_HAVE_AVX_INSTRUCTIONS)

	/*
	* Shift packed 128-bit integers in a left by s bits while shifting in zeros, and store the results in vect_t.
	* Args   : [a0, a1] int128_t
	* Return : [a0 << (s*8), a1 << (s*8)] int128_t
	*/
	template<uint8_t s>
	static INLINE CONST vect_t sll128(const vect_t a) { return _mm256_bslli_epi128(a, s); }

	/*
	* Shift packed 128-bit integers in a right by s while shifting in zeros, and store the results in vect_t.
	* Args   : [a0, a1] int128_t
	* Return : [a0 << (s*8), a1 << (s*8)] int128_t
	*/
	template<uint8_t s>
	static INLINE CONST vect_t srl128(const vect_t a) { return _mm256_bsrli_epi128(a, s); }

	/*
	* Compute the bitwise AND and store the results in vect_t.
	* Args   : [a0, ..., a255]
	*		   [b0, ..., b255]
	* Return : [a0 AND b0, ..., a255 AND b255]
	*/
	static INLINE CONST vect_t vand(const vect_t a, const vect_t b) { return _mm256_and_si256(b, a); }

	/*
	* Compute the bitwise OR and store the results in vect_t.
	* Args   : [a0, ..., a255]
	*		   [b0, ..., b255]
	* Return : [a0 OR b0, ..., a255 OR b255]
	*/
	static INLINE CONST vect_t vor(const vect_t a, const vect_t b) { return _mm256_or_si256(b, a); }

	/*
	* Compute the bitwise XOR and store the results in vect_t.
	* Args   : [a0, ..., a255]
	*		   [b0, ..., b255]
	* Return : [a0 XOR b0, ..., a255 XOR b255]
	*/
	static INLINE CONST vect_t vxor(const vect_t a, const vect_t b) { return _mm256_xor_si256(b, a); }

	/*
	* Compute the bitwise AND NOT and store the results in vect_t.
	* Args   : [a0, ..., a255]
	*		   [b0, ..., b255]
	* Return : [a0 AND (NOT b0), ..., a255 AND (NOT b255)]
	*/
	static INLINE CONST vect_t vandnot(const vect_t a, const vect_t b) { return _mm256_andnot_si256(b, a); }

	/*
	* Shuffle 128-bit integers in a and b using the control in imm8, and store the results in dst.
	* Args   :	[a0, a1] int128_t
	*			[b0, b1] int128_t
	* Return : [s[0..3]?a0:a1:b0:b1, s[4..7]?a0:a1:b0:b1] int128_t
	*/
	template<int s>
	static INLINE CONST vect_t permute128(const vect_t a, const vect_t b) {
		return _mm256_permute2x128_si256(a, b, s);
	}

	/*
	* Unpack and interleave 128-bit integers from the low half of a and b, and store the results in dst.
	* Args   : [a0, a1] int128_t
			   [b0, b1] int128_t
	* Return : [a0, b0] int128_t
	*/
	static INLINE CONST vect_t unpacklo128(const vect_t a, const vect_t b) { return permute128<0x20>(a, b); }

	/*
	* Unpack and interleave 128-bit integers from the high half of a and b, and store the results in dst.
	* Args   : [a0, a1] int128_t
			   [b0, b1] int128_t
	* Return : [a1, b1] int128_t
	*/
	static INLINE CONST vect_t unpackhi128(const vect_t a, const vect_t b) { return permute128<0x31>(a, b); }
#endif
};

template <bool ArithType, bool Int, bool Signed, int Size> struct Simd256_impl;

template <class T>
using Simd256 =
	Simd256_impl<std::is_arithmetic<T>::value, std::is_integral<T>::value, std::is_signed<T>::value, sizeof(T)>;

#include "simd256_float.inl"
#include "simd256_double.inl"

#ifdef SIMD_INT

#if defined(__FFLASFFPACK_HAVE_AVX2_INSTRUCTIONS)
#include "simd256_int64.inl"
#include "simd256_int32.inl"
#include "simd256_int16.inl"
#endif

#endif //#ifdef SIMD_INT

#endif // __FFLASFFPACK_fflas_ffpack_utils_simd256_INL
<commit_msg>Revert "fix FFLAS SIMD FLAG"<commit_after>/* -*- mode: C++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
// vim:sts=4:sw=4:ts=4:noet:sr:cino=>s,f0,{0,g0,(0,\:0,t0,+0,=s
/*
 * Copyright (C) 2014 the FFLAS-FFPACK group
 *
 * Written by   Bastien Vialla<bastien.vialla@lirmm.fr>
 * Brice Boyer (briceboyer) <boyer.brice@gmail.com>
 *
 *
 * ========LICENCE========
 * This file is part of the library FFLAS-FFPACK.
 *
 * FFLAS-FFPACK is free software: you can redistribute it and/or modify
 * it under the terms of the  GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 * ========LICENCE========
 *.
 */

#ifndef __FFLASFFPACK_fflas_ffpack_utils_simd256_INL
#define __FFLASFFPACK_fflas_ffpack_utils_simd256_INL

struct Simd256fp_base {
#if defined(__FFLASFFPACK_HAVE_AVX2_INSTRUCTIONS) or defined(__FFLASFFPACK_HAVE_AVX_INSTRUCTIONS)

	/*
	* Shuffle 128-bits selected by imm8 from a and b, and store the results in dst.
	* Args   :	[a0, a1]
	*			[b0, b1]
	* Return : [s[0..3]?a0:a1:b0:b1, s[4..7]?a0:a1:b0:b1]
	*/
	template<int s>
	static INLINE CONST __m256d permute128(const __m256d a, const __m256d b) {
		return _mm256_permute2f128_pd(a, b, s);
	}

	template<int s>
	static INLINE CONST __m256 permute128(const __m256 a, const __m256 b) {
		return _mm256_permute2f128_ps(a, b, s);
	}

	/*
	* Unpack and interleave 128-bit integers from the low half of a and b, and store the results in dst.
	* Args   : [a0, a1] int128_t
			   [b0, b1] int128_t
	* Return : [a0, b0] int128_t
	*/
	static INLINE CONST __m256d unpacklo128(const __m256d a, const __m256d b) { return permute128<0x20>(a, b); }
	static INLINE CONST __m256 unpacklo128(const __m256 a, const __m256 b) { return permute128<0x20>(a, b); }

	/*
	* Unpack and interleave 128-bit integers from the high half of a and b, and store the results in dst.
	* Args   : [a0, a1] int128_t
			   [b0, b1] int128_t
	* Return : [a1, b1] int128_t
	*/
	static INLINE CONST __m256d unpackhi128(const __m256d a, const __m256d b) { return permute128<0x31>(a, b); }
	static INLINE CONST __m256 unpackhi128(const __m256 a, const __m256 b) { return permute128<0x31>(a, b); }

#endif
};

struct Simd256i_base {

	/*
	* alias to 256 bit simd register
	*/
	using vect_t = __m256i;

	/*
	*  Return vector of type vect_t with all elements set to zero
	*  Return [0, ...,0]
	*/
	static INLINE CONST vect_t zero() { return _mm256_setzero_si256(); }

#if defined(__FFLASFFPACK_HAVE_AVX2_INSTRUCTIONS) or defined(__FFLASFFPACK_HAVE_AVX_INSTRUCTIONS)

	/*
	* Shift packed 128-bit integers in a left by s bits while shifting in zeros, and store the results in vect_t.
	* Args   : [a0, a1] int128_t
	* Return : [a0 << (s*8), a1 << (s*8)] int128_t
	*/
	template<uint8_t s>
	static INLINE CONST vect_t sll128(const vect_t a) { return _mm256_bslli_epi128(a, s); }

	/*
	* Shift packed 128-bit integers in a right by s while shifting in zeros, and store the results in vect_t.
	* Args   : [a0, a1] int128_t
	* Return : [a0 << (s*8), a1 << (s*8)] int128_t
	*/
	template<uint8_t s>
	static INLINE CONST vect_t srl128(const vect_t a) { return _mm256_bsrli_epi128(a, s); }

	/*
	* Compute the bitwise AND and store the results in vect_t.
	* Args   : [a0, ..., a255]
	*		   [b0, ..., b255]
	* Return : [a0 AND b0, ..., a255 AND b255]
	*/
	static INLINE CONST vect_t vand(const vect_t a, const vect_t b) { return _mm256_and_si256(b, a); }

	/*
	* Compute the bitwise OR and store the results in vect_t.
	* Args   : [a0, ..., a255]
	*		   [b0, ..., b255]
	* Return : [a0 OR b0, ..., a255 OR b255]
	*/
	static INLINE CONST vect_t vor(const vect_t a, const vect_t b) { return _mm256_or_si256(b, a); }

	/*
	* Compute the bitwise XOR and store the results in vect_t.
	* Args   : [a0, ..., a255]
	*		   [b0, ..., b255]
	* Return : [a0 XOR b0, ..., a255 XOR b255]
	*/
	static INLINE CONST vect_t vxor(const vect_t a, const vect_t b) { return _mm256_xor_si256(b, a); }

	/*
	* Compute the bitwise AND NOT and store the results in vect_t.
	* Args   : [a0, ..., a255]
	*		   [b0, ..., b255]
	* Return : [a0 AND (NOT b0), ..., a255 AND (NOT b255)]
	*/
	static INLINE CONST vect_t vandnot(const vect_t a, const vect_t b) { return _mm256_andnot_si256(b, a); }

	/*
	* Shuffle 128-bit integers in a and b using the control in imm8, and store the results in dst.
	* Args   :	[a0, a1] int128_t
	*			[b0, b1] int128_t
	* Return : [s[0..3]?a0:a1:b0:b1, s[4..7]?a0:a1:b0:b1] int128_t
	*/
	template<int s>
	static INLINE CONST vect_t permute128(const vect_t a, const vect_t b) {
		return _mm256_permute2x128_si256(a, b, s);
	}

	/*
	* Unpack and interleave 128-bit integers from the low half of a and b, and store the results in dst.
	* Args   : [a0, a1] int128_t
			   [b0, b1] int128_t
	* Return : [a0, b0] int128_t
	*/
	static INLINE CONST vect_t unpacklo128(const vect_t a, const vect_t b) { return permute128<0x20>(a, b); }

	/*
	* Unpack and interleave 128-bit integers from the high half of a and b, and store the results in dst.
	* Args   : [a0, a1] int128_t
			   [b0, b1] int128_t
	* Return : [a1, b1] int128_t
	*/
	static INLINE CONST vect_t unpackhi128(const vect_t a, const vect_t b) { return permute128<0x31>(a, b); }
#endif
};

template <bool ArithType, bool Int, bool Signed, int Size> struct Simd256_impl;

template <class T>
using Simd256 =
	Simd256_impl<std::is_arithmetic<T>::value, std::is_integral<T>::value, std::is_signed<T>::value, sizeof(T)>;

#include "simd256_float.inl"
#include "simd256_double.inl"

#ifdef SIMD_INT

#if defined(__FFLASFFPACK_HAVE_AVX2_INSTRUCTIONS)
#include "simd256_int64.inl"
#include "simd256_int32.inl"
#include "simd256_int16.inl"
#endif

#endif //#ifdef SIMD_INT

#endif // __FFLASFFPACK_fflas_ffpack_utils_simd256_INL
<|endoftext|>