<commit_before>// Copyright (c) 2010 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.

#include "cefclient.h"
#include <stdio.h>
#include <cstdlib>
#include <sstream>
#include <string>
#include <errno.h>
#include "include/cef_app.h"
#include "include/cef_browser.h"
#include "include/cef_command_line.h"
#include "include/cef_frame.h"
#include "include/cef_web_plugin.h"
#include "include/base/cef_logging.h"
#include "client_handler.h"
#include "appshell/common/client_switches.h"
#include "appshell/appshell_helpers.h"
#include "config.h"

CefRefPtr<ClientHandler> g_handler;
int g_remote_debugging_port = 0;

#ifdef OS_WIN
bool g_force_enable_acc = false;
#endif

CefRefPtr<CefBrowser> AppGetBrowser() {
  if (!g_handler.get())
    return NULL;
  return g_handler->GetBrowser();
}

CefWindowHandle AppGetMainHwnd() {
  if (!g_handler.get())
    return NULL;
  return g_handler->GetMainHwnd();
}

// CefCommandLine::HasSwitch is unable to report the presense of switches,
// in the command line properly. This is a generic function that could be
// used to check for any particular switch, passed as a command line argument.
bool HasSwitch(CefRefPtr<CefCommandLine> command_line , CefString& switch_name)
{
  if (command_line) {
    ExtensionString cmdLine = command_line->GetCommandLineString();
    size_t idx = cmdLine.find(switch_name);
    return idx > 0 && idx < cmdLine.length();
  } else {
    return false;
  }
}

// Returns the application settings based on command line arguments.
void AppGetSettings(CefSettings& settings, CefRefPtr<CefCommandLine> command_line) {
  DCHECK(command_line.get());
  if (!command_line.get())
    return;

#if defined(OS_WIN)
  settings.multi_threaded_message_loop =
      command_line->HasSwitch(client::switches::kMultiThreadedMessageLoop);
#endif

  CefString(&settings.cache_path) =
      command_line->GetSwitchValue(client::switches::kCachePath);
  CefString(&settings.log_file) =
      command_line->GetSwitchValue(client::switches::kLogFile);

  {
    std::string str = command_line->GetSwitchValue(client::switches::kLogSeverity);

    // Default to LOGSEVERITY_DISABLE
    settings.log_severity = LOGSEVERITY_DISABLE;

    if (!str.empty()) {
      if (str == client::switches::kLogSeverity_Verbose)
        settings.log_severity = LOGSEVERITY_VERBOSE;
      else if (str == client::switches::kLogSeverity_Info)
        settings.log_severity = LOGSEVERITY_INFO;
      else if (str == client::switches::kLogSeverity_Warning)
        settings.log_severity = LOGSEVERITY_WARNING;
      else if (str == client::switches::kLogSeverity_Error)
        settings.log_severity = LOGSEVERITY_ERROR;
      else if (str == client::switches::kLogSeverity_Disable)
        settings.log_severity = LOGSEVERITY_DISABLE;
    }
  }

  // Don't update the settings.locale with the locale that we detected from the OS.
  // Otherwise, CEF will use it to find the resources and when it fails in finding resources
  // for some locales that are not available in resources, it crashes.
  //CefString(&settings.locale) = appshell::GetCurrentLanguage( );

  CefString(&settings.javascript_flags) =
      command_line->GetSwitchValue(client::switches::kJavascriptFlags);

  // Enable dev tools
  CefString debugger_port = command_line->GetSwitchValue("remote-debugging-port");
  if (!debugger_port.empty()) {
    const long port = strtol(debugger_port.ToString().c_str(), NULL, 10);
    if (errno == ERANGE || port == 0) {
        LOG(ERROR) << "Could not enable Remote debugging.";
        LOG(ERROR) << "Error while parsing remote-debugging-port arg: "<< debugger_port.ToString();
        errno = 0;
    }
    else {
        static const long max_port_num = 65535;
        static const long max_reserved_port_num = 1024;
        if (port > max_reserved_port_num && port < max_port_num) {
          g_remote_debugging_port = static_cast<int>(port);
          settings.remote_debugging_port = g_remote_debugging_port;
        }
        else {
          LOG(ERROR) << "Could not enable Remote debugging on port: "<< port
                     << ". Port number must be greater than "<< max_reserved_port_num
                     << " and less than " << max_port_num << ".";
        }
    }
  }

  std::wstring versionStr = appshell::AppGetProductVersionString();

  if (!versionStr.empty()) {
    // Explicitly append the Chromium version to our own product version string
    // since assigning product version always replaces the Chromium version in
    // the User Agent string.
    versionStr.append(L" ");
    versionStr.append(appshell::AppGetChromiumVersionString());

    // Set product version, which gets added to the User Agent string
    CefString(&settings.product_version) = versionStr;
  }

#ifdef OS_WIN
  // We disable renderer accessibility by default as it is known to cause performance
  // issues. But if any one wants to enable it back, then we need to honor the flag.

  CefString force_acc_switch_name("--force-renderer-accessibility");
  CefString enable_acc_switch_name("--enable-renderer-accessibility");

  if (HasSwitch(command_line, force_acc_switch_name) || HasSwitch(command_line, enable_acc_switch_name))
    g_force_enable_acc = true;
#endif

}
<commit_msg>Improved console error messages (#669)<commit_after>// Copyright (c) 2010 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.

#include "cefclient.h"
#include <stdio.h>
#include <cstdlib>
#include <sstream>
#include <string>
#include <errno.h>
#include "include/cef_app.h"
#include "include/cef_browser.h"
#include "include/cef_command_line.h"
#include "include/cef_frame.h"
#include "include/cef_web_plugin.h"
#include "include/base/cef_logging.h"
#include "client_handler.h"
#include "appshell/common/client_switches.h"
#include "appshell/appshell_helpers.h"
#include "config.h"

CefRefPtr<ClientHandler> g_handler;
int g_remote_debugging_port = 0;

#ifdef OS_WIN
bool g_force_enable_acc = false;
#endif

CefRefPtr<CefBrowser> AppGetBrowser() {
  if (!g_handler.get())
    return NULL;
  return g_handler->GetBrowser();
}

CefWindowHandle AppGetMainHwnd() {
  if (!g_handler.get())
    return NULL;
  return g_handler->GetMainHwnd();
}

// CefCommandLine::HasSwitch is unable to report the presense of switches,
// in the command line properly. This is a generic function that could be
// used to check for any particular switch, passed as a command line argument.
bool HasSwitch(CefRefPtr<CefCommandLine> command_line , CefString& switch_name)
{
  if (command_line) {
    ExtensionString cmdLine = command_line->GetCommandLineString();
    size_t idx = cmdLine.find(switch_name);
    return idx > 0 && idx < cmdLine.length();
  } else {
    return false;
  }
}

// Returns the application settings based on command line arguments.
void AppGetSettings(CefSettings& settings, CefRefPtr<CefCommandLine> command_line) {
  DCHECK(command_line.get());
  if (!command_line.get())
    return;

#if defined(OS_WIN)
  settings.multi_threaded_message_loop =
      command_line->HasSwitch(client::switches::kMultiThreadedMessageLoop);
#endif

  CefString(&settings.cache_path) =
      command_line->GetSwitchValue(client::switches::kCachePath);
  CefString(&settings.log_file) =
      command_line->GetSwitchValue(client::switches::kLogFile);

  {
    std::string str = command_line->GetSwitchValue(client::switches::kLogSeverity);

    // Default to LOGSEVERITY_DISABLE
    settings.log_severity = LOGSEVERITY_DISABLE;

    if (!str.empty()) {
      if (str == client::switches::kLogSeverity_Verbose)
        settings.log_severity = LOGSEVERITY_VERBOSE;
      else if (str == client::switches::kLogSeverity_Info)
        settings.log_severity = LOGSEVERITY_INFO;
      else if (str == client::switches::kLogSeverity_Warning)
        settings.log_severity = LOGSEVERITY_WARNING;
      else if (str == client::switches::kLogSeverity_Error)
        settings.log_severity = LOGSEVERITY_ERROR;
      else if (str == client::switches::kLogSeverity_Disable)
        settings.log_severity = LOGSEVERITY_DISABLE;
    }
  }

  // Don't update the settings.locale with the locale that we detected from the OS.
  // Otherwise, CEF will use it to find the resources and when it fails in finding resources
  // for some locales that are not available in resources, it crashes.
  //CefString(&settings.locale) = appshell::GetCurrentLanguage( );

  CefString(&settings.javascript_flags) =
      command_line->GetSwitchValue(client::switches::kJavascriptFlags);

  // Enable dev tools
  CefString debugger_port = command_line->GetSwitchValue("remote-debugging-port");
  if (!debugger_port.empty()) {
    const long port = strtol(debugger_port.ToString().c_str(), NULL, 10);
    if (errno == ERANGE || port == 0) {
        LOG(ERROR) << "Could not enable remote debugging."
                   << " Error while parsing remote-debugging-port arg: "<< debugger_port.ToString();
        errno = 0;
    }
    else {
        static const long max_port_num = 65534;
        static const long max_reserved_port_num = 1025;
        if (port >= max_reserved_port_num && port <= max_port_num) {
          g_remote_debugging_port = static_cast<int>(port);
          settings.remote_debugging_port = g_remote_debugging_port;
        }
        else {
          LOG(ERROR) << "Cannot enable remote debugging on port "<< port
                     << ". Port numbers should be between "<< max_reserved_port_num
                     << " and " << max_port_num << ".";
        }
    }
  }

  std::wstring versionStr = appshell::AppGetProductVersionString();

  if (!versionStr.empty()) {
    // Explicitly append the Chromium version to our own product version string
    // since assigning product version always replaces the Chromium version in
    // the User Agent string.
    versionStr.append(L" ");
    versionStr.append(appshell::AppGetChromiumVersionString());

    // Set product version, which gets added to the User Agent string
    CefString(&settings.product_version) = versionStr;
  }

#ifdef OS_WIN
  // We disable renderer accessibility by default as it is known to cause performance
  // issues. But if any one wants to enable it back, then we need to honor the flag.

  CefString force_acc_switch_name("--force-renderer-accessibility");
  CefString enable_acc_switch_name("--enable-renderer-accessibility");

  if (HasSwitch(command_line, force_acc_switch_name) || HasSwitch(command_line, enable_acc_switch_name))
    g_force_enable_acc = true;
#endif

}
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
/// @brief Class for arangodb's graph features. Wrapper around the graph informations
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2014-2015 ArangoDB GmbH, Cologne, Germany
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
///
/// 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.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Michael Hackstein
/// @author Copyright 2014-2015, ArangoDB GmbH, Cologne, Germany
/// @author Copyright 2011-2013, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

#include "Basics/JsonHelper.h"
#include "Aql/Graphs.h"
using namespace triagens::basics;
using namespace triagens::aql;

char const* Graph::_attrEdgeDefs = "edgeDefinitions";
char const* Graph::_attrOrphans = "orphanCollections";

// -----------------------------------------------------------------------------
// --SECTION--                                                       Local utils
// -----------------------------------------------------------------------------

void Graph::insertVertexCollectionsFromJsonArray(triagens::basics::Json& arr) {
  for (size_t j = 0; j < arr.size(); ++j) {
    Json c = arr.at(j);
    TRI_ASSERT(c.isString());
    std::string name = JsonHelper::getStringValue(c.json(), "");
    addVertexCollection(name);
  }
}

// -----------------------------------------------------------------------------
// --SECTION--                                                       Graph Class
// -----------------------------------------------------------------------------

std::unordered_set<std::string> const& Graph::vertexCollections () const {
  return _vertexColls;
}

std::unordered_set<std::string> const& Graph::edgeCollections () const {
  return _edgeColls;
}

void Graph::addEdgeCollection (std::string name) {
  _edgeColls.insert(name);
}

void Graph::addVertexCollection (std::string name) {
  _vertexColls.insert(name);
}

triagens::basics::Json Graph::toJson (TRI_memory_zone_t* z,
                           bool verbose) const
{
  triagens::basics::Json json(z, triagens::basics::Json::Object);

  if (_vertexColls.size() > 0) {
    triagens::basics::Json vcn(z, triagens::basics::Json::Array);
    for (auto cn : _vertexColls) {
      vcn.add(triagens::basics::Json(cn));
    }
    json("vertexCollectionNames", vcn);
  }

  if (_edgeColls.size() > 0) {
    triagens::basics::Json ecn(z, triagens::basics::Json::Array);
    for (auto cn : _edgeColls) {
      ecn.add(triagens::basics::Json(cn));
    }
    json("edgeCollectionNames", ecn);
  }

  return json;
}

Graph::Graph(triagens::basics::Json j) :
  _vertexColls(),
  _edgeColls()
{
  auto jsonDef = j.get(_attrEdgeDefs);

  for (size_t i = 0; i < jsonDef.size(); ++i) {
    Json def = jsonDef.at(i);
    TRI_ASSERT(def.isObject());
    Json e = def.get("collection");
    TRI_ASSERT(e.isString());
    std::string eCol = JsonHelper::getStringValue(e.json(), "");
    addEdgeCollection(eCol);
    e = def.get("from");
    TRI_ASSERT(e.isArray());
    insertVertexCollectionsFromJsonArray(e);
    e = def.get("to");
    TRI_ASSERT(e.isArray());
    insertVertexCollectionsFromJsonArray(e);
  }
  auto orphans = j.get(_attrOrphans);
  insertVertexCollectionsFromJsonArray(orphans);
}

<commit_msg>Indention fix<commit_after>////////////////////////////////////////////////////////////////////////////////
/// @brief Class for arangodb's graph features. Wrapper around the graph informations
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2014-2015 ArangoDB GmbH, Cologne, Germany
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
///
/// 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.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Michael Hackstein
/// @author Copyright 2014-2015, ArangoDB GmbH, Cologne, Germany
/// @author Copyright 2011-2013, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

#include "Basics/JsonHelper.h"
#include "Aql/Graphs.h"
using namespace triagens::basics;
using namespace triagens::aql;

char const* Graph::_attrEdgeDefs = "edgeDefinitions";
char const* Graph::_attrOrphans = "orphanCollections";

// -----------------------------------------------------------------------------
// --SECTION--                                                       Local utils
// -----------------------------------------------------------------------------

void Graph::insertVertexCollectionsFromJsonArray(triagens::basics::Json& arr) {
  for (size_t j = 0; j < arr.size(); ++j) {
    Json c = arr.at(j);
    TRI_ASSERT(c.isString());
    std::string name = JsonHelper::getStringValue(c.json(), "");
    addVertexCollection(name);
  }
}

// -----------------------------------------------------------------------------
// --SECTION--                                                       Graph Class
// -----------------------------------------------------------------------------

std::unordered_set<std::string> const& Graph::vertexCollections () const {
  return _vertexColls;
}

std::unordered_set<std::string> const& Graph::edgeCollections () const {
  return _edgeColls;
}

void Graph::addEdgeCollection (std::string name) {
  _edgeColls.insert(name);
}

void Graph::addVertexCollection (std::string name) {
  _vertexColls.insert(name);
}

triagens::basics::Json Graph::toJson (TRI_memory_zone_t* z,
                                      bool verbose) const {
  triagens::basics::Json json(z, triagens::basics::Json::Object);

  if (_vertexColls.size() > 0) {
    triagens::basics::Json vcn(z, triagens::basics::Json::Array);
    for (auto cn : _vertexColls) {
      vcn.add(triagens::basics::Json(cn));
    }
    json("vertexCollectionNames", vcn);
  }

  if (_edgeColls.size() > 0) {
    triagens::basics::Json ecn(z, triagens::basics::Json::Array);
    for (auto cn : _edgeColls) {
      ecn.add(triagens::basics::Json(cn));
    }
    json("edgeCollectionNames", ecn);
  }

  return json;
}

Graph::Graph(triagens::basics::Json j) :
  _vertexColls(),
  _edgeColls()
{
  auto jsonDef = j.get(_attrEdgeDefs);

  for (size_t i = 0; i < jsonDef.size(); ++i) {
    Json def = jsonDef.at(i);
    TRI_ASSERT(def.isObject());
    Json e = def.get("collection");
    TRI_ASSERT(e.isString());
    std::string eCol = JsonHelper::getStringValue(e.json(), "");
    addEdgeCollection(eCol);
    e = def.get("from");
    TRI_ASSERT(e.isArray());
    insertVertexCollectionsFromJsonArray(e);
    e = def.get("to");
    TRI_ASSERT(e.isArray());
    insertVertexCollectionsFromJsonArray(e);
  }
  auto orphans = j.get(_attrOrphans);
  insertVertexCollectionsFromJsonArray(orphans);
}

<|endoftext|>


<commit_before>#include "common.h"
#include <istream>

#define __STDC_LIMIT_MACROS
#define __STDC_CONSTANT_MACROS
#include "llvm/Support/InstIterator.h"

#include "Kernel.h"
#include "Memory.h"
#include "Device.h"
#include "WorkGroup.h"

using namespace spirsim;
using namespace std;

Device::Device()
{
  m_globalMemory = new Memory();
}

Device::~Device()
{
  delete m_globalMemory;
}

Memory* Device::getGlobalMemory() const
{
  return m_globalMemory;
}

void Device::run(const Kernel& kernel,
                    const size_t ndrange[3], const size_t wgsize[3])
{
  // Create work-groups
  size_t numGroups[3] = {ndrange[0]/wgsize[0],
                         ndrange[1]/wgsize[1],
                         ndrange[2]/wgsize[2]};
  size_t totalNumGroups = numGroups[0]*numGroups[1]*numGroups[2];
  for (int k = 0; k < numGroups[2]; k++)
  {
    for (int j = 0; j < numGroups[1]; j++)
    {
      for (int i = 0; i < numGroups[0]; i++)
      {
        if (m_outputMask &
            (OUTPUT_INSTRUCTIONS | OUTPUT_PRIVATE_MEM | OUTPUT_LOCAL_MEM))
        {
          cout << endl << BIG_SEPARATOR << endl;
          cout << "Work-group ("
               << i << ","
               << j << ","
               << k
               << ")" << endl;
          cout << BIG_SEPARATOR << endl;
        }

        WorkGroup *workGroup = new WorkGroup(kernel, *m_globalMemory,
                                             i, j, k, wgsize);

        workGroup->run(kernel, m_outputMask & OUTPUT_INSTRUCTIONS);

        // Dump contents of memories
        if (m_outputMask & OUTPUT_PRIVATE_MEM)
        {
          workGroup->dumpPrivateMemory();
        }
        if (m_outputMask & OUTPUT_LOCAL_MEM)
        {
          workGroup->dumpLocalMemory();
        }

        delete workGroup;
      }
    }
  }

  // Output global memory dump if required
  if (m_outputMask & OUTPUT_GLOBAL_MEM)
  {
    cout << endl << BIG_SEPARATOR << endl << "Global Memory:";
    m_globalMemory->dump();
    cout << BIG_SEPARATOR << endl;
  }
}

void Device::setOutputMask(unsigned char mask)
{
  m_outputMask = mask;
}
<commit_msg>Initialize m_outputMask to 0 on Device creation.<commit_after>#include "common.h"
#include <istream>

#define __STDC_LIMIT_MACROS
#define __STDC_CONSTANT_MACROS
#include "llvm/Support/InstIterator.h"

#include "Kernel.h"
#include "Memory.h"
#include "Device.h"
#include "WorkGroup.h"

using namespace spirsim;
using namespace std;

Device::Device()
{
  m_globalMemory = new Memory();
  m_outputMask = 0;
}

Device::~Device()
{
  delete m_globalMemory;
}

Memory* Device::getGlobalMemory() const
{
  return m_globalMemory;
}

void Device::run(const Kernel& kernel,
                    const size_t ndrange[3], const size_t wgsize[3])
{
  // Create work-groups
  size_t numGroups[3] = {ndrange[0]/wgsize[0],
                         ndrange[1]/wgsize[1],
                         ndrange[2]/wgsize[2]};
  size_t totalNumGroups = numGroups[0]*numGroups[1]*numGroups[2];
  for (int k = 0; k < numGroups[2]; k++)
  {
    for (int j = 0; j < numGroups[1]; j++)
    {
      for (int i = 0; i < numGroups[0]; i++)
      {
        if (m_outputMask &
            (OUTPUT_INSTRUCTIONS | OUTPUT_PRIVATE_MEM | OUTPUT_LOCAL_MEM))
        {
          cout << endl << BIG_SEPARATOR << endl;
          cout << "Work-group ("
               << i << ","
               << j << ","
               << k
               << ")" << endl;
          cout << BIG_SEPARATOR << endl;
        }

        WorkGroup *workGroup = new WorkGroup(kernel, *m_globalMemory,
                                             i, j, k, wgsize);

        workGroup->run(kernel, m_outputMask & OUTPUT_INSTRUCTIONS);

        // Dump contents of memories
        if (m_outputMask & OUTPUT_PRIVATE_MEM)
        {
          workGroup->dumpPrivateMemory();
        }
        if (m_outputMask & OUTPUT_LOCAL_MEM)
        {
          workGroup->dumpLocalMemory();
        }

        delete workGroup;
      }
    }
  }

  // Output global memory dump if required
  if (m_outputMask & OUTPUT_GLOBAL_MEM)
  {
    cout << endl << BIG_SEPARATOR << endl << "Global Memory:";
    m_globalMemory->dump();
    cout << BIG_SEPARATOR << endl;
  }
}

void Device::setOutputMask(unsigned char mask)
{
  m_outputMask = mask;
}
<|endoftext|>


<commit_before>#include "myFunctions.h"
#include <iostream>
#include <fstream>
#include <string>
using namespace std;

void printTitle(ostream &os) {    //   DONE
	cout
		<< "\n\t This is a lab on completely filled arrays "
		<< "\n\t               By J. Guerra                ";
}

void load5(int a[], int n) {    //   DONE
	for (int i = 0; i < n; i++)
		a[i] = 5;
}

void printArr(const int a[], int n, int epl, ostream &os) {    //   DONE
	for (int i = 0; i < n; i++)
		os << a[i] << (i % epl == epl - 1 || i == n - 1 ? "\n" : "\t");
}

char getYorN() {
	char c;

	cin >> c;	cin.ignore(80, '\n');

	while (c != 'Y' && c != 'y' && c != 'N' && c != 'n') {
		cout << "Please type Y or N. Try again: ";
		cin >> c;		cin.ignore(80, '\n');
	}

	return (c == 'y' ? 'Y' : c == 'n' ? 'N' : c);	// returns only capitals
}

string getFileName() {
	string filename;

	getline(cin >> ws, filename);

	return filename;
}<commit_msg>get output file<commit_after>#include "myFunctions.h"
#include <iostream>
#include <fstream>
#include <string>
using namespace std;

void printTitle(ostream &os) {    //   DONE
	cout
		<< "\n\t This is a lab on completely filled arrays "
		<< "\n\t               By J. Guerra                ";
}

void load5(int a[], int n) {      //   DONE
	for (int i = 0; i < n; i++)
		a[i] = 5;
}

void loadEven(int a[], int n) {
	for (int i = 0; i < n; i++)
		a[i] = (i + 1) * 2;
}

void loadOdd(int a[], int n) {
	for (int i = 0; i < n; i++)
		a[i] = i * 2 + 1;
}

void loadSq(int a[], int n) {
	for (int i = 0; i < n; i++)
		a[i] = (i + 1) * (i + 1);
}

//  Pre Condition:  n is the size of the array
// Post Condition:  Loads the array with the first n consecutive prime numbers
void loadPrime(int a[], int n) {
	int currentNum = 2;
	for (int i = 0; i < n; i++) {
		while (!isPrime(currentNum))
			currentNum++;
		a[i] = currentNum;
		currentNum++;
	}
}

bool isPrime(int x){   //    DONE
	for (int i = 2; i * i <= x; i++)
		if (x % i == 0)
			return false;
	return true;
}

void printArr(const int a[], int n, int epl, ostream &os) {    //   DONE
	for (int i = 0; i < n; i++)
		os << a[i] << (i % epl == epl - 1 || i == n - 1 ? "\n" : "\t");
}

char getYorN() {
	char c;

	cin >> c;	cin.ignore(80, '\n');

	while (c != 'Y' && c != 'y' && c != 'N' && c != 'n') {
		cout << "Please type Y or N. Try again: ";
		cin >> c;		cin.ignore(80, '\n');
	}

	return (c == 'y' ? 'Y' : c == 'n' ? 'N' : c);	// returns only capitals
}

string connectFileStream() {
	string filename;
	ofstream ofs;

	getline(cin >> ws, filename);
	ofs.open(filename);

	while (ofs.fail()) {
		cout << "Unable to open file. Try again: ";
		getline(cin >> ws, filename);
		ofs.open(filename);
	}

	ofs.close();

	return filename;
}<|endoftext|>


<commit_before>#ifndef __STAN__IO__WRITER_HPP__
#define __STAN__IO__WRITER_HPP__

#include <cstddef>
#include <stdexcept>
#include <vector>

#include <boost/multi_array.hpp>
#include <boost/throw_exception.hpp>

#include <stan/math/matrix.hpp>
#include <stan/math/special_functions.hpp>

#include <stan/prob/transform.hpp>

namespace stan {

  namespace io {

    /**
     * A stream-based writer for integer, scalar, vector, matrix
     * and array data types, which transforms from constrained to
     * a sequence of constrained variables.
     *
     *
This class converts constrained values to unconstrained
     * values with mappings that invert those defined in
     * stan::io::reader to convert unconstrained values
     * to constrained values.
     *
     * @tparam T Basic scalar type.
     */
    template <typename T>
    class writer {
    private:
      std::vector<T> data_r_;
      std::vector<int> data_i_;
    public:

      typedef typename stan::math::EigenType<T>::matrix matrix_t;
      typedef typename stan::math::EigenType<T>::vector vector_t;
      typedef typename stan::math::EigenType<T>::row_vector row_vector_t;

      typedef Eigen::Array<T,Eigen::Dynamic,1> array_vec_t;

      /**
       * This is the tolerance for checking arithmetic bounds
       * in rank and in simplexes.  The current value is 1E-8.
       */
      const double CONSTRAINT_TOLERANCE;

      /**
       * Construct a writer that writes to the specified
       * scalar and integer vectors.
       *
       * @param data_r Scalar values.
       * @param data_i Integer values.
       */
      writer(std::vector<T>& data_r,
             std::vector<int>& data_i)
        : data_r_(data_r),
          data_i_(data_i),
          CONSTRAINT_TOLERANCE(1E-8) {
      }

      /**
       * Destroy this writer.
       */
      ~writer() { }

      /**
       * Return a reference to the underlying vector of real values
       * that have been written.
       *
       * @return Values that have been written.
       */
      std::vector<T>& data_r() {
        return &data_r_;
      }

      /**
       * Return a reference to the underlying vector of integer values
       * that have been written.
       *
       * @return Values that have been written.
       */
      std::vector<int>& data_i() {
        return &data_i_;
      }

      /**
       * Write the specified integer to the sequence of integer values.
       *
       * @param n Integer to write.
       */
      void integer(int n) {
        data_i_.push_back(n);
      }

      /**
       * Write the unconstrained value corresponding to the specified
       * scalar.  Here, the unconstrain operation is a no-op, which
       * matches reader::scalar_constrain().
       *
       * @param y The value.
       */
      void scalar_unconstrain(T& y) {
        data_r_.push_back(y);
      }

      /**
       * Write the unconstrained value corresponding to the specified
       * positive-constrained scalar.  The transformation applied is
       * log(y), which is the inverse of constraining
       * transform specified in reader::scalar_pos_constrain().
       *
       *
This method will fail if the argument is not non-negative.
       *
       * @param y The positive value.
       * @throw std::runtime_error if y is negative.
       */
      void scalar_pos_unconstrain(T& y) {
        if (y < 0.0)
          BOOST_THROW_EXCEPTION(std::runtime_error ("y is negative"));
        data_r_.push_back(log(y));
      }

      /**
       * Return the unconstrained version of the specified input,
       * which is constrained to be above the specified lower bound.
       * The unconstraining transform is log(y - lb), which
       * inverts the constraining
       * transform defined in reader::scalar_lb_constrain(double),
       *
       * @param lb Lower bound.
       * @param y Lower-bounded value.
       * @throw std::runtime_error if y is lower than the lower bound provided.
       */
      void scalar_lb_unconstrain(double lb, T& y) {
        if (y < lb)
          BOOST_THROW_EXCEPTION(std::runtime_error ("y is lower than the lower bound"));
        data_r_.push_back(log(y - lb));
      }

      /**
       * Write the unconstrained value corresponding to the specified
       * lower-bounded value.  The unconstraining transform is
       * log(ub - y), which reverses the constraining
       * transform defined in reader::scalar_ub_constrain(double).
       *
       * @param ub Upper bound.
       * @param y Constrained value.
       * @throw std::runtime_error if y is higher than the upper bound provided.
       */
      void scalar_ub_unconstrain(double ub, T& y) {
        if (y > ub)
          BOOST_THROW_EXCEPTION(std::runtime_error ("y is higher than the lower bound"));
        data_r_.push_back(log(ub - y));
      }

      /**
       * Write the unconstrained value corresponding to the specified
       * value with the specified bounds.  The unconstraining
       * transform is given by reader::logit((y-L)/(U-L)), which
       * inverts the constraining transform defined in
       * scalar_lub_constrain(double,double).
       *
       * @param lb Lower bound.
       * @param ub Upper bound.
       * @param y Bounded value.
       * @throw std::runtime_error if y is not between the lower and upper bounds
       */
      void scalar_lub_unconstrain(double lb, double ub, T& y) {
        if (y < lb || y > ub)
          BOOST_THROW_EXCEPTION(std::runtime_error ("y is not between the lower and upper bounds"));
        data_r_.push_back(stan::math::logit((y - lb) / (ub - lb)));
      }

      /**
       * Write the unconstrained value corresponding to the specified
       * correlation-constrained variable.
       *
       *
The unconstraining transform is atanh(y), which
       * reverses the transfrom in corr_constrain().
       *
       * @param y Correlation value.
       * @throw std::runtime_error if y is not between -1.0 and 1.0
       */
      void corr_unconstrain(T& y) {
        if (y > 1.0 || y < -1.0)
          BOOST_THROW_EXCEPTION(std::runtime_error ("y is not between -1.0 and 1.0"));
        data_r_.push_back(atanh(y));
      }

      /**
       * Write the unconstrained value corresponding to the
       * specified probability value.
       *
       *
The unconstraining transform is logit(y),
       * which inverts the constraining transform defined in
       * prob_constrain().
       *
       * @param y Probability value.
       * @throw std::runtime_error if y is not between 0.0 and 1.0
        */
      void prob_unconstrain(T& y) {
        if (y > 1.0 || y < 0.0)
          BOOST_THROW_EXCEPTION(std::runtime_error ("y is not between 0.0 and 1.0"));
        data_r_.push_back(stan::math::logit(y));
      }

      /**
       * Write the unconstrained vector that corresponds to the specified
       * positive ordered vector.
       *
       *
The unconstraining transform is defined for input vector y
       * to produce an output vector x of the same size, defined
       * by x[0] = log(y[0]) and by
       * x[k] = log(y[k] - y[k-1]) for k > 0.  This
       * unconstraining transform inverts the constraining transform specified
       * in pos_ordered_constrain(size_t).
       *
       * @param y Positive, ordered vector.
       * @return Unconstrained vector corresponding to the specified vector.
       * @throw std::runtime_error if vector is not positive ordered
       */
      void pos_ordered_unconstrain(vector_t& y) {
        if (y.size() == 0) return;
        stan::math::check_pos_ordered("stan::io::pos_ordered_unconstrain(%1%)", y, "y");
        data_r_.push_back(log(y[0]));
        for (typename vector_t::size_type i = 1; i < y.size(); ++i) {
          data_r_.push_back(log(y[i] - y[i-1]));
        }
      }

      /**
       * Write the specified unconstrained vector.
       *
       * @param y Vector to write.
       */
      void vector_unconstrain(const vector_t& y) {
        for (size_t i = 0; i < y.size(); ++i)
          data_r_.push_back(y[i]);
      }

      /**
       * Write the specified unconstrained vector.
       *
       * @param y Vector to write.
       */
      void row_vector_unconstrain(const vector_t& y) {
        for (size_t i = 0; i < y.size(); ++i)
          data_r_.push_back(y[i]);
      }

      /**
       * Write the specified unconstrained matrix.
       *
       * @param y Matrix to write.
       */
      void matrix_unconstrain(const matrix_t& y) {
        for (size_t i = 0; i < y.rows(); ++i)
          for (size_t j = 0; j < y.cols(); ++j)
            data_r_.push_back(y(i,j));
      }

      /**
       * Write the unconstrained vector corresponding to the specified simplex
       * value.  If the specified constrained simplex is of size K,
       * the returned unconstrained vector is of size K-1.
       *
       *
The transform takes y = y[1],...,y[K] and
       * produces the unconstrained vector x = log(y[1]) -
       * log(y[K]), ..., log(y[K-1]) - log(y[K]).  This inverts
       * the constraining transform of
       * simplex_constrain(size_t).
       *
       * @param y Simplex constrained value.
       * @return Unconstrained value.
       * @throw std::runtime_error if the vector is not a simplex.
       */
      void simplex_unconstrain(vector_t& y) {
        stan::math::check_simplex("stan::io::simplex_unconstrain(%1%)", y, "y");
        typename vector_t::size_type k_minus_1 = y.size() - 1;
        double log_y_k = log(y[k_minus_1]);
        for (typename vector_t::size_type i = 0; i < k_minus_1; ++i) {
          data_r_.push_back(log(y[i]) - log_y_k);
        }
      }

      /**
       * Writes the unconstrained correlation matrix corresponding
       * to the specified constrained correlation matrix.
       *
       *
The unconstraining operation is the inverse of the
       * constraining operation in
       * corr_matrix_constrain(Matrix<T,Dynamic,Dynamic).
       *
       * @param y Constrained correlation matrix.
       * @throw std::runtime_error if the correlation matrix has no elements or
       *    is not a square matrix.
       * @throw std::runtime_error if the correlation matrix cannot be factorized
       *    by factor_cov_matrix() or if the sds returned by factor_cov_matrix()
       *    on log scale are unconstrained.
       */
      void corr_matrix_unconstrain(matrix_t& y) {
        stan::math::check_corr_matrix("stan::io::corr_matrix_unconstrain(%1%)", y, "y");
        size_t k = y.rows();
        size_t k_choose_2 = (k * (k-1)) / 2;
        array_vec_t cpcs(k_choose_2);
        array_vec_t sds(k);
        bool successful = stan::prob::factor_cov_matrix(cpcs,sds,y);
        if (!successful)
          BOOST_THROW_EXCEPTION(std::runtime_error ("y cannot be factorized by factor_cov_matrix"));
        for (size_t i = 0; i < k; ++i) {
          // sds on log scale unconstrained
          if (fabs(sds[i] - 0.0) >= CONSTRAINT_TOLERANCE)
            BOOST_THROW_EXCEPTION(std::runtime_error ("sds on log scale are unconstrained"));
        }
        for (size_t i = 0; i < k_choose_2; ++i)
          data_r_.push_back(cpcs[i]);
      }

      /**
       * Writes the unconstrained covariance matrix corresponding
       * to the specified constrained correlation matrix.
       *
       *
The unconstraining operation is the inverse of the
       * constraining operation in
       * cov_matrix_constrain(Matrix<T,Dynamic,Dynamic).
       *
       * @param y Constrained covariance matrix.
       * @throw std::runtime_error if y has no elements or if it is not square
       */
      void cov_matrix_unconstrain(matrix_t& y) {
        typename matrix_t::size_type k = y.rows();
        if (k == 0 || y.cols() != k)
          BOOST_THROW_EXCEPTION(
              std::runtime_error ("y must have elements and y must be a square matrix"));
        typename matrix_t::size_type k_choose_2 = (k * (k-1)) / 2;
        array_vec_t cpcs(k_choose_2);
        array_vec_t sds(k);
        bool successful = stan::prob::factor_cov_matrix(cpcs,sds,y);
        if(!successful)
          BOOST_THROW_EXCEPTION(std::runtime_error ("factor_cov_matrix failed"));
        for (typename matrix_t::size_type i = 0; i < k_choose_2; ++i)
          data_r_.push_back(cpcs[i]);
        for (typename matrix_t::size_type i = 0; i < k; ++i)
          data_r_.push_back(sds[i]);
      }
    };
  }

}

#endif
<commit_msg>fixed writer reference return issue<commit_after>#ifndef __STAN__IO__WRITER_HPP__
#define __STAN__IO__WRITER_HPP__

#include <cstddef>
#include <stdexcept>
#include <vector>

#include <boost/multi_array.hpp>
#include <boost/throw_exception.hpp>

#include <stan/math/matrix.hpp>
#include <stan/math/special_functions.hpp>

#include <stan/prob/transform.hpp>

namespace stan {

  namespace io {

    /**
     * A stream-based writer for integer, scalar, vector, matrix
     * and array data types, which transforms from constrained to
     * a sequence of constrained variables.
     *
     *
This class converts constrained values to unconstrained
     * values with mappings that invert those defined in
     * stan::io::reader to convert unconstrained values
     * to constrained values.
     *
     * @tparam T Basic scalar type.
     */
    template <typename T>
    class writer {
    private:
      std::vector<T> data_r_;
      std::vector<int> data_i_;
    public:

      typedef typename stan::math::EigenType<T>::matrix matrix_t;
      typedef typename stan::math::EigenType<T>::vector vector_t;
      typedef typename stan::math::EigenType<T>::row_vector row_vector_t;

      typedef Eigen::Array<T,Eigen::Dynamic,1> array_vec_t;

      /**
       * This is the tolerance for checking arithmetic bounds
       * in rank and in simplexes.  The current value is 1E-8.
       */
      const double CONSTRAINT_TOLERANCE;

      /**
       * Construct a writer that writes to the specified
       * scalar and integer vectors.
       *
       * @param data_r Scalar values.
       * @param data_i Integer values.
       */
      writer(std::vector<T>& data_r,
             std::vector<int>& data_i)
        : data_r_(data_r),
          data_i_(data_i),
          CONSTRAINT_TOLERANCE(1E-8) {
      }

      /**
       * Destroy this writer.
       */
      ~writer() { }

      /**
       * Return a reference to the underlying vector of real values
       * that have been written.
       *
       * @return Values that have been written.
       */
      std::vector<T>& data_r() {
        return data_r_;
      }

      /**
       * Return a reference to the underlying vector of integer values
       * that have been written.
       *
       * @return Values that have been written.
       */
      std::vector<int>& data_i() {
        return data_i_;
      }

      /**
       * Write the specified integer to the sequence of integer values.
       *
       * @param n Integer to write.
       */
      void integer(int n) {
        data_i_.push_back(n);
      }

      /**
       * Write the unconstrained value corresponding to the specified
       * scalar.  Here, the unconstrain operation is a no-op, which
       * matches reader::scalar_constrain().
       *
       * @param y The value.
       */
      void scalar_unconstrain(T& y) {
        data_r_.push_back(y);
      }

      /**
       * Write the unconstrained value corresponding to the specified
       * positive-constrained scalar.  The transformation applied is
       * log(y), which is the inverse of constraining
       * transform specified in reader::scalar_pos_constrain().
       *
       *
This method will fail if the argument is not non-negative.
       *
       * @param y The positive value.
       * @throw std::runtime_error if y is negative.
       */
      void scalar_pos_unconstrain(T& y) {
        if (y < 0.0)
          BOOST_THROW_EXCEPTION(std::runtime_error ("y is negative"));
        data_r_.push_back(log(y));
      }

      /**
       * Return the unconstrained version of the specified input,
       * which is constrained to be above the specified lower bound.
       * The unconstraining transform is log(y - lb), which
       * inverts the constraining
       * transform defined in reader::scalar_lb_constrain(double),
       *
       * @param lb Lower bound.
       * @param y Lower-bounded value.
       * @throw std::runtime_error if y is lower than the lower bound provided.
       */
      void scalar_lb_unconstrain(double lb, T& y) {
        if (y < lb)
          BOOST_THROW_EXCEPTION(std::runtime_error ("y is lower than the lower bound"));
        data_r_.push_back(log(y - lb));
      }

      /**
       * Write the unconstrained value corresponding to the specified
       * lower-bounded value.  The unconstraining transform is
       * log(ub - y), which reverses the constraining
       * transform defined in reader::scalar_ub_constrain(double).
       *
       * @param ub Upper bound.
       * @param y Constrained value.
       * @throw std::runtime_error if y is higher than the upper bound provided.
       */
      void scalar_ub_unconstrain(double ub, T& y) {
        if (y > ub)
          BOOST_THROW_EXCEPTION(std::runtime_error ("y is higher than the lower bound"));
        data_r_.push_back(log(ub - y));
      }

      /**
       * Write the unconstrained value corresponding to the specified
       * value with the specified bounds.  The unconstraining
       * transform is given by reader::logit((y-L)/(U-L)), which
       * inverts the constraining transform defined in
       * scalar_lub_constrain(double,double).
       *
       * @param lb Lower bound.
       * @param ub Upper bound.
       * @param y Bounded value.
       * @throw std::runtime_error if y is not between the lower and upper bounds
       */
      void scalar_lub_unconstrain(double lb, double ub, T& y) {
        if (y < lb || y > ub)
          BOOST_THROW_EXCEPTION(std::runtime_error ("y is not between the lower and upper bounds"));
        data_r_.push_back(stan::math::logit((y - lb) / (ub - lb)));
      }

      /**
       * Write the unconstrained value corresponding to the specified
       * correlation-constrained variable.
       *
       *
The unconstraining transform is atanh(y), which
       * reverses the transfrom in corr_constrain().
       *
       * @param y Correlation value.
       * @throw std::runtime_error if y is not between -1.0 and 1.0
       */
      void corr_unconstrain(T& y) {
        if (y > 1.0 || y < -1.0)
          BOOST_THROW_EXCEPTION(std::runtime_error ("y is not between -1.0 and 1.0"));
        data_r_.push_back(atanh(y));
      }

      /**
       * Write the unconstrained value corresponding to the
       * specified probability value.
       *
       *
The unconstraining transform is logit(y),
       * which inverts the constraining transform defined in
       * prob_constrain().
       *
       * @param y Probability value.
       * @throw std::runtime_error if y is not between 0.0 and 1.0
        */
      void prob_unconstrain(T& y) {
        if (y > 1.0 || y < 0.0)
          BOOST_THROW_EXCEPTION(std::runtime_error ("y is not between 0.0 and 1.0"));
        data_r_.push_back(stan::math::logit(y));
      }

      /**
       * Write the unconstrained vector that corresponds to the specified
       * positive ordered vector.
       *
       *
The unconstraining transform is defined for input vector y
       * to produce an output vector x of the same size, defined
       * by x[0] = log(y[0]) and by
       * x[k] = log(y[k] - y[k-1]) for k > 0.  This
       * unconstraining transform inverts the constraining transform specified
       * in pos_ordered_constrain(size_t).
       *
       * @param y Positive, ordered vector.
       * @return Unconstrained vector corresponding to the specified vector.
       * @throw std::runtime_error if vector is not positive ordered
       */
      void pos_ordered_unconstrain(vector_t& y) {
        if (y.size() == 0) return;
        stan::math::check_pos_ordered("stan::io::pos_ordered_unconstrain(%1%)", y, "y");
        data_r_.push_back(log(y[0]));
        for (typename vector_t::size_type i = 1; i < y.size(); ++i) {
          data_r_.push_back(log(y[i] - y[i-1]));
        }
      }

      /**
       * Write the specified unconstrained vector.
       *
       * @param y Vector to write.
       */
      void vector_unconstrain(const vector_t& y) {
        for (size_t i = 0; i < y.size(); ++i)
          data_r_.push_back(y[i]);
      }

      /**
       * Write the specified unconstrained vector.
       *
       * @param y Vector to write.
       */
      void row_vector_unconstrain(const vector_t& y) {
        for (size_t i = 0; i < y.size(); ++i)
          data_r_.push_back(y[i]);
      }

      /**
       * Write the specified unconstrained matrix.
       *
       * @param y Matrix to write.
       */
      void matrix_unconstrain(const matrix_t& y) {
        for (size_t i = 0; i < y.rows(); ++i)
          for (size_t j = 0; j < y.cols(); ++j)
            data_r_.push_back(y(i,j));
      }

      /**
       * Write the unconstrained vector corresponding to the specified simplex
       * value.  If the specified constrained simplex is of size K,
       * the returned unconstrained vector is of size K-1.
       *
       *
The transform takes y = y[1],...,y[K] and
       * produces the unconstrained vector x = log(y[1]) -
       * log(y[K]), ..., log(y[K-1]) - log(y[K]).  This inverts
       * the constraining transform of
       * simplex_constrain(size_t).
       *
       * @param y Simplex constrained value.
       * @return Unconstrained value.
       * @throw std::runtime_error if the vector is not a simplex.
       */
      void simplex_unconstrain(vector_t& y) {
        stan::math::check_simplex("stan::io::simplex_unconstrain(%1%)", y, "y");
        typename vector_t::size_type k_minus_1 = y.size() - 1;
        double log_y_k = log(y[k_minus_1]);
        for (typename vector_t::size_type i = 0; i < k_minus_1; ++i) {
          data_r_.push_back(log(y[i]) - log_y_k);
        }
      }

      /**
       * Writes the unconstrained correlation matrix corresponding
       * to the specified constrained correlation matrix.
       *
       *
The unconstraining operation is the inverse of the
       * constraining operation in
       * corr_matrix_constrain(Matrix<T,Dynamic,Dynamic).
       *
       * @param y Constrained correlation matrix.
       * @throw std::runtime_error if the correlation matrix has no elements or
       *    is not a square matrix.
       * @throw std::runtime_error if the correlation matrix cannot be factorized
       *    by factor_cov_matrix() or if the sds returned by factor_cov_matrix()
       *    on log scale are unconstrained.
       */
      void corr_matrix_unconstrain(matrix_t& y) {
        stan::math::check_corr_matrix("stan::io::corr_matrix_unconstrain(%1%)", y, "y");
        size_t k = y.rows();
        size_t k_choose_2 = (k * (k-1)) / 2;
        array_vec_t cpcs(k_choose_2);
        array_vec_t sds(k);
        bool successful = stan::prob::factor_cov_matrix(cpcs,sds,y);
        if (!successful)
          BOOST_THROW_EXCEPTION(std::runtime_error ("y cannot be factorized by factor_cov_matrix"));
        for (size_t i = 0; i < k; ++i) {
          // sds on log scale unconstrained
          if (fabs(sds[i] - 0.0) >= CONSTRAINT_TOLERANCE)
            BOOST_THROW_EXCEPTION(std::runtime_error ("sds on log scale are unconstrained"));
        }
        for (size_t i = 0; i < k_choose_2; ++i)
          data_r_.push_back(cpcs[i]);
      }

      /**
       * Writes the unconstrained covariance matrix corresponding
       * to the specified constrained correlation matrix.
       *
       *
The unconstraining operation is the inverse of the
       * constraining operation in
       * cov_matrix_constrain(Matrix<T,Dynamic,Dynamic).
       *
       * @param y Constrained covariance matrix.
       * @throw std::runtime_error if y has no elements or if it is not square
       */
      void cov_matrix_unconstrain(matrix_t& y) {
        typename matrix_t::size_type k = y.rows();
        if (k == 0 || y.cols() != k)
          BOOST_THROW_EXCEPTION(
              std::runtime_error ("y must have elements and y must be a square matrix"));
        typename matrix_t::size_type k_choose_2 = (k * (k-1)) / 2;
        array_vec_t cpcs(k_choose_2);
        array_vec_t sds(k);
        bool successful = stan::prob::factor_cov_matrix(cpcs,sds,y);
        if(!successful)
          BOOST_THROW_EXCEPTION(std::runtime_error ("factor_cov_matrix failed"));
        for (typename matrix_t::size_type i = 0; i < k_choose_2; ++i)
          data_r_.push_back(cpcs[i]);
        for (typename matrix_t::size_type i = 0; i < k; ++i)
          data_r_.push_back(sds[i]);
      }
    };
  }

}

#endif
<|endoftext|>


<commit_before>/* Copyright (c) 2008-2017 the MRtrix3 contributors.
 *
 * 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/.
 *
 * MRtrix 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.
 *
 * For more details, see http://www.mrtrix.org/.
 */

#include "stats/permtest.h"

namespace MR
{
  namespace Stats
  {
    namespace PermTest
    {

      PreProcessor::PreProcessor (const std::shared_ptr<Math::Stats::GLM::TestBase> stats_calculator,
                                  const std::shared_ptr<EnhancerBase> enhancer,
                                  matrix_type& global_enhanced_sum,
                                  vector<vector<size_t>>& global_enhanced_count) :
          stats_calculator (stats_calculator),
          enhancer (enhancer),
          global_enhanced_sum (global_enhanced_sum),
          global_enhanced_count (global_enhanced_count),
          enhanced_sum (vector_type::Zero (global_enhanced_sum.size())),
          enhanced_count (stats_calculator->num_outputs(), vector<size_t> (stats_calculator->num_elements(), 0)),
          stats (global_enhanced_sum.rows(), global_enhanced_sum.cols()),
          enhanced_stats (global_enhanced_sum.rows(), global_enhanced_sum.cols()),
          mutex (new std::mutex())
      {
        assert (stats_calculator);
        assert (enhancer);
      }

      PreProcessor::~PreProcessor ()
      {
        std::lock_guard<std::mutex> lock (*mutex);
        global_enhanced_sum.array() += enhanced_sum.array();
        for (ssize_t row = 0; row != global_enhanced_sum.rows(); ++row) {
          for (ssize_t col = 0; col != global_enhanced_sum.cols(); ++col)
            global_enhanced_count[row][col] += enhanced_count[row][col];
        }
      }

      bool PreProcessor::operator() (const Math::Stats::Shuffle& shuffle)
      {
        if (!shuffle.data.rows())
          return false;
        (*stats_calculator) (shuffle.data, stats);
        (*enhancer) (stats, enhanced_stats);
        for (ssize_t c = 0; c != enhanced_stats.rows(); ++c) {
          for (ssize_t i = 0; i < enhanced_stats.cols(); ++i) {
            if (enhanced_stats(c, i) > 0.0) {
              enhanced_sum(c, i) += enhanced_stats(c, i);
              enhanced_count[c][i]++;
            }
          }
        }
        return true;
      }

      Processor::Processor (const std::shared_ptr<Math::Stats::GLM::TestBase> stats_calculator,
                            const std::shared_ptr<EnhancerBase> enhancer,
                            const matrix_type& empirical_enhanced_statistics,
                            const matrix_type& default_enhanced_statistics,
                            matrix_type& perm_dist,
                            vector<vector<size_t>>& global_uncorrected_pvalue_counter) :
          stats_calculator (stats_calculator),
          enhancer (enhancer),
          empirical_enhanced_statistics (empirical_enhanced_statistics),
          default_enhanced_statistics (default_enhanced_statistics),
          statistics (stats_calculator->num_elements(), stats_calculator->num_outputs()),
          enhanced_statistics (stats_calculator->num_elements(), stats_calculator->num_outputs()),
    // TODO Consider changing to Eigen::Array<size_t>
          uncorrected_pvalue_counter (stats_calculator->num_outputs(), vector<size_t> (stats_calculator->num_elements(), 0)),
          perm_dist (perm_dist),
          global_uncorrected_pvalue_counter (global_uncorrected_pvalue_counter),
          mutex (new std::mutex())
      {
        assert (stats_calculator);
      }

      Processor::~Processor ()
      {
        std::lock_guard<std::mutex> lock (*mutex);
        for (size_t contrast = 0; contrast != stats_calculator->num_outputs(); ++contrast) {
          for (size_t element = 0; element != stats_calculator->num_elements(); ++element)
            global_uncorrected_pvalue_counter[contrast][element] += uncorrected_pvalue_counter[contrast][element];
        }
      }

      bool Processor::operator() (const Math::Stats::Shuffle& shuffle)
      {
        (*stats_calculator) (shuffle.data, statistics);
        if (enhancer)
          (*enhancer) (statistics, enhanced_statistics);
        else
          enhanced_statistics = statistics;

        if (empirical_enhanced_statistics.size())
          enhanced_statistics.array() /= empirical_enhanced_statistics.array();

        perm_dist.row(shuffle.index) = enhanced_statistics.colwise().maxCoeff();

        for (ssize_t contrast = 0; contrast != enhanced_statistics.cols(); ++contrast) {
          for (ssize_t element = 0; element != enhanced_statistics.rows(); ++element) {
            if (default_enhanced_statistics(element, contrast) > enhanced_statistics(element, contrast))
              uncorrected_pvalue_counter[contrast][element]++;
          }
        }

        return true;
      }

      void precompute_empirical_stat (const std::shared_ptr<Math::Stats::GLM::TestBase> stats_calculator,
                                      const std::shared_ptr<EnhancerBase> enhancer,
                                      matrix_type& empirical_statistic)
      {
        assert (stats_calculator);
        vector<vector<size_t>> global_enhanced_count (empirical_statistic.rows(), vector<size_t> (empirical_statistic.cols(), 0));
        {
          Math::Stats::Shuffler shuffler (stats_calculator->num_subjects(), true, "Pre-computing empirical statistic for non-stationarity correction");
          PreProcessor preprocessor (stats_calculator, enhancer, empirical_statistic, global_enhanced_count);
          Thread::run_queue (shuffler, Math::Stats::Shuffle(), Thread::multi (preprocessor));
        }
        for (ssize_t row = 0; row != empirical_statistic.rows(); ++row) {
          for (ssize_t i = 0; i != empirical_statistic.cols(); ++i) {
            if (global_enhanced_count[row][i] > 0.0)
              empirical_statistic(row, i) /= static_cast<default_type> (global_enhanced_count[row][i]);
          }
        }
      }

      void precompute_default_permutation (const std::shared_ptr<Math::Stats::GLM::TestBase> stats_calculator,
                                           const std::shared_ptr<EnhancerBase> enhancer,
                                           const matrix_type& empirical_enhanced_statistic,
                                           matrix_type& default_enhanced_statistics,
                                           matrix_type& default_statistics)
      {
        assert (stats_calculator);
        default_statistics.resize (stats_calculator->num_elements(), stats_calculator->num_outputs());
        default_enhanced_statistics.resize (stats_calculator->num_elements(), stats_calculator->num_outputs());

        const matrix_type default_shuffle (matrix_type::Identity (stats_calculator->num_subjects(), stats_calculator->num_subjects()));
        (*stats_calculator) (default_shuffle, default_statistics);

        if (enhancer)
          (*enhancer) (default_statistics, default_enhanced_statistics);
        else
          default_enhanced_statistics = default_statistics;

        if (empirical_enhanced_statistic.size())
          default_enhanced_statistics.array() /= empirical_enhanced_statistic.array();
      }

      void run_permutations (const std::shared_ptr<Math::Stats::GLM::TestBase> stats_calculator,
                             const std::shared_ptr<EnhancerBase> enhancer,
                             const matrix_type& empirical_enhanced_statistic,
                             const matrix_type& default_enhanced_statistics,
                             matrix_type& perm_dist,
                             matrix_type& uncorrected_pvalues)
      {
        assert (stats_calculator);
        Math::Stats::Shuffler shuffler (stats_calculator->num_subjects(), false, "Running permutations");
        perm_dist.resize (shuffler.size(), stats_calculator->num_outputs());
        uncorrected_pvalues.resize (stats_calculator->num_elements(), stats_calculator->num_outputs());

        vector<vector<size_t>> global_uncorrected_pvalue_count (stats_calculator->num_outputs(), vector<size_t> (stats_calculator->num_elements(), 0));
        {
          Processor processor (stats_calculator, enhancer,
                               empirical_enhanced_statistic,
                               default_enhanced_statistics,
                               perm_dist,
                               global_uncorrected_pvalue_count);
          Thread::run_queue (shuffler, Math::Stats::Shuffle(), Thread::multi (processor));
        }

        for (size_t contrast = 0; contrast != stats_calculator->num_outputs(); ++contrast) {
          for (size_t element = 0; element != stats_calculator->num_elements(); ++element)
            uncorrected_pvalues(element, contrast) = global_uncorrected_pvalue_count[contrast][element] / default_type(shuffler.size());
        }
      }

    }
  }
}

<commit_msg>Stats: Fix -nonstationary option<commit_after>/* Copyright (c) 2008-2017 the MRtrix3 contributors.
 *
 * 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/.
 *
 * MRtrix 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.
 *
 * For more details, see http://www.mrtrix.org/.
 */

#include "stats/permtest.h"

namespace MR
{
  namespace Stats
  {
    namespace PermTest
    {

      PreProcessor::PreProcessor (const std::shared_ptr<Math::Stats::GLM::TestBase> stats_calculator,
                                  const std::shared_ptr<EnhancerBase> enhancer,
                                  matrix_type& global_enhanced_sum,
                                  vector<vector<size_t>>& global_enhanced_count) :
          stats_calculator (stats_calculator),
          enhancer (enhancer),
          global_enhanced_sum (global_enhanced_sum),
          global_enhanced_count (global_enhanced_count),
          enhanced_sum (vector_type::Zero (global_enhanced_sum.size())),
          enhanced_count (stats_calculator->num_outputs(), vector<size_t> (stats_calculator->num_elements(), 0)),
          stats (global_enhanced_sum.rows(), global_enhanced_sum.cols()),
          enhanced_stats (global_enhanced_sum.rows(), global_enhanced_sum.cols()),
          mutex (new std::mutex())
      {
        assert (stats_calculator);
        assert (enhancer);
      }

      PreProcessor::~PreProcessor ()
      {
        std::lock_guard<std::mutex> lock (*mutex);
        global_enhanced_sum.array() += enhanced_sum.array();
        for (ssize_t row = 0; row != global_enhanced_sum.rows(); ++row) {
          for (ssize_t col = 0; col != global_enhanced_sum.cols(); ++col)
            global_enhanced_count[row][col] += enhanced_count[row][col];
        }
      }

      bool PreProcessor::operator() (const Math::Stats::Shuffle& shuffle)
      {
        if (!shuffle.data.rows())
          return false;
        (*stats_calculator) (shuffle.data, stats);
        (*enhancer) (stats, enhanced_stats);
        for (ssize_t c = 0; c != enhanced_stats.rows(); ++c) {
          for (ssize_t i = 0; i < enhanced_stats.cols(); ++i) {
            if (enhanced_stats(c, i) > 0.0) {
              enhanced_sum(c, i) += enhanced_stats(c, i);
              enhanced_count[c][i]++;
            }
          }
        }
        return true;
      }

      Processor::Processor (const std::shared_ptr<Math::Stats::GLM::TestBase> stats_calculator,
                            const std::shared_ptr<EnhancerBase> enhancer,
                            const matrix_type& empirical_enhanced_statistics,
                            const matrix_type& default_enhanced_statistics,
                            matrix_type& perm_dist,
                            vector<vector<size_t>>& global_uncorrected_pvalue_counter) :
          stats_calculator (stats_calculator),
          enhancer (enhancer),
          empirical_enhanced_statistics (empirical_enhanced_statistics),
          default_enhanced_statistics (default_enhanced_statistics),
          statistics (stats_calculator->num_elements(), stats_calculator->num_outputs()),
          enhanced_statistics (stats_calculator->num_elements(), stats_calculator->num_outputs()),
    // TODO Consider changing to Eigen::Array<size_t>
          uncorrected_pvalue_counter (stats_calculator->num_outputs(), vector<size_t> (stats_calculator->num_elements(), 0)),
          perm_dist (perm_dist),
          global_uncorrected_pvalue_counter (global_uncorrected_pvalue_counter),
          mutex (new std::mutex())
      {
        assert (stats_calculator);
      }

      Processor::~Processor ()
      {
        std::lock_guard<std::mutex> lock (*mutex);
        for (size_t contrast = 0; contrast != stats_calculator->num_outputs(); ++contrast) {
          for (size_t element = 0; element != stats_calculator->num_elements(); ++element)
            global_uncorrected_pvalue_counter[contrast][element] += uncorrected_pvalue_counter[contrast][element];
        }
      }

      bool Processor::operator() (const Math::Stats::Shuffle& shuffle)
      {
        (*stats_calculator) (shuffle.data, statistics);
        if (enhancer)
          (*enhancer) (statistics, enhanced_statistics);
        else
          enhanced_statistics = statistics;

        if (empirical_enhanced_statistics.size())
          enhanced_statistics.array() /= empirical_enhanced_statistics.array();

        perm_dist.row(shuffle.index) = enhanced_statistics.colwise().maxCoeff();

        for (ssize_t contrast = 0; contrast != enhanced_statistics.cols(); ++contrast) {
          for (ssize_t element = 0; element != enhanced_statistics.rows(); ++element) {
            if (default_enhanced_statistics(element, contrast) > enhanced_statistics(element, contrast))
              uncorrected_pvalue_counter[contrast][element]++;
          }
        }

        return true;
      }

      void precompute_empirical_stat (const std::shared_ptr<Math::Stats::GLM::TestBase> stats_calculator,
                                      const std::shared_ptr<EnhancerBase> enhancer,
                                      matrix_type& empirical_statistic)
      {
        assert (stats_calculator);
        empirical_statistic = matrix_type::Zero (stats_calculator->num_elements(), stats_calculator->num_outputs());
        vector<vector<size_t>> global_enhanced_count (stats_calculator->num_outputs(), vector<size_t> (stats_calculator->num_elements(), 0));
        {
          Math::Stats::Shuffler shuffler (stats_calculator->num_subjects(), true, "Pre-computing empirical statistic for non-stationarity correction");
          PreProcessor preprocessor (stats_calculator, enhancer, empirical_statistic, global_enhanced_count);
          Thread::run_queue (shuffler, Math::Stats::Shuffle(), Thread::multi (preprocessor));
        }
        for (ssize_t contrast = 0; contrast != stats_calculator->num_outputs(); ++contrast) {
          for (ssize_t element = 0; element != stats_calculator->num_elements(); ++element) {
            if (global_enhanced_count[contrast][element] > 0)
              empirical_statistic(contrast, element) /= static_cast<default_type> (global_enhanced_count[contrast][element]);
          }
        }
      }

      void precompute_default_permutation (const std::shared_ptr<Math::Stats::GLM::TestBase> stats_calculator,
                                           const std::shared_ptr<EnhancerBase> enhancer,
                                           const matrix_type& empirical_enhanced_statistic,
                                           matrix_type& default_enhanced_statistics,
                                           matrix_type& default_statistics)
      {
        assert (stats_calculator);
        default_statistics.resize (stats_calculator->num_elements(), stats_calculator->num_outputs());
        default_enhanced_statistics.resize (stats_calculator->num_elements(), stats_calculator->num_outputs());

        const matrix_type default_shuffle (matrix_type::Identity (stats_calculator->num_subjects(), stats_calculator->num_subjects()));
        (*stats_calculator) (default_shuffle, default_statistics);

        if (enhancer)
          (*enhancer) (default_statistics, default_enhanced_statistics);
        else
          default_enhanced_statistics = default_statistics;

        if (empirical_enhanced_statistic.size())
          default_enhanced_statistics.array() /= empirical_enhanced_statistic.array();
      }

      void run_permutations (const std::shared_ptr<Math::Stats::GLM::TestBase> stats_calculator,
                             const std::shared_ptr<EnhancerBase> enhancer,
                             const matrix_type& empirical_enhanced_statistic,
                             const matrix_type& default_enhanced_statistics,
                             matrix_type& perm_dist,
                             matrix_type& uncorrected_pvalues)
      {
        assert (stats_calculator);
        Math::Stats::Shuffler shuffler (stats_calculator->num_subjects(), false, "Running permutations");
        perm_dist.resize (shuffler.size(), stats_calculator->num_outputs());
        uncorrected_pvalues.resize (stats_calculator->num_elements(), stats_calculator->num_outputs());

        vector<vector<size_t>> global_uncorrected_pvalue_count (stats_calculator->num_outputs(), vector<size_t> (stats_calculator->num_elements(), 0));
        {
          Processor processor (stats_calculator, enhancer,
                               empirical_enhanced_statistic,
                               default_enhanced_statistics,
                               perm_dist,
                               global_uncorrected_pvalue_count);
          Thread::run_queue (shuffler, Math::Stats::Shuffle(), Thread::multi (processor));
        }

        for (size_t contrast = 0; contrast != stats_calculator->num_outputs(); ++contrast) {
          for (size_t element = 0; element != stats_calculator->num_elements(); ++element)
            uncorrected_pvalues(element, contrast) = global_uncorrected_pvalue_count[contrast][element] / default_type(shuffler.size());
        }
      }

    }
  }
}

<|endoftext|>


<commit_before>#pragma once

#include <cassert>
#include <fstream>
#include <cstring>
#include <string>

/**
 * This namespace defines wrappers for std::ifstream, std::ofstream, and
 * std::fstream objects. The wrappers perform the following steps:
 * - check the open modes make sense
 * - check that the call to open() is successful
 * - (for input streams) check that the opened file is peek-able
 * - turn on the badbit in the exception mask
 */
namespace strict_fstream
{

// Help people out a bit, it seems like this is a common recommenation since
// musl breaks all over the place.
#if defined(__NEED_size_t) && !defined(__MUSL__)
#warning "It seems to be recommended to patch in a define for __MUSL__ if you use musl globally: https://www.openwall.com/lists/musl/2013/02/10/5"
#define __MUSL__
#endif

// Workaround for broken musl implementation
// Since musl insists that they are perfectly compatible, ironically enough,
// they don't officially have a __musl__ or similar. But __NEED_size_t is defined in their
// relevant header (and not in working implementations), so we can use that.
#ifdef __MUSL__
#warning "Working around broken strerror_r() implementation in musl, remove when musl is fixed"
#endif

// Non-gnu variants of strerror_* don't necessarily null-terminate if
// truncating, so we have to do things manually.
inline std::string &trim_to_null(std::string &buff)
{
    const std::string::size_type pos = buff.find('\0');
    if (pos == std::string::npos) {
        buff += " [...]"; // it has been truncated
    } else {
        buff.resize(pos);
    }
    return buff;
}

/// Overload of error-reporting function, to enable use with VS.
/// Ref: http://stackoverflow.com/a/901316/717706
static std::string strerror()
{
    std::string buff(256, '\0');
#ifdef _WIN32
    // Since strerror_s might set errno itself, we need to store it.
    const int err_num = errno;
    if (strerror_s(buff.data(), buff.size(), err_num) != 0) {
        return trim_to_null(buff);
    } else {
        return "Unknown error (" + std::to_string(err_num) + ")";
    }
#elif ((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600 || defined(__APPLE__)) && ! _GNU_SOURCE) || defined(__MUSL__)
// XSI-compliant strerror_r()
    const int err_num = errno; // See above
    if (strerror_r(err_num, buff.data(), buff.size()) == 0) {
        return trim_to_null(buff);
    } else {
        return "Unknown error (" + std::to_string(err_num) + ")";
    }
#else
// GNU-specific strerror_r()
    char * p = strerror_r(errno, &buff[0], buff.size());
    return std::string(p, std::strlen(p));
#endif
}

/// Exception class thrown by failed operations.
class Exception
    : public std::exception
{
public:
    Exception(const std::string& msg) : _msg(msg) {}
    const char * what() const noexcept { return _msg.c_str(); }
private:
    std::string _msg;
}; // class Exception

namespace detail
{

struct static_method_holder
{
    static std::string mode_to_string(std::ios_base::openmode mode)
    {
        static const int n_modes = 6;
        static const std::ios_base::openmode mode_val_v[n_modes] =
            {
                std::ios_base::in,
                std::ios_base::out,
                std::ios_base::app,
                std::ios_base::ate,
                std::ios_base::trunc,
                std::ios_base::binary
            };

        static const char * mode_name_v[n_modes] =
            {
                "in",
                "out",
                "app",
                "ate",
                "trunc",
                "binary"
            };
        std::string res;
        for (int i = 0; i < n_modes; ++i)
        {
            if (mode & mode_val_v[i])
            {
                res += (! res.empty()? "|" : "");
                res += mode_name_v[i];
            }
        }
        if (res.empty()) res = "none";
        return res;
    }
    static void check_mode(const std::string& filename, std::ios_base::openmode mode)
    {
        if ((mode & std::ios_base::trunc) && ! (mode & std::ios_base::out))
        {
            throw Exception(std::string("strict_fstream: open('") + filename + "'): mode error: trunc and not out");
        }
        else if ((mode & std::ios_base::app) && ! (mode & std::ios_base::out))
        {
            throw Exception(std::string("strict_fstream: open('") + filename + "'): mode error: app and not out");
        }
        else if ((mode & std::ios_base::trunc) && (mode & std::ios_base::app))
        {
            throw Exception(std::string("strict_fstream: open('") + filename + "'): mode error: trunc and app");
        }
     }
    static void check_open(std::ios * s_p, const std::string& filename, std::ios_base::openmode mode)
    {
        if (s_p->fail())
        {
            throw Exception(std::string("strict_fstream: open('")
                            + filename + "'," + mode_to_string(mode) + "): open failed: "
                            + strerror());
        }
    }
    static void check_peek(std::istream * is_p, const std::string& filename, std::ios_base::openmode mode)
    {
        bool peek_failed = true;
        try
        {
            is_p->peek();
            peek_failed = is_p->fail();
        }
        catch (const std::ios_base::failure &) {}
        if (peek_failed)
        {
            throw Exception(std::string("strict_fstream: open('")
                            + filename + "'," + mode_to_string(mode) + "): peek failed: "
                            + strerror());
        }
        is_p->clear();
    }
}; // struct static_method_holder

} // namespace detail

class ifstream
    : public std::ifstream
{
public:
    ifstream() = default;
    ifstream(const std::string& filename, std::ios_base::openmode mode = std::ios_base::in)
    {
        open(filename, mode);
    }
    void open(const std::string& filename, std::ios_base::openmode mode = std::ios_base::in)
    {
        mode |= std::ios_base::in;
        exceptions(std::ios_base::badbit);
        detail::static_method_holder::check_mode(filename, mode);
        std::ifstream::open(filename, mode);
        detail::static_method_holder::check_open(this, filename, mode);
        detail::static_method_holder::check_peek(this, filename, mode);
    }
}; // class ifstream

class ofstream
    : public std::ofstream
{
public:
    ofstream() = default;
    ofstream(const std::string& filename, std::ios_base::openmode mode = std::ios_base::out)
    {
        open(filename, mode);
    }
    void open(const std::string& filename, std::ios_base::openmode mode = std::ios_base::out)
    {
        mode |= std::ios_base::out;
        exceptions(std::ios_base::badbit);
        detail::static_method_holder::check_mode(filename, mode);
        std::ofstream::open(filename, mode);
        detail::static_method_holder::check_open(this, filename, mode);
    }
}; // class ofstream

class fstream
    : public std::fstream
{
public:
    fstream() = default;
    fstream(const std::string& filename, std::ios_base::openmode mode = std::ios_base::in)
    {
        open(filename, mode);
    }
    void open(const std::string& filename, std::ios_base::openmode mode = std::ios_base::in)
    {
        if (! (mode & std::ios_base::out)) mode |= std::ios_base::in;
        exceptions(std::ios_base::badbit);
        detail::static_method_holder::check_mode(filename, mode);
        std::fstream::open(filename, mode);
        detail::static_method_holder::check_open(this, filename, mode);
        detail::static_method_holder::check_peek(this, filename, mode);
    }
}; // class fstream

} // namespace strict_fstream

<commit_msg>fix macos/alpine<commit_after>#pragma once

#include <cassert>
#include <fstream>
#include <cstring>
#include <string>
#include <vector>

/**
 * This namespace defines wrappers for std::ifstream, std::ofstream, and
 * std::fstream objects. The wrappers perform the following steps:
 * - check the open modes make sense
 * - check that the call to open() is successful
 * - (for input streams) check that the opened file is peek-able
 * - turn on the badbit in the exception mask
 */
namespace strict_fstream
{

// Help people out a bit, it seems like this is a common recommenation since
// musl breaks all over the place.
#if defined(__NEED_size_t) && !defined(__MUSL__)
#warning "It seems to be recommended to patch in a define for __MUSL__ if you use musl globally: https://www.openwall.com/lists/musl/2013/02/10/5"
#define __MUSL__
#endif

// Workaround for broken musl implementation
// Since musl insists that they are perfectly compatible, ironically enough,
// they don't officially have a __musl__ or similar. But __NEED_size_t is defined in their
// relevant header (and not in working implementations), so we can use that.
#ifdef __MUSL__
#warning "Working around broken strerror_r() implementation in musl, remove when musl is fixed"
#endif

// Non-gnu variants of strerror_* don't necessarily null-terminate if
// truncating, so we have to do things manually.
inline std::string trim_to_null(const std::vector<char> &buff)
{
    std::string ret(buff.begin(), buff.end());

    const std::string::size_type pos = ret.find('\0');
    if (pos == std::string::npos) {
        ret += " [...]"; // it has been truncated
    } else {
        ret.resize(pos);
    }
    return ret;
}

/// Overload of error-reporting function, to enable use with VS and non-GNU
/// POSIX libc's
/// Ref:
///   - http://stackoverflow.com/a/901316/717706
static std::string strerror()
{
    // Can't use std::string since we're pre-C++17
    std::vector<char> buff(256, '\0');

#ifdef _WIN32
    // Since strerror_s might set errno itself, we need to store it.
    const int err_num = errno;
    if (strerror_s(buff.data(), buff.size(), err_num) != 0) {
        return trim_to_null(buff);
    } else {
        return "Unknown error (" + std::to_string(err_num) + ")";
    }
#elif ((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600 || defined(__APPLE__)) && ! _GNU_SOURCE) || defined(__MUSL__)
// XSI-compliant strerror_r()
    const int err_num = errno; // See above
    if (strerror_r(err_num, buff.data(), buff.size()) == 0) {
        return trim_to_null(buff);
    } else {
        return "Unknown error (" + std::to_string(err_num) + ")";
    }
#else
// GNU-specific strerror_r()
    char * p = strerror_r(errno, &buff[0], buff.size());
    return std::string(p, std::strlen(p));
#endif
}

/// Exception class thrown by failed operations.
class Exception
    : public std::exception
{
public:
    Exception(const std::string& msg) : _msg(msg) {}
    const char * what() const noexcept { return _msg.c_str(); }
private:
    std::string _msg;
}; // class Exception

namespace detail
{

struct static_method_holder
{
    static std::string mode_to_string(std::ios_base::openmode mode)
    {
        static const int n_modes = 6;
        static const std::ios_base::openmode mode_val_v[n_modes] =
            {
                std::ios_base::in,
                std::ios_base::out,
                std::ios_base::app,
                std::ios_base::ate,
                std::ios_base::trunc,
                std::ios_base::binary
            };

        static const char * mode_name_v[n_modes] =
            {
                "in",
                "out",
                "app",
                "ate",
                "trunc",
                "binary"
            };
        std::string res;
        for (int i = 0; i < n_modes; ++i)
        {
            if (mode & mode_val_v[i])
            {
                res += (! res.empty()? "|" : "");
                res += mode_name_v[i];
            }
        }
        if (res.empty()) res = "none";
        return res;
    }
    static void check_mode(const std::string& filename, std::ios_base::openmode mode)
    {
        if ((mode & std::ios_base::trunc) && ! (mode & std::ios_base::out))
        {
            throw Exception(std::string("strict_fstream: open('") + filename + "'): mode error: trunc and not out");
        }
        else if ((mode & std::ios_base::app) && ! (mode & std::ios_base::out))
        {
            throw Exception(std::string("strict_fstream: open('") + filename + "'): mode error: app and not out");
        }
        else if ((mode & std::ios_base::trunc) && (mode & std::ios_base::app))
        {
            throw Exception(std::string("strict_fstream: open('") + filename + "'): mode error: trunc and app");
        }
     }
    static void check_open(std::ios * s_p, const std::string& filename, std::ios_base::openmode mode)
    {
        if (s_p->fail())
        {
            throw Exception(std::string("strict_fstream: open('")
                            + filename + "'," + mode_to_string(mode) + "): open failed: "
                            + strerror());
        }
    }
    static void check_peek(std::istream * is_p, const std::string& filename, std::ios_base::openmode mode)
    {
        bool peek_failed = true;
        try
        {
            is_p->peek();
            peek_failed = is_p->fail();
        }
        catch (const std::ios_base::failure &) {}
        if (peek_failed)
        {
            throw Exception(std::string("strict_fstream: open('")
                            + filename + "'," + mode_to_string(mode) + "): peek failed: "
                            + strerror());
        }
        is_p->clear();
    }
}; // struct static_method_holder

} // namespace detail

class ifstream
    : public std::ifstream
{
public:
    ifstream() = default;
    ifstream(const std::string& filename, std::ios_base::openmode mode = std::ios_base::in)
    {
        open(filename, mode);
    }
    void open(const std::string& filename, std::ios_base::openmode mode = std::ios_base::in)
    {
        mode |= std::ios_base::in;
        exceptions(std::ios_base::badbit);
        detail::static_method_holder::check_mode(filename, mode);
        std::ifstream::open(filename, mode);
        detail::static_method_holder::check_open(this, filename, mode);
        detail::static_method_holder::check_peek(this, filename, mode);
    }
}; // class ifstream

class ofstream
    : public std::ofstream
{
public:
    ofstream() = default;
    ofstream(const std::string& filename, std::ios_base::openmode mode = std::ios_base::out)
    {
        open(filename, mode);
    }
    void open(const std::string& filename, std::ios_base::openmode mode = std::ios_base::out)
    {
        mode |= std::ios_base::out;
        exceptions(std::ios_base::badbit);
        detail::static_method_holder::check_mode(filename, mode);
        std::ofstream::open(filename, mode);
        detail::static_method_holder::check_open(this, filename, mode);
    }
}; // class ofstream

class fstream
    : public std::fstream
{
public:
    fstream() = default;
    fstream(const std::string& filename, std::ios_base::openmode mode = std::ios_base::in)
    {
        open(filename, mode);
    }
    void open(const std::string& filename, std::ios_base::openmode mode = std::ios_base::in)
    {
        if (! (mode & std::ios_base::out)) mode |= std::ios_base::in;
        exceptions(std::ios_base::badbit);
        detail::static_method_holder::check_mode(filename, mode);
        std::fstream::open(filename, mode);
        detail::static_method_holder::check_open(this, filename, mode);
        detail::static_method_holder::check_peek(this, filename, mode);
    }
}; // class fstream

} // namespace strict_fstream

<|endoftext|>