<commit_before>/** \brief Utility for generating a dependency graph for externally-referenced symbols.
 *  \author Dr. Johannes Ruscheinski (johannes.ruscheinski@uni-tuebingen.de)
 *
 *  \copyright 2019 Universitätsbibliothek Tübingen.  All rights reserved.
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program 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 Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <algorithm>
#include <iostream>
#include <unordered_set>
#include <vector>
#include <cstdlib>
#include <cstring>
#include "ExecUtil.h"
#include "FileUtil.h"
#include "StringUtil.h"
#include "util.h"

namespace {

[[noreturn]] void Usage() {
    ::Usage("[--debug] absolute_library_paths");
}

struct LibraryAndSymbols {
    std::string library_path_;
    std::unordered_set<std::string> provided_, needed_;
public:
    LibraryAndSymbols() = default;
    LibraryAndSymbols(const LibraryAndSymbols &other) = default;
    explicit LibraryAndSymbols(const std::string &library_path): library_path_(library_path) { }
};

void ProcessLine(const bool debug, const std::string &line, LibraryAndSymbols * const library_and_symbols,
                 std::unordered_set<std::string> * const all_provided)
{
    std::vector<std::string> parts;
    StringUtil::SplitThenTrimWhite(line, ' ', &parts);
    if (parts.size() == 2 and parts[1] != "_GLOBAL_OFFSET_TABLE_")
        library_and_symbols->needed_.emplace(parts[1] + (debug ? " (" + parts[0] + ")" : ""));
    else if (parts.size() == 3) {
        all_provided->emplace(parts[2] + (debug ? " (U)" : ""));
        if (parts[1] == "T")
            library_and_symbols->provided_.emplace(parts[2] + (debug ? " (" + parts[1] + ")" : ""));
    }
}

void ExtractSymbols(const bool debug, LibraryAndSymbols * const library_and_symbols) {
    std::string stdout;
    const std::string COMMAND("nm " + library_and_symbols->library_path_);
    if (not ExecUtil::ExecSubcommandAndCaptureStdout(COMMAND, &stdout, /* suppress_stderr = */true))
        LOG_ERROR("failed to execute \"" + COMMAND + "\"!");

    std::unordered_set<std::string> all_provided;

    std::string line;
    for (const char ch : stdout) {
        if (ch == '\n') {
            ProcessLine(debug, line, library_and_symbols, &all_provided);
            line.clear();
        } else
            line += ch;
    }

    if (not line.empty())
        ProcessLine(debug, line, library_and_symbols, &all_provided);

    // Remove referenced symbols that are implemented in the library themselves:
    for (const auto &symbol : all_provided)
        library_and_symbols->needed_.erase(symbol);

    LOG_DEBUG(library_and_symbols->library_path_ + " provided: " + std::to_string(library_and_symbols->provided_.size())
              + " needed: " + std::to_string(library_and_symbols->needed_.size()));
}

void ListSymbols(const std::string &library_path, const std::string &description, const std::unordered_set<std::string> &symbols) {
    std::vector<std::string> sorted_symbols;
    sorted_symbols.reserve(symbols.size());

    for (const auto &symbol : symbols)
        sorted_symbols.emplace_back(symbol);
    std::sort(sorted_symbols.begin(), sorted_symbols.end());

    std::cout << FileUtil::GetBasename(library_path) << " (" << description << ")\n";
    for (const auto &symbol : sorted_symbols)
        std::cout << "    " << symbol << '\n';
}

} // unnamed namespace

int Main(int argc, char *argv[]) {
    if (argc == 1)
        Usage();

    bool debug(false);
    if (argc > 1 and std::strcmp("--debug", argv[1]) == 0) {
        debug = true;
        logger->setMinimumLogLevel(Logger::LL_DEBUG);
        --argc, ++argv;
    }
    if (argc < 1)
        Usage();

    std::vector<LibraryAndSymbols> libraries_and_symbols;
    for (int arg_no(1); arg_no < argc; ++arg_no) {
        LibraryAndSymbols new_library_and_symbols(argv[arg_no]);
        ExtractSymbols(debug, &new_library_and_symbols);
        if (debug) {
            ListSymbols(new_library_and_symbols.library_path_, "defined", new_library_and_symbols.provided_);
            ListSymbols(new_library_and_symbols.library_path_, "referenced", new_library_and_symbols.needed_);
        } else
            libraries_and_symbols.emplace_back(new_library_and_symbols);
    }

    if (debug) {
        std::unordered_set<std::string> found_external_references;
        for (const auto &lib1 : libraries_and_symbols) {
            for (const auto &lib2 : libraries_and_symbols) {
                if (lib1.library_path_ == lib2.library_path_)
                    continue;

                for (const auto &external_symbol : lib1.needed_) {
                    if (lib2.provided_.find(external_symbol) != lib2.provided_.cend())
                        found_external_references.emplace(external_symbol);
                }
            }
        }

        std::cout << "Missing external references:\n";
        for (const auto &lib : libraries_and_symbols) {
            for (const auto &external_symbol : lib.needed_) {
                if (found_external_references.find(external_symbol) == found_external_references.cend())
                    std::cout << external_symbol << " (" << FileUtil::GetBasename(lib.library_path_) << ")\n";
            }
        }
    } else {
        for (const auto &lib1 : libraries_and_symbols) {
            for (const auto &lib2 : libraries_and_symbols) {
                if (lib1.library_path_ == lib2.library_path_)
                    continue;

                for (const auto &external_symbol : lib1.needed_) {
                    if (lib2.provided_.find(external_symbol) != lib2.provided_.cend())
                        std::cout << FileUtil::GetLastPathComponent(lib1.library_path_) << " -> "
                                  << FileUtil::GetLastPathComponent(lib2.library_path_) << '\n';
                    break;
                }
            }
        }
    }

    return EXIT_SUCCESS;
}
<commit_msg>Fixed an obvious bug.<commit_after>/** \brief Utility for generating a dependency graph for externally-referenced symbols.
 *  \author Dr. Johannes Ruscheinski (johannes.ruscheinski@uni-tuebingen.de)
 *
 *  \copyright 2019 Universitätsbibliothek Tübingen.  All rights reserved.
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program 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 Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <algorithm>
#include <iostream>
#include <unordered_set>
#include <vector>
#include <cstdlib>
#include <cstring>
#include "ExecUtil.h"
#include "FileUtil.h"
#include "StringUtil.h"
#include "util.h"

namespace {

[[noreturn]] void Usage() {
    ::Usage("[--debug] absolute_library_paths");
}

struct LibraryAndSymbols {
    std::string library_path_;
    std::unordered_set<std::string> provided_, needed_;
public:
    LibraryAndSymbols() = default;
    LibraryAndSymbols(const LibraryAndSymbols &other) = default;
    explicit LibraryAndSymbols(const std::string &library_path): library_path_(library_path) { }
};

void ProcessLine(const bool debug, const std::string &line, LibraryAndSymbols * const library_and_symbols,
                 std::unordered_set<std::string> * const all_provided)
{
    std::vector<std::string> parts;
    StringUtil::SplitThenTrimWhite(line, ' ', &parts);
    if (parts.size() == 2 and parts[1] != "_GLOBAL_OFFSET_TABLE_")
        library_and_symbols->needed_.emplace(parts[1] + (debug ? " (" + parts[0] + ")" : ""));
    else if (parts.size() == 3) {
        all_provided->emplace(parts[2] + (debug ? " (U)" : ""));
        if (parts[1] == "T")
            library_and_symbols->provided_.emplace(parts[2] + (debug ? " (" + parts[1] + ")" : ""));
    }
}

void ExtractSymbols(const bool debug, LibraryAndSymbols * const library_and_symbols) {
    std::string stdout;
    const std::string COMMAND("nm " + library_and_symbols->library_path_);
    if (not ExecUtil::ExecSubcommandAndCaptureStdout(COMMAND, &stdout, /* suppress_stderr = */true))
        LOG_ERROR("failed to execute \"" + COMMAND + "\"!");

    std::unordered_set<std::string> all_provided;

    std::string line;
    for (const char ch : stdout) {
        if (ch == '\n') {
            ProcessLine(debug, line, library_and_symbols, &all_provided);
            line.clear();
        } else
            line += ch;
    }

    if (not line.empty())
        ProcessLine(debug, line, library_and_symbols, &all_provided);

    // Remove referenced symbols that are implemented in the library themselves:
    for (const auto &symbol : all_provided)
        library_and_symbols->needed_.erase(symbol);

    LOG_DEBUG(library_and_symbols->library_path_ + " provided: " + std::to_string(library_and_symbols->provided_.size())
              + " needed: " + std::to_string(library_and_symbols->needed_.size()));
}

void ListSymbols(const std::string &library_path, const std::string &description, const std::unordered_set<std::string> &symbols) {
    std::vector<std::string> sorted_symbols;
    sorted_symbols.reserve(symbols.size());

    for (const auto &symbol : symbols)
        sorted_symbols.emplace_back(symbol);
    std::sort(sorted_symbols.begin(), sorted_symbols.end());

    std::cout << FileUtil::GetBasename(library_path) << " (" << description << ")\n";
    for (const auto &symbol : sorted_symbols)
        std::cout << "    " << symbol << '\n';
}

} // unnamed namespace

int Main(int argc, char *argv[]) {
    if (argc == 1)
        Usage();

    bool debug(false);
    if (argc > 1 and std::strcmp("--debug", argv[1]) == 0) {
        debug = true;
        logger->setMinimumLogLevel(Logger::LL_DEBUG);
        --argc, ++argv;
    }
    if (argc < 1)
        Usage();

    std::vector<LibraryAndSymbols> libraries_and_symbols;
    for (int arg_no(1); arg_no < argc; ++arg_no) {
        LibraryAndSymbols new_library_and_symbols(argv[arg_no]);
        ExtractSymbols(debug, &new_library_and_symbols);
        if (debug) {
            ListSymbols(new_library_and_symbols.library_path_, "defined", new_library_and_symbols.provided_);
            ListSymbols(new_library_and_symbols.library_path_, "referenced", new_library_and_symbols.needed_);
        } else
            libraries_and_symbols.emplace_back(new_library_and_symbols);
    }

    if (debug) {
        std::unordered_set<std::string> found_external_references;
        for (const auto &lib1 : libraries_and_symbols) {
            for (const auto &lib2 : libraries_and_symbols) {
                if (lib1.library_path_ == lib2.library_path_)
                    continue;

                for (const auto &external_symbol : lib1.needed_) {
                    if (lib2.provided_.find(external_symbol) != lib2.provided_.cend())
                        found_external_references.emplace(external_symbol);
                }
            }
        }

        std::cout << "Missing external references:\n";
        for (const auto &lib : libraries_and_symbols) {
            for (const auto &external_symbol : lib.needed_) {
                if (found_external_references.find(external_symbol) == found_external_references.cend())
                    std::cout << external_symbol << " (" << FileUtil::GetBasename(lib.library_path_) << ")\n";
            }
        }
    } else {
        for (const auto &lib1 : libraries_and_symbols) {
            for (const auto &lib2 : libraries_and_symbols) {
                if (lib1.library_path_ == lib2.library_path_)
                    continue;

                for (const auto &external_symbol : lib1.needed_) {
                    if (lib2.provided_.find(external_symbol) != lib2.provided_.cend()) {
                        std::cout << FileUtil::GetLastPathComponent(lib1.library_path_) << " -> "
                                  << FileUtil::GetLastPathComponent(lib2.library_path_) << '\n';
                        break;
                    }
                }
            }
        }
    }

    return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/* -*- mode:linux -*- */
/**
 * \file tiles_state.cc
 *
 *
 *
 * \author Ethan Burns
 * \date 2008-11-03
 */

#include <assert.h>
#include <math.h>

#include <vector>
#include <iostream>

#include "tiles.h"
#include "tiles_state.h"

using namespace std;

void TilesState::compute_hash(void)
{
	unsigned int bits = 0;
	unsigned int n = tiles.size();
	const Tiles *t = dynamic_cast<const Tiles *>(domain);
	const vector<unsigned int> *ones = t->get_ones();

	hash_val = 0;
	for (int i = tiles.size() - 1; i >= 0; i -= 1) {
		unsigned int k = tiles[i];
		hash_val += (ones->at(bits >> (n - k)) * (n - 1 - i));
		bits |= 1 << (n - k - 1);
	}
}

TilesState::TilesState(SearchDomain *d, const State *parent, float g,
		       float h, vector<unsigned int> tiles,
		       unsigned int blank)
	: State(d, parent, g),
	  tiles(tiles),
	  blank(blank)
{
	this->h = h;
	compute_hash();
}

TilesState::TilesState(SearchDomain *d, const State *parent, float g,
		       vector<unsigned int> tiles, unsigned int blank)
	: State(d, parent, g),
	  tiles(tiles),
	  blank(blank)
{
	const Tiles::ManhattanDist *mh =
		dynamic_cast<const Tiles::ManhattanDist *>(domain->get_heuristic());
	mh == mh;
	assert(tiles[blank] == 0);
	this->h = domain->get_heuristic()->compute(this);
	assert(this->h == 0 ? is_goal() : 1);
	compute_hash();
}

/**
 * Test if the tiles are in order.
 */
bool TilesState::is_goal(void) const
{
	Tiles * t= dynamic_cast<Tiles*>(domain);

	return t->is_goal(this);
}

int TilesState::hash(void) const
{
	return hash_val;
}

State *TilesState::clone(void) const
{
	return new TilesState(domain, parent, g, tiles, blank);
}

void TilesState::print(ostream &o) const
{
	Tiles *t = dynamic_cast<Tiles*>(domain);
	unsigned int i = 0;

	o << "Hash: " << hash_val << endl;
	for (unsigned int y = 0; y < t->get_height(); y += 1) {
		for (unsigned int x = 0; x < t->get_width(); x += 1) {
			o << tiles[i];
			if (x < t->get_width() - 1)
				o << "\t";
			i += 1;
		}
		o << endl;
	}
}

/**
 * Test if two states are the same configuration.
 */
bool TilesState::equals(const State *s) const
{
	const TilesState *other = dynamic_cast<const TilesState *>(s);

	for (unsigned int i = 0; i < tiles.size(); i += 1)
		if (tiles[i] != other->tiles[i])
			return false;

	return true;
}

/**
 * Get the tile vector.
 */
const vector<unsigned int> *TilesState::get_tiles(void) const
{
	return &tiles;
}

/**
 * Get the blank position.
 */
unsigned int TilesState::get_blank(void) const
{
	return blank;
}
<commit_msg>Remove debug code.<commit_after>/* -*- mode:linux -*- */
/**
 * \file tiles_state.cc
 *
 *
 *
 * \author Ethan Burns
 * \date 2008-11-03
 */

#include <assert.h>
#include <math.h>

#include <vector>
#include <iostream>

#include "tiles.h"
#include "tiles_state.h"

using namespace std;

void TilesState::compute_hash(void)
{
	unsigned int bits = 0;
	unsigned int n = tiles.size();
	const Tiles *t = dynamic_cast<const Tiles *>(domain);
	const vector<unsigned int> *ones = t->get_ones();

	hash_val = 0;
	for (int i = tiles.size() - 1; i >= 0; i -= 1) {
		unsigned int k = tiles[i];
		hash_val += (ones->at(bits >> (n - k)) * (n - 1 - i));
		bits |= 1 << (n - k - 1);
	}
}

TilesState::TilesState(SearchDomain *d, const State *parent, float g,
		       float h, vector<unsigned int> tiles,
		       unsigned int blank)
	: State(d, parent, g),
	  tiles(tiles),
	  blank(blank)
{
	this->h = h;
	compute_hash();
}

TilesState::TilesState(SearchDomain *d, const State *parent, float g,
		       vector<unsigned int> tiles, unsigned int blank)
	: State(d, parent, g),
	  tiles(tiles),
	  blank(blank)
{
	assert(tiles[blank] == 0);
	this->h = domain->get_heuristic()->compute(this);
	assert(this->h == 0 ? is_goal() : 1);
	compute_hash();
}

/**
 * Test if the tiles are in order.
 */
bool TilesState::is_goal(void) const
{
	Tiles * t= dynamic_cast<Tiles*>(domain);

	return t->is_goal(this);
}

int TilesState::hash(void) const
{
	return hash_val;
}

State *TilesState::clone(void) const
{
	return new TilesState(domain, parent, g, tiles, blank);
}

void TilesState::print(ostream &o) const
{
	Tiles *t = dynamic_cast<Tiles*>(domain);
	unsigned int i = 0;

	o << "Hash: " << hash_val << endl;
	for (unsigned int y = 0; y < t->get_height(); y += 1) {
		for (unsigned int x = 0; x < t->get_width(); x += 1) {
			o << tiles[i];
			if (x < t->get_width() - 1)
				o << "\t";
			i += 1;
		}
		o << endl;
	}
}

/**
 * Test if two states are the same configuration.
 */
bool TilesState::equals(const State *s) const
{
	const TilesState *other = dynamic_cast<const TilesState *>(s);

	for (unsigned int i = 0; i < tiles.size(); i += 1)
		if (tiles[i] != other->tiles[i])
			return false;

	return true;
}

/**
 * Get the tile vector.
 */
const vector<unsigned int> *TilesState::get_tiles(void) const
{
	return &tiles;
}

/**
 * Get the blank position.
 */
unsigned int TilesState::get_blank(void) const
{
	return blank;
}
<|endoftext|>


<commit_before>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2015 Oslo and Akershus University College of Applied Sciences
// and Alfred Bratterud
//
// 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.

//#define DEBUG // Enable debugging
//#define DEBUG2

#include <kernel/elf.hpp>
#include <util/fixedvec.hpp>
#include <common>
#include <cassert>
#include <cstdlib>
#include <cstdint>
#include <map>
#include <stdexcept>

extern void print_backtrace();
extern void* heap_begin;
extern void* heap_end;
static void safe_print_symbol(int N, void* addr);

static char dbg_write_buffer[1024];
#include <unistd.h>
#define DPRINTF(X,...)  { \
        int L = snprintf(dbg_write_buffer, sizeof(dbg_write_buffer), \
        X, ##__VA_ARGS__); write(1, dbg_write_buffer, L); }

struct allocation
{
  allocation() : addr(0) {}
  allocation(char* A, size_t S, void* L1, void* L2, void* L3)
    :  addr(A), len(S), level1(L1), level2(L2), level3(L3) {}

  char*  addr;
  size_t len;
  void*  level1;
  void*  level2;
  void*  level3;
};

static int enable_debugging = 1;
static int enable_debugging_verbose = 0;
static int enable_buffer_protection = 1;
static fixedvector<allocation,  65536> allocs;
static fixedvector<allocation*, 65536> free_allocs;

// There is a chance of a buffer overrun where this exact value
// is written, but the chance of that happening is minimal
static const uint64_t buffer_protection_checksum = 0xdeadbeef1badcafe;

extern "C"
void _enable_heap_debugging(int enabled)
{
  enable_debugging = enabled;
}
extern "C"
void _enable_heap_debugging_verbose(int enabled)
{
  enable_debugging_verbose = enabled;
}
extern "C"
void _enable_heap_debugging_buffer_protection(int enabled)
{
  enable_buffer_protection = enabled;
}
extern "C"
int _get_heap_debugging_buffers_usage()
{
  return allocs.size();
}
extern "C"
int _get_heap_debugging_buffers_total()
{
  return allocs.capacity();
}

static allocation* find_alloc(char* addr)
{
  for (auto& x : allocs)
  if (x.addr) // nullptr's are free slots
  {
    if (addr >= x.addr && addr < x.addr + x.len)
        return &x; // perfect match or misaligned pointer
  }
  return nullptr;
}

void* operator new (std::size_t len) throw(std::bad_alloc)
{
  void* data = nullptr;

  if (enable_buffer_protection) {
    // Allocate requested memory + enough to fit checksum at start and end
    data = malloc(len + sizeof(buffer_protection_checksum) * 2);

    // Write checksums
    auto* temp = reinterpret_cast<char*>(data);
    memcpy(temp,
           &buffer_protection_checksum,
           sizeof(buffer_protection_checksum));

    memcpy(temp + sizeof(buffer_protection_checksum) + len,
           &buffer_protection_checksum,
           sizeof(buffer_protection_checksum));

  } else {
    data = malloc(len);
  }

  if (enable_debugging_verbose) {
    DPRINTF("malloc(%u bytes) == %p\n", len, data);
    safe_print_symbol(1, __builtin_return_address(0));
    safe_print_symbol(2, __builtin_return_address(1));
  }

  if (UNLIKELY(!data)) {
      print_backtrace();
      DPRINTF("malloc(%u bytes): FAILED\n", len);
      throw std::bad_alloc();
  }

  if (enable_debugging) {
    if (!free_allocs.empty()) {
      auto* x = free_allocs.pop();
      new(x) allocation((char*) data, len,
                        __builtin_return_address(0),
                        __builtin_return_address(1),
                        __builtin_return_address(2));
    } else if (!allocs.free_capacity()) {
      DPRINTF("[WARNING] Internal fixed vectors are FULL, expect bogus double free messages\n");
    } else {
      allocs.emplace((char*) data, len,
                      __builtin_return_address(0),
                      __builtin_return_address(1),
                      __builtin_return_address(2));
    }
  }

  if (enable_buffer_protection) {
    // We need to return a pointer to the allocated memory + 4
    // e.g. after our first checksum
    return reinterpret_cast<void*>(reinterpret_cast<char*>(data) +
                                   sizeof(buffer_protection_checksum));
  } else {
    return data;
  }
}
void* operator new[] (std::size_t n) throw(std::bad_alloc)
{
  return ::operator new (n);
}

inline static void deleted_ptr(void* ptr)
{
  if (enable_buffer_protection) {
    // Calculate where the real allocation starts (at our first checksum)
    ptr = reinterpret_cast<void*>(reinterpret_cast<char*>(ptr) -
                                  sizeof(buffer_protection_checksum));
  }

  if (enable_debugging) {
    auto* x = find_alloc((char*) ptr);
    if (x == nullptr) {
      if (ptr < heap_begin || ptr > heap_end) {
          DPRINTF("[ERROR] Free on invalid non-heap address: %p\n", ptr);
      } else {
          DPRINTF("[ERROR] Possible double free on address: %p\n", ptr);
      }
      print_backtrace();
      return;
    }
    else if (x->addr == ptr) {
      if (enable_debugging_verbose) {
        DPRINTF("free(%p) == %u bytes\n", x->addr, x->len);
        safe_print_symbol(1, __builtin_return_address(1));
        safe_print_symbol(2, __builtin_return_address(2));
      }

      // This is the only place where we can verify the buffer protection
      // checksums, since we need to know the length of the allocation
      if (enable_buffer_protection)
      {
        auto* temp = reinterpret_cast<char*>(ptr);
        auto underflow = memcmp(temp,
                                &buffer_protection_checksum,
                                sizeof(buffer_protection_checksum));
        auto overflow = memcmp(temp + sizeof(buffer_protection_checksum) + x->len,
                               &buffer_protection_checksum,
                               sizeof(buffer_protection_checksum));

        if (underflow)
        {
          DPRINTF("[ERROR] Buffer underflow found on address: %p\n", ptr);
          // TODO: print stacktrace
        }

        if (overflow)
        {
          DPRINTF("[ERROR] Buffer overflow found on address: %p\n", ptr);
          // TODO: print stacktrace
        }
      }

      // perfect match
      x->addr = nullptr;
      x->len  = 0;
      free_allocs.add(x);
    }
    else if (x->addr != ptr) {
      DPRINTF("[ERROR] Free on misaligned address: %p inside %p:%u",
             ptr, x->addr, x->len);
      print_backtrace();
      return;
    }
  }
  free(ptr);
}
void operator delete(void* ptr) throw()
{
  deleted_ptr(ptr);
}
void operator delete[] (void* ptr) throw()
{
  deleted_ptr(ptr);
}

static void safe_print_symbol(int N, void* addr)
{
  char _symbol_buffer[2048];
  char _btrace_buffer[2048];
  auto symb = Elf::safe_resolve_symbol(
              addr, _symbol_buffer, sizeof(_symbol_buffer));
  int len = snprintf(_btrace_buffer, sizeof(_btrace_buffer),
           "-> [%d] %8x + 0x%.3x: %s\n", \
           N, symb.addr, symb.offset, symb.name);\
  write(1, _btrace_buffer, len);
}

#include <delegate>
typedef delegate<bool(void*, size_t)> heap_print_func;

void print_heap_allocations(heap_print_func func)
{
  DPRINTF("Listing %u allocations...\n", allocs.size());
  for (auto& x : allocs) {
    if (x.addr != nullptr && func(x.addr, x.len)) {
      // entry
      DPRINTF("[%p] %u bytes\n", x.addr, x.len);
      // backtrace
      safe_print_symbol(1, x.level1);
      safe_print_symbol(2, x.level2);
      safe_print_symbol(3, x.level3);
    }
  }
}
<commit_msg>heap_debugging: Fix warnings in 64-bit<commit_after>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2015 Oslo and Akershus University College of Applied Sciences
// and Alfred Bratterud
//
// 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.

//#define DEBUG // Enable debugging
//#define DEBUG2

#include <kernel/elf.hpp>
#include <util/fixedvec.hpp>
#include <common>
#include <cassert>
#include <cstdlib>
#include <cstdint>
#include <map>
#include <stdexcept>

extern void print_backtrace();
extern void* heap_begin;
extern void* heap_end;
static void safe_print_symbol(int N, void* addr);

static char dbg_write_buffer[1024];
#include <unistd.h>
#define DPRINTF(X,...)  { \
        int L = snprintf(dbg_write_buffer, sizeof(dbg_write_buffer), \
        X, ##__VA_ARGS__); write(1, dbg_write_buffer, L); }

struct allocation
{
  allocation() : addr(0) {}
  allocation(char* A, size_t S, void* L1, void* L2, void* L3)
    :  addr(A), len(S), level1(L1), level2(L2), level3(L3) {}

  char*  addr;
  size_t len;
  void*  level1;
  void*  level2;
  void*  level3;
};

static int enable_debugging = 1;
static int enable_debugging_verbose = 0;
static int enable_buffer_protection = 1;
static fixedvector<allocation,  65536> allocs;
static fixedvector<allocation*, 65536> free_allocs;

// There is a chance of a buffer overrun where this exact value
// is written, but the chance of that happening is minimal
static const uint64_t buffer_protection_checksum = 0xdeadbeef1badcafe;

extern "C"
void _enable_heap_debugging(int enabled)
{
  enable_debugging = enabled;
}
extern "C"
void _enable_heap_debugging_verbose(int enabled)
{
  enable_debugging_verbose = enabled;
}
extern "C"
void _enable_heap_debugging_buffer_protection(int enabled)
{
  enable_buffer_protection = enabled;
}
extern "C"
int _get_heap_debugging_buffers_usage()
{
  return allocs.size();
}
extern "C"
int _get_heap_debugging_buffers_total()
{
  return allocs.capacity();
}

static allocation* find_alloc(char* addr)
{
  for (auto& x : allocs)
  if (x.addr) // nullptr's are free slots
  {
    if (addr >= x.addr && addr < x.addr + x.len)
        return &x; // perfect match or misaligned pointer
  }
  return nullptr;
}

void* operator new (std::size_t len) throw(std::bad_alloc)
{
  void* data = nullptr;

  if (enable_buffer_protection) {
    // Allocate requested memory + enough to fit checksum at start and end
    data = malloc(len + sizeof(buffer_protection_checksum) * 2);

    // Write checksums
    auto* temp = reinterpret_cast<char*>(data);
    memcpy(temp,
           &buffer_protection_checksum,
           sizeof(buffer_protection_checksum));

    memcpy(temp + sizeof(buffer_protection_checksum) + len,
           &buffer_protection_checksum,
           sizeof(buffer_protection_checksum));

  } else {
    data = malloc(len);
  }

  if (enable_debugging_verbose) {
    DPRINTF("malloc(%llu bytes) == %p\n", (unsigned long long) len, data);
    safe_print_symbol(1, __builtin_return_address(0));
    safe_print_symbol(2, __builtin_return_address(1));
  }

  if (UNLIKELY(!data)) {
      print_backtrace();
      DPRINTF("malloc(%llu bytes): FAILED\n", (unsigned long long) len);
      throw std::bad_alloc();
  }

  if (enable_debugging) {
    if (!free_allocs.empty()) {
      auto* x = free_allocs.pop();
      new(x) allocation((char*) data, len,
                        __builtin_return_address(0),
                        __builtin_return_address(1),
                        __builtin_return_address(2));
    } else if (!allocs.free_capacity()) {
      DPRINTF("[WARNING] Internal fixed vectors are FULL, expect bogus double free messages\n");
    } else {
      allocs.emplace((char*) data, len,
                      __builtin_return_address(0),
                      __builtin_return_address(1),
                      __builtin_return_address(2));
    }
  }

  if (enable_buffer_protection) {
    // We need to return a pointer to the allocated memory + 4
    // e.g. after our first checksum
    return reinterpret_cast<void*>(reinterpret_cast<char*>(data) +
                                   sizeof(buffer_protection_checksum));
  } else {
    return data;
  }
}
void* operator new[] (std::size_t n) throw(std::bad_alloc)
{
  return ::operator new (n);
}

inline static void deleted_ptr(void* ptr)
{
  if (enable_buffer_protection) {
    // Calculate where the real allocation starts (at our first checksum)
    ptr = reinterpret_cast<void*>(reinterpret_cast<char*>(ptr) -
                                  sizeof(buffer_protection_checksum));
  }

  if (enable_debugging) {
    auto* x = find_alloc((char*) ptr);
    if (x == nullptr) {
      if (ptr < heap_begin || ptr > heap_end) {
          DPRINTF("[ERROR] Free on invalid non-heap address: %p\n", ptr);
      } else {
          DPRINTF("[ERROR] Possible double free on address: %p\n", ptr);
      }
      print_backtrace();
      return;
    }
    else if (x->addr == ptr) {
      if (enable_debugging_verbose) {
        DPRINTF("free(%p) == %llu bytes\n", x->addr, (unsigned long long) x->len);
        safe_print_symbol(1, __builtin_return_address(1));
        safe_print_symbol(2, __builtin_return_address(2));
      }

      // This is the only place where we can verify the buffer protection
      // checksums, since we need to know the length of the allocation
      if (enable_buffer_protection)
      {
        auto* temp = reinterpret_cast<char*>(ptr);
        auto underflow = memcmp(temp,
                                &buffer_protection_checksum,
                                sizeof(buffer_protection_checksum));
        auto overflow = memcmp(temp + sizeof(buffer_protection_checksum) + x->len,
                               &buffer_protection_checksum,
                               sizeof(buffer_protection_checksum));

        if (underflow)
        {
          DPRINTF("[ERROR] Buffer underflow found on address: %p\n", ptr);
          // TODO: print stacktrace
        }

        if (overflow)
        {
          DPRINTF("[ERROR] Buffer overflow found on address: %p\n", ptr);
          // TODO: print stacktrace
        }
      }

      // perfect match
      x->addr = nullptr;
      x->len  = 0;
      free_allocs.add(x);
    }
    else if (x->addr != ptr) {
      DPRINTF("[ERROR] Free on misaligned address: %p inside %p:%llu",
             ptr, x->addr, (unsigned long long) x->len);
      print_backtrace();
      return;
    }
  }
  free(ptr);
}
void operator delete(void* ptr) throw()
{
  deleted_ptr(ptr);
}
void operator delete[] (void* ptr) throw()
{
  deleted_ptr(ptr);
}

static void safe_print_symbol(int N, void* addr)
{
  char _symbol_buffer[2048];
  char _btrace_buffer[2048];
  auto symb = Elf::safe_resolve_symbol(
              addr, _symbol_buffer, sizeof(_symbol_buffer));
  int len = snprintf(_btrace_buffer, sizeof(_btrace_buffer),
           "-> [%d] %16p + 0x%.3x: %s\n", \
           N, (void*) symb.addr, symb.offset, symb.name);\
  write(1, _btrace_buffer, len);
}

#include <delegate>
typedef delegate<bool(void*, size_t)> heap_print_func;

void print_heap_allocations(heap_print_func func)
{
  DPRINTF("Listing %u allocations...\n", allocs.size());
  for (auto& x : allocs) {
    if (x.addr != nullptr && func(x.addr, x.len)) {
      // entry
      DPRINTF("[%p] %llu bytes\n", x.addr, (unsigned long long) x.len);
      // backtrace
      safe_print_symbol(1, x.level1);
      safe_print_symbol(2, x.level2);
      safe_print_symbol(3, x.level3);
    }
  }
}
<|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
//#include "goto-def.h"

/* Copyright (c) FFLAS-FFPACK
* Written by Clément Pernet <clement.pernet@imag.fr>
* ========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========
*/

// Please do not commit with any of these defines on - AB 2015-01-12
//#define __FFLASFFPACK_USE_TBB
//#define __FFLASFFPACK_USE_OPENMP
//#define __FFLASFFPACK_USE_DATAFLOW
//#define WINO_PARALLEL_TMPS
//#define __FFLASFFPACK_FORCE_SEQ
//#define PFGEMM_WINO_SEQ 32
//#define CLASSIC_SEQ
#define CLASSIC_HYBRID
//#define WINO_SEQ
//#define FFT_PROFILER
//#define PROFILE_FGEMM_MP
#include "fflas-ffpack/fflas-ffpack-config.h"
#include <iostream>
#include <givaro/modular-balanced.h>

#include "fflas-ffpack/config-blas.h"
#include "fflas-ffpack/fflas/fflas.h"
#include "fflas-ffpack/utils/timer.h"
#include "fflas-ffpack/utils/args-parser.h"

#ifdef __FFLASFFPACK_USE_KAAPI
#include "libkomp.h"
#endif

using namespace std;
using namespace FFLAS;

int main(int argc, char** argv) {

	size_t iter = 3 ;
	Givaro::Integer q = 131071 ;
	size_t m = 2000 ;
	size_t k = 2000 ;
	size_t n = 2000 ;
	int nbw = -1 ;
	int p=0;
	int t=MAX_THREADS;
	int NBK = -1;

	Argument as[] = {
		{ 'q', "-q Q", "Set the field characteristic (-1 for random).",         TYPE_INTEGER , &q },
		{ 'm', "-m M", "Set the row dimension of A.",      TYPE_INT , &m },
		{ 'k', "-k K", "Set the col dimension of A.",      TYPE_INT , &k },
		{ 'n', "-n N", "Set the col dimension of B.",      TYPE_INT , &n },
		{ 'w', "-w N", "Set the number of winograd levels (-1 for random).",    TYPE_INT , &nbw },
		{ 'i', "-i R", "Set number of repetitions.",       TYPE_INT , &iter },
		{ 'p', "-p P", "0 for sequential, 1 for 2D iterative, 2 for 2D rec, 3 for 2D rec adaptive, 4 for 3D rc in-place, 5 for 3D rec, 6 for 3D rec adaptive.", TYPE_INT , &p },
		{ 't', "-t T", "number of virtual threads to drive the partition.", TYPE_INT , &t },
		{ 'b', "-b B", "number of numa blocks per dimension for the numa placement", TYPE_INT , &NBK },
		END_OF_ARGUMENTS
	};

	parseArguments(argc,argv,as);

	if (NBK==-1) NBK = t;
//  typedef Givaro::Modular<Givaro::Integer> Field;
//  typedef Givaro::Modular<int64_t> Field;
    typedef Givaro::Modular<double> Field;
//	typedef Givaro::Modular<float> Field;
//	typedef Givaro::ModularBalanced<float> Field;
//	typedef Givaro::ModularBalanced<double> Field;
//	typedef Givaro::Modular<Givaro::Integer> Field;
	typedef Field::Element Element;

  Field F(q);

  Timer chrono, TimFreivalds;
  double time=0.0, timev=0.0;

  Element * A, * B, * C;

  Field::RandIter G(F);
  A = fflas_new(F,m,k,Alignment::CACHE_PAGESIZE);
//#pragma omp parallel for collapse(2) schedule(runtime)
  PAR_BLOCK { pfrand(F,G, m,k,A,m/size_t(NBK)); }

  B = fflas_new(F,k,n,Alignment::CACHE_PAGESIZE);
//#pragma omp parallel for collapse(2) schedule(runtime)
  PAR_BLOCK { pfrand(F,G, k,n,B,k/NBK); }

  C = fflas_new(F,m,n,Alignment::CACHE_PAGESIZE);
//#pragma omp parallel for collapse(2) schedule(runtime)
  PAR_BLOCK { pfzero(F, m,n,C,m/NBK); }

  for (size_t i=0;i<=iter;++i){

      chrono.clear();
      if (p && p!=7){
	      // CuttingStrategy meth = RECURSIVE;
	      // StrategyParameter strat = THREADS;

	      typedef CuttingStrategy::Block block;
	      typedef CuttingStrategy::Recursive rec;
	      typedef StrategyParameter::Threads threads;
	      typedef StrategyParameter::TwoD  twod;
	      typedef StrategyParameter::TwoDAdaptive  twoda;
	      typedef StrategyParameter::ThreeD  threed;
	      typedef StrategyParameter::ThreeDAdaptive  threeda;
	      typedef StrategyParameter::ThreeDInPlace  threedip;
	      PAR_BLOCK{
              if (i) { chrono.start(); }

	      switch (p){
		  case 1:{
			  MMHelper<Field, MMHelperAlgo::Winograd, typename ModeTraits<Field>::value, ParSeqHelper::Parallel<block,threads> > WH(F,nbw, SPLITTER(t,block,threads));
			  fgemm (F, FflasNoTrans, FflasNoTrans, m,n,k, F.one, A, k, B, n, F.zero, C,n, WH);
			  break;}
		  case 2:{
			  MMHelper<Field, MMHelperAlgo::Winograd, typename ModeTraits<Field>::value, ParSeqHelper::Parallel<rec,twod> > WH(F,nbw, SPLITTER(t,rec,twod));
			  fgemm (F, FflasNoTrans, FflasNoTrans, m,n,k, F.one, A, k, B, n, F.zero, C,n, WH);
			  break;
		  }
		  case 3:{
			  MMHelper<Field, MMHelperAlgo::Winograd, typename ModeTraits<Field>::value, ParSeqHelper::Parallel<rec,twoda> > WH(F,nbw, SPLITTER(t,rec,twoda));
			  fgemm (F, FflasNoTrans, FflasNoTrans, m,n,k, F.one, A, k, B, n, F.zero, C,n, WH);
			  break;
		  }
		  case 4:{
			  MMHelper<Field, MMHelperAlgo::Winograd, typename ModeTraits<Field>::value, ParSeqHelper::Parallel<rec,threedip> > WH(F,nbw, SPLITTER(t,rec,threedip));
			  fgemm (F, FflasNoTrans, FflasNoTrans, m,n,k, F.one, A, k, B, n, F.zero, C,n, WH);
			  break;
		  }
		  case 5:{
			  MMHelper<Field, MMHelperAlgo::Winograd, typename ModeTraits<Field>::value, ParSeqHelper::Parallel<rec,threed> > WH(F,nbw, SPLITTER(t,rec,threed));
			  fgemm (F, FflasNoTrans, FflasNoTrans, m,n,k, F.one, A, k, B, n, F.zero, C,n, WH);
			  break;
		  }
		  case 6:{
			  MMHelper<Field, MMHelperAlgo::Winograd, typename ModeTraits<Field>::value, ParSeqHelper::Parallel<rec,threeda> > WH(F,nbw, SPLITTER(t,rec,threeda));
			  fgemm (F, FflasNoTrans, FflasNoTrans, m,n,k, F.one, A, k, B, n, F.zero, C,n, WH);
			  break;
		  }
		  default:{
			  MMHelper<Field, MMHelperAlgo::Winograd, typename ModeTraits<Field>::value, ParSeqHelper::Parallel<block,threads> > WH(F,nbw, SPLITTER(t,block,threads));
			  fgemm (F, FflasNoTrans, FflasNoTrans, m,n,k, F.one, A, k, B, n, F.zero, C,n, WH);
			  break;
		  }
	      }
		  }
	      if (i) {chrono.stop(); time+=chrono.realtime();}
      }else{
	      if(p==7){

			  int nrec = 0;
			  int dim = m;
			  //                      if(dim < 19000)
			  nrec--;
			  while(dim >= __FFLASFFPACK_WINOTHRESHOLD*2){
				  dim=dim/2;
				  nrec++;
			  }
			  nrec=std::max(1,nrec);
			  //			  std::cout<<" WINO_THREShold"<<__FFLASFFPACK_WINOTHRESHOLD<<" nrec = "<<nrec<<" dim = "<<dim<<std::endl;
			  if(nbw != -1)
				  nrec=nbw;
			  nbw=nrec;
			  if (i) chrono.start();
			  PAR_BLOCK
			  {
				  MMHelper<Field, MMHelperAlgo::WinogradPar,ModeTraits<Field>::value,ParSeqHelper::Parallel<> >  WH (F, nrec, ParSeqHelper::Parallel<>(t));
				  fgemm (F, FflasNoTrans, FflasNoTrans, m,n,k, F.one, A, k, B, n, F.zero, C,n,WH);
			  }
			  if (i) {chrono.stop(); time+=chrono.realtime();}

		      // MMHelper<Field, MMHelperAlgo::WinogradPar>
		      // 	      WH (F, nbw, ParSeqHelper::Sequential());
		      // 	  //		      cout<<"wino parallel"<<endl;
		      // if (i) chrono.start();
		      // PAR_BLOCK
		      // {
		      // 	      fgemm (F, FflasNoTrans, FflasNoTrans, m,n,k, F.one, A, k, B, n, F.zero, C,n,WH);
		      // }
		      // if (i) {chrono.stop(); time+=chrono.realtime();}
	      }
	      else{

		      MMHelper<Field,MMHelperAlgo::Winograd>//,
					  //typename FieldTraits<Field>::value,
					  //ParSeqHelper::Sequential>
			      WH (F, nbw, ParSeqHelper::Sequential());
		      if (i) chrono.start();
		      fgemm (F, FflasNoTrans, FflasNoTrans, m,n,k, F.one, A, k, B, n, F.zero, C,n,WH);
		      if (i) {chrono.stop(); time+=chrono.realtime();}
	      }
  }

      TimFreivalds.clear();
      TimFreivalds.start();

      bool pass = freivalds(F, FflasNoTrans, FflasNoTrans, m,n,k, F.one, A, k, B, n, C,n);
      TimFreivalds.stop();
      timev+=TimFreivalds.usertime();
      if (!pass)
	      std::cout<<"FAILED"<<std::endl;
}
  fflas_delete( A);
  fflas_delete( B);
  fflas_delete( C);

	// -----------
	// Standard output for benchmark - Alexis Breust 2014/11/14
	std::cout << "Time: " << time / double(iter)
			  << " Gfops: " << (2.*double(m)/1000.*double(n)/1000.*double(k)/1000.0) / time * double(iter);
	writeCommandString(std::cout, as) << std::endl;

#if __FFLASFFPACK_DEBUG
        std::cout<<"Freivalds vtime: "<<timev/(double)iter<<std::endl;
#endif

  return 0;
}

<commit_msg>median for bench fgemm<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
//#include "goto-def.h"

/* Copyright (c) FFLAS-FFPACK
* Written by Clément Pernet <clement.pernet@imag.fr>
* ========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========
*/

// Please do not commit with any of these defines on - AB 2015-01-12
//#define __FFLASFFPACK_USE_TBB
//#define __FFLASFFPACK_USE_OPENMP
//#define __FFLASFFPACK_USE_DATAFLOW
//#define WINO_PARALLEL_TMPS
//#define __FFLASFFPACK_FORCE_SEQ
//#define PFGEMM_WINO_SEQ 32
//#define CLASSIC_SEQ
#define CLASSIC_HYBRID
//#define WINO_SEQ
//#define FFT_PROFILER
//#define PROFILE_FGEMM_MP
#include "fflas-ffpack/fflas-ffpack-config.h"
#include <iostream>
#include <givaro/modular-balanced.h>

#include "fflas-ffpack/config-blas.h"
#include "fflas-ffpack/fflas/fflas.h"
#include "fflas-ffpack/utils/timer.h"
#include "fflas-ffpack/utils/args-parser.h"

#ifdef __FFLASFFPACK_USE_KAAPI
#include "libkomp.h"
#endif

using namespace std;
using namespace FFLAS;

int main(int argc, char** argv) {

	size_t iter = 3 ;
	Givaro::Integer q = 131071 ;
	size_t m = 2000 ;
	size_t k = 2000 ;
	size_t n = 2000 ;
	int nbw = -1 ;
	int p=0;
	int t=MAX_THREADS;
	int NBK = -1;

	Argument as[] = {
		{ 'q', "-q Q", "Set the field characteristic (-1 for random).",         TYPE_INTEGER , &q },
		{ 'm', "-m M", "Set the row dimension of A.",      TYPE_INT , &m },
		{ 'k', "-k K", "Set the col dimension of A.",      TYPE_INT , &k },
		{ 'n', "-n N", "Set the col dimension of B.",      TYPE_INT , &n },
		{ 'w', "-w N", "Set the number of winograd levels (-1 for random).",    TYPE_INT , &nbw },
		{ 'i', "-i R", "Set number of repetitions.",       TYPE_INT , &iter },
		{ 'p', "-p P", "0 for sequential, 1 for 2D iterative, 2 for 2D rec, 3 for 2D rec adaptive, 4 for 3D rc in-place, 5 for 3D rec, 6 for 3D rec adaptive.", TYPE_INT , &p },
		{ 't', "-t T", "number of virtual threads to drive the partition.", TYPE_INT , &t },
		{ 'b', "-b B", "number of numa blocks per dimension for the numa placement", TYPE_INT , &NBK },
		END_OF_ARGUMENTS
	};

	parseArguments(argc,argv,as);

	if (NBK==-1) NBK = t;
//  typedef Givaro::Modular<Givaro::Integer> Field;
//  typedef Givaro::Modular<int64_t> Field;
    typedef Givaro::Modular<double> Field;
//	typedef Givaro::Modular<float> Field;
//	typedef Givaro::ModularBalanced<float> Field;
//	typedef Givaro::ModularBalanced<double> Field;
//	typedef Givaro::Modular<Givaro::Integer> Field;
	typedef Field::Element Element;

  Field F(q);

  Timer chrono, TimFreivalds;
  double timev=0.0;
  double *time=new double[iter];

  Element * A, * B, * C;

  Field::RandIter G(F);
  A = fflas_new(F,m,k,Alignment::CACHE_PAGESIZE);
//#pragma omp parallel for collapse(2) schedule(runtime)
  PAR_BLOCK { pfrand(F,G, m,k,A,m/size_t(NBK)); }

  B = fflas_new(F,k,n,Alignment::CACHE_PAGESIZE);
//#pragma omp parallel for collapse(2) schedule(runtime)
  PAR_BLOCK { pfrand(F,G, k,n,B,k/NBK); }

  C = fflas_new(F,m,n,Alignment::CACHE_PAGESIZE);
//#pragma omp parallel for collapse(2) schedule(runtime)
  PAR_BLOCK { pfzero(F, m,n,C,m/NBK); }

  for (size_t i=0;i<=iter;++i){

      chrono.clear();
      if (p && p!=7){
	      // CuttingStrategy meth = RECURSIVE;
	      // StrategyParameter strat = THREADS;

	      typedef CuttingStrategy::Block block;
	      typedef CuttingStrategy::Recursive rec;
	      typedef StrategyParameter::Threads threads;
	      typedef StrategyParameter::TwoD  twod;
	      typedef StrategyParameter::TwoDAdaptive  twoda;
	      typedef StrategyParameter::ThreeD  threed;
	      typedef StrategyParameter::ThreeDAdaptive  threeda;
	      typedef StrategyParameter::ThreeDInPlace  threedip;
	      PAR_BLOCK{
              if (i) { chrono.start(); }

	      switch (p){
		  case 1:{
			  MMHelper<Field, MMHelperAlgo::Winograd, typename ModeTraits<Field>::value, ParSeqHelper::Parallel<block,threads> > WH(F,nbw, SPLITTER(t,block,threads));
			  fgemm (F, FflasNoTrans, FflasNoTrans, m,n,k, F.one, A, k, B, n, F.zero, C,n, WH);
			  break;}
		  case 2:{
			  MMHelper<Field, MMHelperAlgo::Winograd, typename ModeTraits<Field>::value, ParSeqHelper::Parallel<rec,twod> > WH(F,nbw, SPLITTER(t,rec,twod));
			  fgemm (F, FflasNoTrans, FflasNoTrans, m,n,k, F.one, A, k, B, n, F.zero, C,n, WH);
			  break;
		  }
		  case 3:{
			  MMHelper<Field, MMHelperAlgo::Winograd, typename ModeTraits<Field>::value, ParSeqHelper::Parallel<rec,twoda> > WH(F,nbw, SPLITTER(t,rec,twoda));
			  fgemm (F, FflasNoTrans, FflasNoTrans, m,n,k, F.one, A, k, B, n, F.zero, C,n, WH);
			  break;
		  }
		  case 4:{
			  MMHelper<Field, MMHelperAlgo::Winograd, typename ModeTraits<Field>::value, ParSeqHelper::Parallel<rec,threedip> > WH(F,nbw, SPLITTER(t,rec,threedip));
			  fgemm (F, FflasNoTrans, FflasNoTrans, m,n,k, F.one, A, k, B, n, F.zero, C,n, WH);
			  break;
		  }
		  case 5:{
			  MMHelper<Field, MMHelperAlgo::Winograd, typename ModeTraits<Field>::value, ParSeqHelper::Parallel<rec,threed> > WH(F,nbw, SPLITTER(t,rec,threed));
			  fgemm (F, FflasNoTrans, FflasNoTrans, m,n,k, F.one, A, k, B, n, F.zero, C,n, WH);
			  break;
		  }
		  case 6:{
			  MMHelper<Field, MMHelperAlgo::Winograd, typename ModeTraits<Field>::value, ParSeqHelper::Parallel<rec,threeda> > WH(F,nbw, SPLITTER(t,rec,threeda));
			  fgemm (F, FflasNoTrans, FflasNoTrans, m,n,k, F.one, A, k, B, n, F.zero, C,n, WH);
			  break;
		  }
		  default:{
			  MMHelper<Field, MMHelperAlgo::Winograd, typename ModeTraits<Field>::value, ParSeqHelper::Parallel<block,threads> > WH(F,nbw, SPLITTER(t,block,threads));
			  fgemm (F, FflasNoTrans, FflasNoTrans, m,n,k, F.one, A, k, B, n, F.zero, C,n, WH);
			  break;
		  }
	      }
		  }
	      if (i) {chrono.stop(); time[i-1]=chrono.realtime();}
      }else{
	      if(p==7){

			  int nrec = 0;
			  int dim = m;
			  //                      if(dim < 19000)
			  nrec--;
			  while(dim >= __FFLASFFPACK_WINOTHRESHOLD*2){
				  dim=dim/2;
				  nrec++;
			  }
			  nrec=std::max(1,nrec);
			  //			  std::cout<<" WINO_THREShold"<<__FFLASFFPACK_WINOTHRESHOLD<<" nrec = "<<nrec<<" dim = "<<dim<<std::endl;
			  if(nbw != -1)
				  nrec=nbw;
			  nbw=nrec;
			  if (i) chrono.start();
			  PAR_BLOCK
			  {
				  MMHelper<Field, MMHelperAlgo::WinogradPar,ModeTraits<Field>::value,ParSeqHelper::Parallel<> >  WH (F, nrec, ParSeqHelper::Parallel<>(t));
				  fgemm (F, FflasNoTrans, FflasNoTrans, m,n,k, F.one, A, k, B, n, F.zero, C,n,WH);
			  }
			  if (i) {chrono.stop(); time[i-1]=chrono.realtime();}

		      // MMHelper<Field, MMHelperAlgo::WinogradPar>
		      // 	      WH (F, nbw, ParSeqHelper::Sequential());
		      // 	  //		      cout<<"wino parallel"<<endl;
		      // if (i) chrono.start();
		      // PAR_BLOCK
		      // {
		      // 	      fgemm (F, FflasNoTrans, FflasNoTrans, m,n,k, F.one, A, k, B, n, F.zero, C,n,WH);
		      // }
		      // if (i) {chrono.stop(); time+=chrono.realtime();}
	      }
	      else{

		      MMHelper<Field,MMHelperAlgo::Winograd>//,
					  //typename FieldTraits<Field>::value,
					  //ParSeqHelper::Sequential>
			      WH (F, nbw, ParSeqHelper::Sequential());
		      if (i) chrono.start();
		      fgemm (F, FflasNoTrans, FflasNoTrans, m,n,k, F.one, A, k, B, n, F.zero, C,n,WH);
		      if (i) {chrono.stop(); time[i-1]=chrono.realtime();}
	      }
  }

      TimFreivalds.clear();
      TimFreivalds.start();

      bool pass = freivalds(F, FflasNoTrans, FflasNoTrans, m,n,k, F.one, A, k, B, n, C,n);
      TimFreivalds.stop();
      timev+=TimFreivalds.usertime();
      if (!pass)
	      std::cout<<"FAILED"<<std::endl;
}
  fflas_delete( A);
  fflas_delete( B);
  fflas_delete( C);
  std::sort(time, time+iter);
  double mediantime = time[iter/2];
  delete[] time;

	// -----------
	// Standard output for benchmark - Alexis Breust 2014/11/14
	std::cout << "Time: " << mediantime
			  << " Gfops: " << (2.*double(m)/1000.*double(n)/1000.*double(k)/1000.0) / mediantime;
	writeCommandString(std::cout, as) << std::endl;

#if __FFLASFFPACK_DEBUG
        std::cout<<"Freivalds vtime: "<<timev/(double)iter<<std::endl;
#endif

  return 0;
}

<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <fstream>
#include <cstdint>

using namespace std;

template <typename T>
struct Node
{
	Node *left;
	Node *right;
	T data;
};

template <typename T>
class BinaryTree;

template <typename T>
std::ostream& operator<<(std::ostream&, const BinaryTree<T>&);

template <typename T>
class BinaryTree
{
private:
	Node<T>*root;
	int count;
public:
	BinaryTree();
	~BinaryTree();
	Node<T>* root_();
	int getCount()const;
	void insert_node(const T&x);
	Node<T> *find_node(const T&, Node<T>*)const;
	void remove_element(const T& temp);
	void deleteNode(Node<T>* temp);
	Node<T>* _deleteRoot(Node<T>* temp);
	void writing(const std::string& filename)const;
	friend std::ostream& operator<<<>(std::ostream&, const BinaryTree<T>&);
};

template <typename T>
BinaryTree<T>::BinaryTree()
{
	root = nullptr;
	count = 0;
}

template<typename T>
Node<T>* BinaryTree<T>::root_()
{
	return root;
}

template <typename T>
BinaryTree<T>::~BinaryTree()
{
	deleteNode(root);
}

template <typename T>
int BinaryTree<T>::getCount()const
{
	return count;
}

template<typename T>
void BinaryTree<T>::insert_node(const T&x)
{
	if (find_node(x, root_())) return;
	Node<T>* MyTree = new Node<T>;
	MyTree->data = x;
	MyTree->left = MyTree->right = 0;
	Node<T>* buff = root;
	Node<T>* temp = root;
	while (temp)
	{
		buff = temp;
		if (x < temp->data)
			temp = temp->left;
		else
			temp = temp->right;
	}
	if (!buff)
		root = MyTree;
	else
	{
		if (x < buff->data)
			buff->left = MyTree;
		else
			buff->right = MyTree;
	}
	++count;
}

template<typename T>
Node<T>* BinaryTree<T>::find_node(const T& data, Node<T>* temp) const
{
	if (temp == 0 || data == temp->data)
		return temp;
	if (data > temp->data)
		return find_node(data, temp->right);
	else
		return find_node(data, temp->left);
}

template<typename T>
void BinaryTree<T>::writing(const std::string& filename)const
{
	ofstream file_1(filename);
	file_1 << count << "\t";
	output(file_1, root);
	file_1.close();
}

template<typename T>
void BinaryTree<T>::deleteNode(Node<T>* temp)
{
	if (!temp)
	{
		throw "error";
	}
	if (temp->left)
	{
		deleteNode(temp->left);
		temp->left = nullptr;
	}

	if (temp->right)
	{
		deleteNode(temp->right);
		temp->right = nullptr;
	}
	delete temp;
}

template <typename T>
std::ostream& output(std::ostream& ost, const Node<T>* node, unsigned int level)
{
	if (!node)
		return ost;
	output(ost, node->right, level + 1);
	for (unsigned int i = 0; i < level; i++)
		ost << "\t";
	ost << node->data << std::endl;
	output(ost, node->left, level + 1);
	return ost;
}

template <typename T>
Node<T>* BinaryTree<T>::_deleteRoot(Node<T>* temp)
{
	Node<T>* buff, *parent;
	if (temp)
	{
		buff = temp->right;
		if (!buff)
		{
			buff = temp->left;
		}
		else
		{
			if (buff->left)
			{
				parent = temp;
				while (buff->left)
				{
					parent = buff;
					buff = buff->left;
				}
				parent->left = buff->right;
				buff->right = temp->right;
			}
			buff->left = temp->left;
		}
		delete temp;
		return buff;
	}
	return nullptr;
}

template <typename T>
void BinaryTree<T>::remove_element(const T& temp)
{
	Node<T>* buff = root, *parent;
	if (root)
	{
		if (root->data == temp)
		{
			root = _deleteRoot(root);
		}
		else
		{
			parent = root;
			if (temp < parent->data) buff = parent->left;
			else buff = parent->right;
			while (buff)
			{
				if (buff->data == temp)
					{
					if (temp < parent->data) parent->left = _deleteRoot(parent->left);
					else parent->right = _deleteRoot(parent->right);
					return;
				}
				parent = buff;
				if (temp < parent->data) buff = parent->left;
				else buff = parent->right;
			}
		}
	}
	--count;
}

template <typename T>
std::ostream& operator<<(std::ostream& ost, const BinaryTree<T>& temp)
{
	output(ost, temp.root, 0);
	return ost;
}

<commit_msg>Update BinaryTree.hpp<commit_after>#include <iostream>
#include <string>
#include <fstream>
#include <cstdint>

using namespace std;

template <typename T>
struct Node
{
	Node *left;
	Node *right;
	T data;
};

template <typename T>
class BinaryTree;

template <typename T>
std::ostream& operator<<(std::ostream&, const BinaryTree<T>&);

template <typename T>
class BinaryTree
{
private:
	Node<T>*root;
	int count;
public:
	BinaryTree();
	~BinaryTree();
	Node<T>* root_();
	unsigned int getCount()const;
	void insert_node(const T&x);
	Node<T> *find_node(const T&, Node<T>*)const;
	void remove_element(const T& temp);
	void deleteNode(Node<T>* temp);
	Node<T>* _deleteRoot(Node<T>* temp);
	void writing(const std::string& filename)const;
	friend std::ostream& operator<<<>(std::ostream&, const BinaryTree<T>&);
};

template <typename T>
BinaryTree<T>::BinaryTree()
{
	root = nullptr;
	count = 0;
}

template<typename T>
Node<T>* BinaryTree<T>::root_()
{
	return root;
}

template <typename T>
BinaryTree<T>::~BinaryTree()
{
	deleteNode(root);
}

template <typename T>
unsigned int BinaryTree<T>::getCount()const
{
	return count;
}

template<typename T>
void BinaryTree<T>::insert_node(const T&x)
{
	if (find_node(x, root_())) return;
	Node<T>* MyTree = new Node<T>;
	MyTree->data = x;
	MyTree->left = MyTree->right = 0;
	Node<T>* buff = root;
	Node<T>* temp = root;
	while (temp)
	{
		buff = temp;
		if (x < temp->data)
			temp = temp->left;
		else
			temp = temp->right;
	}
	if (!buff)
		root = MyTree;
	else
	{
		if (x < buff->data)
			buff->left = MyTree;
		else
			buff->right = MyTree;
	}
	++count;
}

template<typename T>
Node<T>* BinaryTree<T>::find_node(const T& data, Node<T>* temp) const
{
	if (temp == 0 || data == temp->data)
		return temp;
	if (data > temp->data)
		return find_node(data, temp->right);
	else
		return find_node(data, temp->left);
}

template<typename T>
void BinaryTree<T>::writing(const std::string& filename)const
{
	ofstream file_1(filename);
	file_1 << count << "\t";
	output(file_1, root);
	file_1.close();
}

template<typename T>
void BinaryTree<T>::deleteNode(Node<T>* temp)
{
	if (!temp)
	{
		throw "error";
	}
	if (temp->left)
	{
		deleteNode(temp->left);
		temp->left = nullptr;
	}

	if (temp->right)
	{
		deleteNode(temp->right);
		temp->right = nullptr;
	}
	delete temp;
}

template <typename T>
std::ostream& output(std::ostream& ost, const Node<T>* node, unsigned int level)
{
	if (!node)
		return ost;
	output(ost, node->right, level + 1);
	for (unsigned int i = 0; i < level; i++)
		ost << "\t";
	ost << node->data << std::endl;
	output(ost, node->left, level + 1);
	return ost;
}

template <typename T>
Node<T>* BinaryTree<T>::_deleteRoot(Node<T>* temp)
{
	Node<T>* buff, *parent;
	if (temp)
	{
		buff = temp->right;
		if (!buff)
		{
			buff = temp->left;
		}
		else
		{
			if (buff->left)
			{
				parent = temp;
				while (buff->left)
				{
					parent = buff;
					buff = buff->left;
				}
				parent->left = buff->right;
				buff->right = temp->right;
			}
			buff->left = temp->left;
		}
		delete temp;
		return buff;
	}
	return nullptr;
}

template <typename T>
void BinaryTree<T>::remove_element(const T& temp)
{
	Node<T>* buff = root, *parent;
	if (root)
	{
		if (root->data == temp)
		{
			root = _deleteRoot(root);
		}
		else
		{
			parent = root;
			if (temp < parent->data) buff = parent->left;
			else buff = parent->right;
			while (buff)
			{
				if (buff->data == temp)
					{
					if (temp < parent->data) parent->left = _deleteRoot(parent->left);
					else parent->right = _deleteRoot(parent->right);
					return;
				}
				parent = buff;
				if (temp < parent->data) buff = parent->left;
				else buff = parent->right;
			}
		}
	}
	--count;
}

template <typename T>
std::ostream& operator<<(std::ostream& ost, const BinaryTree<T>& temp)
{
	output(ost, temp.root, 0);
	return ost;
}

<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you 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 .
 */

#include <sal/types.h>
#include <assert.h>

#include <premac.h>
#ifndef IOS
#include <CoreServices/CoreServices.h>
#endif
#include <CoreFoundation/CoreFoundation.h>
#include <postmac.h>

namespace /* private */
{
    template <typename T>
    class CFGuard
    {
    public:
        explicit CFGuard(T& rT) : rT_(rT) {}
        ~CFGuard() { if (rT_) CFRelease(rT_); }
    private:
        T& rT_;
    };

    typedef CFGuard<CFArrayRef> CFArrayGuard;
    typedef CFGuard<CFStringRef> CFStringGuard;
    typedef CFGuard<CFPropertyListRef> CFPropertyListGuard;

    /** Get the current process locale from system
    */
    CFStringRef getProcessLocale()
    {
        CFPropertyListRef pref = CFPreferencesCopyAppValue(CFSTR("AppleLocale"), kCFPreferencesCurrentApplication);
        CFPropertyListGuard proplGuard(pref);

        if (pref == NULL) // return fallback value 'en_US'
             return CFStringCreateWithCString(kCFAllocatorDefault, "en_US", kCFStringEncodingASCII);

        CFStringRef sref = (CFGetTypeID(pref) == CFArrayGetTypeID()) ? (CFStringRef)CFArrayGetValueAtIndex((CFArrayRef)pref, 0) : (CFStringRef)pref;

        // NOTE: this API is only available with Mac OS X >=10.3. We need to use it because
        // Apple used non-ISO values on systems <10.2 like "German" for instance but didn't
        // upgrade those values during upgrade to newer Mac OS X versions. See also #i54337#
        return CFLocaleCreateCanonicalLocaleIdentifierFromString(kCFAllocatorDefault, sref);
    }
} // namespace private

/** Grab current locale from system.
*/
extern "C" {
int macosx_getLocale(char *locale, sal_uInt32 bufferLen)
{
    CFStringRef sref = getProcessLocale();
    CFStringGuard sGuard(sref);

    assert(sref != NULL && "osxlocale.cxx: getProcessLocale must return a non-NULL value");

    // split the string into substrings; the first two (if there are two) substrings
    // are language and country
    CFArrayRef subs = CFStringCreateArrayBySeparatingStrings(NULL, sref, CFSTR("_"));
    CFArrayGuard arrGuard(subs);

    CFStringRef lang = (CFStringRef)CFArrayGetValueAtIndex(subs, 0);
    CFStringGetCString(lang, locale, bufferLen, kCFStringEncodingASCII);

    // country also available? Assumption: if the array contains more than one
    // value the second value is always the country!
    if (CFArrayGetCount(subs) > 1)
    {
        strlcat(locale, "_", bufferLen - strlen(locale));

        CFStringRef country = (CFStringRef)CFArrayGetValueAtIndex(subs, 1);
        CFStringGetCString(country, locale + strlen(locale), bufferLen - strlen(locale), kCFStringEncodingASCII);
    }
    // Append 'UTF-8' to the locale because the Mac OS X file
    // system interface is UTF-8 based and sal tries to determine
    // the file system locale from the locale information
    strlcat(locale, ".UTF-8", bufferLen - strlen(locale));

    return noErr;
}
}

/*
 * macxp_OSXConvertCFEncodingToIANACharSetName
 *
 * Convert a CoreFoundation text encoding to an IANA charset name.
 */
extern "C" int macxp_OSXConvertCFEncodingToIANACharSetName( char *buffer, unsigned int bufferLen, CFStringEncoding cfEncoding )
{
    CFStringRef sCFEncodingName;

    sCFEncodingName = CFStringConvertEncodingToIANACharSetName( cfEncoding );
    CFStringGetCString( sCFEncodingName, buffer, bufferLen, cfEncoding );

    if ( sCFEncodingName )
        CFRelease( sCFEncodingName );

    return( noErr );
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>Bin obsolete comment<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you 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 .
 */

#include <sal/types.h>
#include <assert.h>

#include <premac.h>
#ifndef IOS
#include <CoreServices/CoreServices.h>
#endif
#include <CoreFoundation/CoreFoundation.h>
#include <postmac.h>

namespace /* private */
{
    template <typename T>
    class CFGuard
    {
    public:
        explicit CFGuard(T& rT) : rT_(rT) {}
        ~CFGuard() { if (rT_) CFRelease(rT_); }
    private:
        T& rT_;
    };

    typedef CFGuard<CFArrayRef> CFArrayGuard;
    typedef CFGuard<CFStringRef> CFStringGuard;
    typedef CFGuard<CFPropertyListRef> CFPropertyListGuard;

    /** Get the current process locale from system
    */
    CFStringRef getProcessLocale()
    {
        CFPropertyListRef pref = CFPreferencesCopyAppValue(CFSTR("AppleLocale"), kCFPreferencesCurrentApplication);
        CFPropertyListGuard proplGuard(pref);

        if (pref == NULL) // return fallback value 'en_US'
             return CFStringCreateWithCString(kCFAllocatorDefault, "en_US", kCFStringEncodingASCII);

        CFStringRef sref = (CFGetTypeID(pref) == CFArrayGetTypeID()) ? (CFStringRef)CFArrayGetValueAtIndex((CFArrayRef)pref, 0) : (CFStringRef)pref;

        return CFLocaleCreateCanonicalLocaleIdentifierFromString(kCFAllocatorDefault, sref);
    }
} // namespace private

/** Grab current locale from system.
*/
extern "C" {
int macosx_getLocale(char *locale, sal_uInt32 bufferLen)
{
    CFStringRef sref = getProcessLocale();
    CFStringGuard sGuard(sref);

    assert(sref != NULL && "osxlocale.cxx: getProcessLocale must return a non-NULL value");

    // split the string into substrings; the first two (if there are two) substrings
    // are language and country
    CFArrayRef subs = CFStringCreateArrayBySeparatingStrings(NULL, sref, CFSTR("_"));
    CFArrayGuard arrGuard(subs);

    CFStringRef lang = (CFStringRef)CFArrayGetValueAtIndex(subs, 0);
    CFStringGetCString(lang, locale, bufferLen, kCFStringEncodingASCII);

    // country also available? Assumption: if the array contains more than one
    // value the second value is always the country!
    if (CFArrayGetCount(subs) > 1)
    {
        strlcat(locale, "_", bufferLen - strlen(locale));

        CFStringRef country = (CFStringRef)CFArrayGetValueAtIndex(subs, 1);
        CFStringGetCString(country, locale + strlen(locale), bufferLen - strlen(locale), kCFStringEncodingASCII);
    }
    // Append 'UTF-8' to the locale because the Mac OS X file
    // system interface is UTF-8 based and sal tries to determine
    // the file system locale from the locale information
    strlcat(locale, ".UTF-8", bufferLen - strlen(locale));

    return noErr;
}
}

/*
 * macxp_OSXConvertCFEncodingToIANACharSetName
 *
 * Convert a CoreFoundation text encoding to an IANA charset name.
 */
extern "C" int macxp_OSXConvertCFEncodingToIANACharSetName( char *buffer, unsigned int bufferLen, CFStringEncoding cfEncoding )
{
    CFStringRef sCFEncodingName;

    sCFEncodingName = CFStringConvertEncodingToIANACharSetName( cfEncoding );
    CFStringGetCString( sCFEncodingName, buffer, bufferLen, cfEncoding );

    if ( sCFEncodingName )
        CFRelease( sCFEncodingName );

    return( noErr );
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>/*
 * Copyright 2013 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkGpuBlurUtils.h"

#include "SkRect.h"

#if SK_SUPPORT_GPU
#include "effects/GrConvolutionEffect.h"
#include "effects/GrTextureDomainEffect.h"
#include "GrContext.h"
#endif

namespace SkGpuBlurUtils {

#if SK_SUPPORT_GPU

#define MAX_BLUR_SIGMA 4.0f

static void scale_rect(SkRect* rect, float xScale, float yScale) {
    rect->fLeft   = SkScalarMul(rect->fLeft,   SkFloatToScalar(xScale));
    rect->fTop    = SkScalarMul(rect->fTop,    SkFloatToScalar(yScale));
    rect->fRight  = SkScalarMul(rect->fRight,  SkFloatToScalar(xScale));
    rect->fBottom = SkScalarMul(rect->fBottom, SkFloatToScalar(yScale));
}

static float adjust_sigma(float sigma, int *scaleFactor, int *radius) {
    *scaleFactor = 1;
    while (sigma > MAX_BLUR_SIGMA) {
        *scaleFactor *= 2;
        sigma *= 0.5f;
    }
    *radius = static_cast<int>(ceilf(sigma * 3.0f));
    GrAssert(*radius <= GrConvolutionEffect::kMaxKernelRadius);
    return sigma;
}

static void convolve_gaussian(GrContext* context,
                              GrTexture* texture,
                              const SkRect& srcRect,
                              const SkRect& dstRect,
                              bool cropToSrcRect,
                              float sigma,
                              int radius,
                              Gr1DKernelEffect::Direction direction) {
    GrPaint paint;
    paint.reset();
    float bounds[2] = { 0.0f, 1.0f };
    if (cropToSrcRect) {
        if (direction == Gr1DKernelEffect::kX_Direction) {
            bounds[0] = SkScalarToFloat(srcRect.left()) / texture->width();
            bounds[1] = SkScalarToFloat(srcRect.right()) / texture->width();
        } else {
            bounds[0] = SkScalarToFloat(srcRect.top()) / texture->height();
            bounds[1] = SkScalarToFloat(srcRect.bottom()) / texture->height();
        }
    }

    SkAutoTUnref<GrEffectRef> conv(GrConvolutionEffect::CreateGaussian(texture,
                                                                       direction,
                                                                       radius,
                                                                       sigma,
                                                                       cropToSrcRect,
                                                                       bounds));
    paint.addColorEffect(conv);
    context->drawRectToRect(paint, dstRect, srcRect);
}

GrTexture* GaussianBlur(GrContext* context,
                        GrTexture* srcTexture,
                        bool canClobberSrc,
                        const SkRect& rect,
                        bool cropToRect,
                        float sigmaX,
                        float sigmaY) {
    GrAssert(NULL != context);

    GrContext::AutoRenderTarget art(context);

    GrContext::AutoMatrix am;
    am.setIdentity(context);

    SkIRect clearRect;
    int scaleFactorX, radiusX;
    int scaleFactorY, radiusY;
    sigmaX = adjust_sigma(sigmaX, &scaleFactorX, &radiusX);
    sigmaY = adjust_sigma(sigmaY, &scaleFactorY, &radiusY);

    SkRect srcRect(rect);
    scale_rect(&srcRect, 1.0f / scaleFactorX, 1.0f / scaleFactorY);
    srcRect.roundOut();
    scale_rect(&srcRect, static_cast<float>(scaleFactorX),
                         static_cast<float>(scaleFactorY));

    GrContext::AutoClip acs(context, SkRect::MakeWH(srcRect.width(), srcRect.height()));

    GrAssert(kBGRA_8888_GrPixelConfig == srcTexture->config() ||
             kRGBA_8888_GrPixelConfig == srcTexture->config() ||
             kAlpha_8_GrPixelConfig == srcTexture->config());

    GrTextureDesc desc;
    desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
    desc.fWidth = SkScalarFloorToInt(srcRect.width());
    desc.fHeight = SkScalarFloorToInt(srcRect.height());
    desc.fConfig = srcTexture->config();

    GrAutoScratchTexture temp1, temp2;
    GrTexture* dstTexture = temp1.set(context, desc);
    GrTexture* tempTexture = canClobberSrc ? srcTexture : temp2.set(context, desc);
    if (NULL == dstTexture || NULL == tempTexture) {
        return NULL;
    }

    for (int i = 1; i < scaleFactorX || i < scaleFactorY; i *= 2) {
        GrPaint paint;
        SkMatrix matrix;
        matrix.setIDiv(srcTexture->width(), srcTexture->height());
        context->setRenderTarget(dstTexture->asRenderTarget());
        SkRect dstRect(srcRect);
        if (cropToRect && i == 1) {
            dstRect.offset(-dstRect.fLeft, -dstRect.fTop);
            SkRect domain;
            matrix.mapRect(&domain, rect);
            domain.inset(i < scaleFactorX ? SK_ScalarHalf / srcTexture->width() : 0.0f,
                         i < scaleFactorY ? SK_ScalarHalf / srcTexture->height() : 0.0f);
            SkAutoTUnref<GrEffectRef> effect(GrTextureDomainEffect::Create(
                srcTexture,
                matrix,
                domain,
                GrTextureDomainEffect::kDecal_WrapMode,
                GrTextureParams::kBilerp_FilterMode));
            paint.addColorEffect(effect);
        } else {
            GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::kBilerp_FilterMode);
            paint.addColorTextureEffect(srcTexture, matrix, params);
        }
        scale_rect(&dstRect, i < scaleFactorX ? 0.5f : 1.0f,
                             i < scaleFactorY ? 0.5f : 1.0f);
        context->drawRectToRect(paint, dstRect, srcRect);
        srcRect = dstRect;
        srcTexture = dstTexture;
        SkTSwap(dstTexture, tempTexture);
    }

    SkIRect srcIRect;
    srcRect.roundOut(&srcIRect);

    if (sigmaX > 0.0f) {
        if (scaleFactorX > 1) {
            // Clear out a radius to the right of the srcRect to prevent the
            // X convolution from reading garbage.
            clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop,
                                          radiusX, srcIRect.height());
            context->clear(&clearRect, 0x0);
        }
        context->setRenderTarget(dstTexture->asRenderTarget());
        SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height());
        convolve_gaussian(context, srcTexture, srcRect, dstRect, cropToRect,
                          sigmaX, radiusX, Gr1DKernelEffect::kX_Direction);
        srcTexture = dstTexture;
        srcRect = dstRect;
        SkTSwap(dstTexture, tempTexture);
    }

    if (sigmaY > 0.0f) {
        if (scaleFactorY > 1 || sigmaX > 0.0f) {
            // Clear out a radius below the srcRect to prevent the Y
            // convolution from reading garbage.
            clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom,
                                          srcIRect.width(), radiusY);
            context->clear(&clearRect, 0x0);
        }

        context->setRenderTarget(dstTexture->asRenderTarget());
        SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height());
        convolve_gaussian(context, srcTexture, srcRect, dstRect, cropToRect,
                          sigmaY, radiusY, Gr1DKernelEffect::kY_Direction);
        srcTexture = dstTexture;
        srcRect = dstRect;
        SkTSwap(dstTexture, tempTexture);
    }

    if (scaleFactorX > 1 || scaleFactorY > 1) {
        // Clear one pixel to the right and below, to accommodate bilinear
        // upsampling.
        clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom,
                                      srcIRect.width() + 1, 1);
        context->clear(&clearRect, 0x0);
        clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop,
                                      1, srcIRect.height());
        context->clear(&clearRect, 0x0);
        SkMatrix matrix;
        matrix.setIDiv(srcTexture->width(), srcTexture->height());
        context->setRenderTarget(dstTexture->asRenderTarget());

        GrPaint paint;
        // FIXME:  this should be mitchell, not bilinear.
        GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::kBilerp_FilterMode);
        paint.addColorTextureEffect(srcTexture, matrix, params);

        SkRect dstRect(srcRect);
        scale_rect(&dstRect, (float) scaleFactorX, (float) scaleFactorY);
        context->drawRectToRect(paint, dstRect, srcRect);
        srcRect = dstRect;
        srcTexture = dstTexture;
        SkTSwap(dstTexture, tempTexture);
    }
    if (srcTexture == temp1.texture()) {
        return temp1.detach();
    } else if (srcTexture == temp2.texture()) {
        return temp2.detach();
    } else {
        srcTexture->ref();
        return srcTexture;
    }
}
#endif

}
<commit_msg>Optimize the blur convolution by only applying domain clamping where necessary.  Split the blur convolution into left and right margins which have clamping applied and a center portion which doesn't. Also reorder the convolve_gaussian() parameters to match GrConvolutionEffect params. Correctness is covered by existing tests; performance is covered by BlurImageFilter bench.<commit_after>/*
 * Copyright 2013 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkGpuBlurUtils.h"

#include "SkRect.h"

#if SK_SUPPORT_GPU
#include "effects/GrConvolutionEffect.h"
#include "effects/GrTextureDomainEffect.h"
#include "GrContext.h"
#endif

namespace SkGpuBlurUtils {

#if SK_SUPPORT_GPU

#define MAX_BLUR_SIGMA 4.0f

static void scale_rect(SkRect* rect, float xScale, float yScale) {
    rect->fLeft   = SkScalarMul(rect->fLeft,   SkFloatToScalar(xScale));
    rect->fTop    = SkScalarMul(rect->fTop,    SkFloatToScalar(yScale));
    rect->fRight  = SkScalarMul(rect->fRight,  SkFloatToScalar(xScale));
    rect->fBottom = SkScalarMul(rect->fBottom, SkFloatToScalar(yScale));
}

static float adjust_sigma(float sigma, int *scaleFactor, int *radius) {
    *scaleFactor = 1;
    while (sigma > MAX_BLUR_SIGMA) {
        *scaleFactor *= 2;
        sigma *= 0.5f;
    }
    *radius = static_cast<int>(ceilf(sigma * 3.0f));
    GrAssert(*radius <= GrConvolutionEffect::kMaxKernelRadius);
    return sigma;
}

static void convolve_gaussian_pass(GrContext* context,
                                   const SkRect& srcRect,
                                   const SkRect& dstRect,
                                   GrTexture* texture,
                                   Gr1DKernelEffect::Direction direction,
                                   int radius,
                                   float sigma,
                                   bool useBounds,
                                   float bounds[2]) {
    GrPaint paint;
    paint.reset();
    SkAutoTUnref<GrEffectRef> conv(GrConvolutionEffect::CreateGaussian(
        texture, direction, radius, sigma, useBounds, bounds));
    paint.reset();
    paint.addColorEffect(conv);
    context->drawRectToRect(paint, dstRect, srcRect);
}

static void convolve_gaussian(GrContext* context,
                              const SkRect& srcRect,
                              const SkRect& dstRect,
                              GrTexture* texture,
                              Gr1DKernelEffect::Direction direction,
                              int radius,
                              float sigma,
                              bool cropToSrcRect) {
    float bounds[2] = { 0.0f, 1.0f };
    if (!cropToSrcRect) {
        convolve_gaussian_pass(context, srcRect, dstRect, texture,
                          direction, radius, sigma, false, bounds);
        return;
    }
    SkRect lowerSrcRect = srcRect, lowerDstRect = dstRect;
    SkRect middleSrcRect = srcRect, middleDstRect = dstRect;
    SkRect upperSrcRect = srcRect, upperDstRect = dstRect;
    SkScalar size;
    SkScalar rad = SkIntToScalar(radius);
    if (direction == Gr1DKernelEffect::kX_Direction) {
        bounds[0] = SkScalarToFloat(srcRect.left()) / texture->width();
        bounds[1] = SkScalarToFloat(srcRect.right()) / texture->width();
        size = srcRect.width();
        lowerSrcRect.fRight = srcRect.left() + rad;
        lowerDstRect.fRight = dstRect.left() + rad;
        upperSrcRect.fLeft = srcRect.right() - rad;
        upperDstRect.fLeft = dstRect.right() - rad;
        middleSrcRect.inset(rad, 0);
        middleDstRect.inset(rad, 0);
    } else {
        bounds[0] = SkScalarToFloat(srcRect.top()) / texture->height();
        bounds[1] = SkScalarToFloat(srcRect.bottom()) / texture->height();
        size = srcRect.height();
        lowerSrcRect.fBottom = srcRect.top() + rad;
        lowerDstRect.fBottom = dstRect.top() + rad;
        upperSrcRect.fTop = srcRect.bottom() - rad;
        upperDstRect.fTop = dstRect.bottom() - rad;
        middleSrcRect.inset(0, rad);
        middleDstRect.inset(0, rad);
    }
    if (radius >= size * SK_ScalarHalf) {
        // Blur radius covers srcRect; use bounds over entire draw
        convolve_gaussian_pass(context, srcRect, dstRect, texture,
                          direction, radius, sigma, true, bounds);
    } else {
        // Draw upper and lower margins with bounds; middle without.
        convolve_gaussian_pass(context, lowerSrcRect, lowerDstRect, texture,
                          direction, radius, sigma, true, bounds);
        convolve_gaussian_pass(context, upperSrcRect, upperDstRect, texture,
                          direction, radius, sigma, true, bounds);
        convolve_gaussian_pass(context, middleSrcRect, middleDstRect, texture,
                          direction, radius, sigma, false, bounds);
    }
}

GrTexture* GaussianBlur(GrContext* context,
                        GrTexture* srcTexture,
                        bool canClobberSrc,
                        const SkRect& rect,
                        bool cropToRect,
                        float sigmaX,
                        float sigmaY) {
    GrAssert(NULL != context);

    GrContext::AutoRenderTarget art(context);

    GrContext::AutoMatrix am;
    am.setIdentity(context);

    SkIRect clearRect;
    int scaleFactorX, radiusX;
    int scaleFactorY, radiusY;
    sigmaX = adjust_sigma(sigmaX, &scaleFactorX, &radiusX);
    sigmaY = adjust_sigma(sigmaY, &scaleFactorY, &radiusY);

    SkRect srcRect(rect);
    scale_rect(&srcRect, 1.0f / scaleFactorX, 1.0f / scaleFactorY);
    srcRect.roundOut();
    scale_rect(&srcRect, static_cast<float>(scaleFactorX),
                         static_cast<float>(scaleFactorY));

    GrContext::AutoClip acs(context, SkRect::MakeWH(srcRect.width(), srcRect.height()));

    GrAssert(kBGRA_8888_GrPixelConfig == srcTexture->config() ||
             kRGBA_8888_GrPixelConfig == srcTexture->config() ||
             kAlpha_8_GrPixelConfig == srcTexture->config());

    GrTextureDesc desc;
    desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
    desc.fWidth = SkScalarFloorToInt(srcRect.width());
    desc.fHeight = SkScalarFloorToInt(srcRect.height());
    desc.fConfig = srcTexture->config();

    GrAutoScratchTexture temp1, temp2;
    GrTexture* dstTexture = temp1.set(context, desc);
    GrTexture* tempTexture = canClobberSrc ? srcTexture : temp2.set(context, desc);
    if (NULL == dstTexture || NULL == tempTexture) {
        return NULL;
    }

    for (int i = 1; i < scaleFactorX || i < scaleFactorY; i *= 2) {
        GrPaint paint;
        SkMatrix matrix;
        matrix.setIDiv(srcTexture->width(), srcTexture->height());
        context->setRenderTarget(dstTexture->asRenderTarget());
        SkRect dstRect(srcRect);
        if (cropToRect && i == 1) {
            dstRect.offset(-dstRect.fLeft, -dstRect.fTop);
            SkRect domain;
            matrix.mapRect(&domain, rect);
            domain.inset(i < scaleFactorX ? SK_ScalarHalf / srcTexture->width() : 0.0f,
                         i < scaleFactorY ? SK_ScalarHalf / srcTexture->height() : 0.0f);
            SkAutoTUnref<GrEffectRef> effect(GrTextureDomainEffect::Create(
                srcTexture,
                matrix,
                domain,
                GrTextureDomainEffect::kDecal_WrapMode,
                GrTextureParams::kBilerp_FilterMode));
            paint.addColorEffect(effect);
        } else {
            GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::kBilerp_FilterMode);
            paint.addColorTextureEffect(srcTexture, matrix, params);
        }
        scale_rect(&dstRect, i < scaleFactorX ? 0.5f : 1.0f,
                             i < scaleFactorY ? 0.5f : 1.0f);
        context->drawRectToRect(paint, dstRect, srcRect);
        srcRect = dstRect;
        srcTexture = dstTexture;
        SkTSwap(dstTexture, tempTexture);
    }

    SkIRect srcIRect;
    srcRect.roundOut(&srcIRect);

    if (sigmaX > 0.0f) {
        if (scaleFactorX > 1) {
            // Clear out a radius to the right of the srcRect to prevent the
            // X convolution from reading garbage.
            clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop,
                                          radiusX, srcIRect.height());
            context->clear(&clearRect, 0x0);
        }
        context->setRenderTarget(dstTexture->asRenderTarget());
        SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height());
        convolve_gaussian(context, srcRect, dstRect, srcTexture,
                          Gr1DKernelEffect::kX_Direction, radiusX, sigmaX, cropToRect);
        srcTexture = dstTexture;
        srcRect = dstRect;
        SkTSwap(dstTexture, tempTexture);
    }

    if (sigmaY > 0.0f) {
        if (scaleFactorY > 1 || sigmaX > 0.0f) {
            // Clear out a radius below the srcRect to prevent the Y
            // convolution from reading garbage.
            clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom,
                                          srcIRect.width(), radiusY);
            context->clear(&clearRect, 0x0);
        }

        context->setRenderTarget(dstTexture->asRenderTarget());
        SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height());
        convolve_gaussian(context, srcRect, dstRect, srcTexture,
                          Gr1DKernelEffect::kY_Direction, radiusY, sigmaY, cropToRect);
        srcTexture = dstTexture;
        srcRect = dstRect;
        SkTSwap(dstTexture, tempTexture);
    }

    if (scaleFactorX > 1 || scaleFactorY > 1) {
        // Clear one pixel to the right and below, to accommodate bilinear
        // upsampling.
        clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom,
                                      srcIRect.width() + 1, 1);
        context->clear(&clearRect, 0x0);
        clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop,
                                      1, srcIRect.height());
        context->clear(&clearRect, 0x0);
        SkMatrix matrix;
        matrix.setIDiv(srcTexture->width(), srcTexture->height());
        context->setRenderTarget(dstTexture->asRenderTarget());

        GrPaint paint;
        // FIXME:  this should be mitchell, not bilinear.
        GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::kBilerp_FilterMode);
        paint.addColorTextureEffect(srcTexture, matrix, params);

        SkRect dstRect(srcRect);
        scale_rect(&dstRect, (float) scaleFactorX, (float) scaleFactorY);
        context->drawRectToRect(paint, dstRect, srcRect);
        srcRect = dstRect;
        srcTexture = dstTexture;
        SkTSwap(dstTexture, tempTexture);
    }
    if (srcTexture == temp1.texture()) {
        return temp1.detach();
    } else if (srcTexture == temp2.texture()) {
        return temp2.detach();
    } else {
        srcTexture->ref();
        return srcTexture;
    }
}
#endif

}
<|endoftext|>


<commit_before>/*
Copyright (c) 2017 InversePalindrome
Memento Mori - SharedData.cpp
InversePalindrome.com
*/

#include "SharedData.hpp"

SharedData::SharedData(sf::RenderWindow& window, sfg::SFGUI& gui, sfg::Desktop& hud, TextureHolder& textures,
	ImageHolder& images, SoundHolder& sounds, FontHolder& fonts, SoundManager& soundManager, KeyBindings& keyBindings) :
	window(window),
	gui(gui),
	hud(hud),
	textures(textures),
	images(images),
	sounds(sounds),
	fonts(fonts),
	soundManager(soundManager),
	keyBindings(keyBindings)
{
}<commit_msg>Delete SharedData.cpp<commit_after><|endoftext|>