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

#ifdef _WIN32
#include <windows.h>
#ifndef AF_IPX
#include <winsock2.h>
#endif
#define SOCKET_HANDLE SOCKET
#else

#include <arpa/inet.h>
#include <netdb.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>

#define SOCKET_HANDLE int
#define closesocket close
#endif

#include <stdlib.h>
#include <string>

#include "native_client/src/trusted/gdb_rsp/util.h"
#include "native_client/src/trusted/port/platform.h"
#include "native_client/src/trusted/port/transport.h"

using gdb_rsp::stringvec;
using gdb_rsp::StringSplit;

namespace port {

typedef int socklen_t;

class Transport : public ITransport {
 public:
  Transport() {
    handle_ = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  }

  explicit Transport(SOCKET_HANDLE s) {
    handle_ = s;
  }

  ~Transport() {
    if (handle_ != -1) closesocket(handle_);
  }

  // Read from this transport, return a negative value if there is an error
  // otherwise return the number of bytes actually read.
  virtual int32_t Read(void *ptr, int32_t len) {
    return ::recv(handle_, reinterpret_cast<char *>(ptr), len, 0);
  }

  // Write to this transport, return a negative value if there is an error
  // otherwise return the number of bytes actually written.
  virtual int32_t Write(const void *ptr, int32_t len) {
    return ::send(handle_, reinterpret_cast<const char *>(ptr), len, 0);
  }

  // Return true if data becomes availible or false after ms milliseconds.
  virtual bool ReadWaitWithTimeout(uint32_t ms = 0) {
    fd_set fds;

    FD_ZERO(&fds);
    FD_SET(handle_, &fds);

    // We want a "non-blocking" check
    struct timeval timeout;
    timeout.tv_sec = 0;
    timeout.tv_usec= ms * 1000;

    // Check if this file handle can select on read
    int cnt = select(static_cast<int>(handle_) + 1, &fds, 0, 0, &timeout);

    // If we are ready, or if there is an error.  We return true
    // on error, to "timeout" and let the next IO request fail.
    if (cnt != 0) return true;

    return false;
  }

// On windows, the header that defines this has other definition
// colitions, so we define it outselves just in case
#ifndef SD_BOTH
#define SD_BOTH 2
#endif

  virtual void Disconnect() {
    // Shutdown the conneciton in both diections.  This should
    // always succeed, and nothing we can do if this fails.
    (void) ::shutdown(handle_, SD_BOTH);
  }

 protected:
  SOCKET_HANDLE handle_;
};

// Convert string in the form of [addr][:port] where addr is a
// IPv4 address or host name, and port is a 16b tcp/udp port.
// Both portions are optional, and only the portion of the address
// provided is updated.  Values are provided in network order.
static bool StringToIPv4(const std::string &instr, uint32_t *addr,
                         uint16_t *port) {
  // Make a copy so the are unchanged unless we succeed
  uint32_t outaddr = *addr;
  uint16_t outport = *port;

  // Substrings of the full ADDR:PORT
  std::string addrstr;
  std::string portstr;

  // We should either have one or two tokens in the form of:
  //  IP - IP, NUL
  //  IP: -  IP, NUL
  //  :PORT - NUL, PORT
  //  IP:PORT - IP, PORT

  // Search for the port marker
  size_t portoff = instr.find(':');

  // If we found a ":" before the end, get both substrings
  if ((portoff != std::string::npos) && (portoff + 1 < instr.size())) {
    addrstr = instr.substr(0, portoff);
    portstr = instr.substr(portoff + 1, std::string::npos);
  } else {
    // otherwise the entire string is the addr portion.
    addrstr = instr;
    portstr = "";
  }

  // If the address portion was provided, update it
  if (addrstr.size()) {
    // Special case 0.0.0.0 which means any IPv4 interface
    if (addrstr == "0.0.0.0") {
      outaddr = 0;
    } else {
      struct hostent *host = gethostbyname(addrstr.data());

      // Check that we found an IPv4 host
      if ((NULL == host) || (AF_INET != host->h_addrtype))  return false;

      // Make sure the IP list isn't empty.
      if (0 == host->h_addr_list[0]) return false;

      // Use the first address in the array of address pointers.
      uint32_t **addrarray = reinterpret_cast<uint32_t**>(host->h_addr_list);
      outaddr = *addrarray[0];
    }
  }

  // if the port portion was provided, then update it
  if (portstr.size()) {
    int val = atoi(portstr.data());
    if ((val < 0) || (val > 65535)) return false;
    outport = ntohs(static_cast<uint16_t>(val));
  }

  // We haven't failed, so set the values
  *addr = outaddr;
  *port = outport;
  return true;
}

static SOCKET_HANDLE s_ServerSock;

static bool SocketInit() {
  s_ServerSock = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  if (s_ServerSock == -1) {
    IPlatform::LogError("Failed to create socket.\n");
    return false;
  }

  return true;
}

static bool SocketsAvailable() {
  static bool _init = SocketInit();
  return _init;
}

static bool BuildSockAddr(const char *addr, struct sockaddr_in *sockaddr) {
  std::string addrstr = addr;
  uint32_t *pip = reinterpret_cast<uint32_t*>(&sockaddr->sin_addr.s_addr);
  uint16_t *pport = reinterpret_cast<uint16_t*>(&sockaddr->sin_port);

  sockaddr->sin_family = AF_INET;
  return StringToIPv4(addrstr, pip, pport);
}

ITransport* ITransport::Connect(const char *addr) {
  if (!SocketsAvailable()) return NULL;

  SOCKET_HANDLE s = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  if (s == -1) {
    IPlatform::LogError("Failed to create connection socket.\n");
    return NULL;
  }

  struct sockaddr_in saddr;
  saddr.sin_family = AF_INET;
  saddr.sin_addr.s_addr = htonl(0x7F000001);
  saddr.sin_port = htons(4014);

  // Override portions address that are provided
  if (addr) BuildSockAddr(addr, &saddr);

  if (::connect(s, reinterpret_cast<sockaddr*>(&saddr), sizeof(saddr)) != 0) {
    IPlatform::LogError("Failed to connect.\n");
    return NULL;
  }

  return new Transport(s);
}

ITransport* ITransport::Accept(const char *addr) {
  static bool listening = false;
  if (!SocketsAvailable()) return NULL;

  if (!listening) {
    struct sockaddr_in saddr;
    socklen_t addrlen = static_cast<socklen_t>(sizeof(saddr));
    saddr.sin_family = AF_INET;
    saddr.sin_addr.s_addr = htonl(0x7F000001);
    saddr.sin_port = htons(4014);

    // Override portions address that are provided
    if (addr) BuildSockAddr(addr, &saddr);

    // This is necessary to ensure that the TCP port is released
    // promptly when sel_ldr exits.  Without this, the TCP port might
    // only be released after a timeout, and later processes can fail
    // to bind it.
    int reuse_address = 1;
    setsockopt(s_ServerSock, SOL_SOCKET, SO_REUSEADDR,
               reinterpret_cast<char *>(&reuse_address),
               sizeof(reuse_address));

    struct sockaddr *psaddr = reinterpret_cast<struct sockaddr *>(&saddr);
    if (bind(s_ServerSock, psaddr, addrlen)) {
      IPlatform::LogError("Failed to bind server.\n");
      return NULL;
    }

    if (listen(s_ServerSock, 1)) {
      IPlatform::LogError("Failed to listen.\n");
      return NULL;
    }

    listening = true;
  }

  if (listening) {
    SOCKET_HANDLE s = ::accept(s_ServerSock, NULL, 0);
    if (-1 != s) return new Transport(s);
    return NULL;
  }

  return NULL;
}

void ITransport::Free(ITransport* itrans) {
  Transport* trans = static_cast<Transport*>(itrans);
  delete trans;
}

}  // namespace port

<commit_msg>Commit for groby: http://codereview.chromium.org/9116030/ BUG=none TEST=none Review URL: http://codereview.chromium.org/9212014<commit_after>/*
 * Copyright (c) 2012 The Native Client Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifdef _WIN32
#include <windows.h>
#ifndef AF_IPX
#include <winsock2.h>
#endif
#define SOCKET_HANDLE SOCKET
#else

#include <arpa/inet.h>
#include <netdb.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>

#define SOCKET_HANDLE int
#define closesocket close
#endif

#include <stdlib.h>
#include <string>

#include "native_client/src/trusted/gdb_rsp/util.h"
#include "native_client/src/trusted/port/platform.h"
#include "native_client/src/trusted/port/transport.h"

using gdb_rsp::stringvec;
using gdb_rsp::StringSplit;

namespace port {

typedef int socklen_t;

class Transport : public ITransport {
 public:
  Transport() {
    handle_ = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  }

  explicit Transport(SOCKET_HANDLE s) {
    handle_ = s;
  }

  ~Transport() {
    if (handle_ != -1) closesocket(handle_);
  }

  // Read from this transport, return a negative value if there is an error
  // otherwise return the number of bytes actually read.
  virtual int32_t Read(void *ptr, int32_t len) {
    return ::recv(handle_, reinterpret_cast<char *>(ptr), len, 0);
  }

  // Write to this transport, return a negative value if there is an error
  // otherwise return the number of bytes actually written.
  virtual int32_t Write(const void *ptr, int32_t len) {
    return ::send(handle_, reinterpret_cast<const char *>(ptr), len, 0);
  }

  // Return true if data becomes availible or false after ms milliseconds.
  virtual bool ReadWaitWithTimeout(uint32_t ms = 0) {
    fd_set fds;

    FD_ZERO(&fds);
    FD_SET(handle_, &fds);

    // We want a "non-blocking" check
    struct timeval timeout;
    timeout.tv_sec = 0;
    timeout.tv_usec= ms * 1000;

    // Check if this file handle can select on read
    int cnt = select(static_cast<int>(handle_) + 1, &fds, 0, 0, &timeout);

    // If we are ready, or if there is an error.  We return true
    // on error, to "timeout" and let the next IO request fail.
    if (cnt != 0) return true;

    return false;
  }

// On windows, the header that defines this has other definition
// colitions, so we define it outselves just in case
#ifndef SD_BOTH
#define SD_BOTH 2
#endif

  virtual void Disconnect() {
    // Shutdown the conneciton in both diections.  This should
    // always succeed, and nothing we can do if this fails.
    (void) ::shutdown(handle_, SD_BOTH);
  }

 protected:
  SOCKET_HANDLE handle_;
};

// Convert string in the form of [addr][:port] where addr is a
// IPv4 address or host name, and port is a 16b tcp/udp port.
// Both portions are optional, and only the portion of the address
// provided is updated.  Values are provided in network order.
static bool StringToIPv4(const std::string &instr, uint32_t *addr,
                         uint16_t *port) {
  // Make a copy so the are unchanged unless we succeed
  uint32_t outaddr = *addr;
  uint16_t outport = *port;

  // Substrings of the full ADDR:PORT
  std::string addrstr;
  std::string portstr;

  // We should either have one or two tokens in the form of:
  //  IP - IP, NUL
  //  IP: -  IP, NUL
  //  :PORT - NUL, PORT
  //  IP:PORT - IP, PORT

  // Search for the port marker
  size_t portoff = instr.find(':');

  // If we found a ":" before the end, get both substrings
  if ((portoff != std::string::npos) && (portoff + 1 < instr.size())) {
    addrstr = instr.substr(0, portoff);
    portstr = instr.substr(portoff + 1, std::string::npos);
  } else {
    // otherwise the entire string is the addr portion.
    addrstr = instr;
    portstr = "";
  }

  // If the address portion was provided, update it
  if (addrstr.size()) {
    // Special case 0.0.0.0 which means any IPv4 interface
    if (addrstr == "0.0.0.0") {
      outaddr = 0;
    } else {
      struct hostent *host = gethostbyname(addrstr.data());

      // Check that we found an IPv4 host
      if ((NULL == host) || (AF_INET != host->h_addrtype))  return false;

      // Make sure the IP list isn't empty.
      if (0 == host->h_addr_list[0]) return false;

      // Use the first address in the array of address pointers.
      uint32_t **addrarray = reinterpret_cast<uint32_t**>(host->h_addr_list);
      outaddr = *addrarray[0];
    }
  }

  // if the port portion was provided, then update it
  if (portstr.size()) {
    int val = atoi(portstr.data());
    if ((val < 0) || (val > 65535)) return false;
    outport = ntohs(static_cast<uint16_t>(val));
  }

  // We haven't failed, so set the values
  *addr = outaddr;
  *port = outport;
  return true;
}

static SOCKET_HANDLE s_ServerSock;

static bool SocketInit() {
  s_ServerSock = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  if (s_ServerSock == -1) {
    IPlatform::LogError("Failed to create socket.\n");
    return false;
  }

  return true;
}

static bool SocketsAvailable() {
  static bool _init = SocketInit();
  return _init;
}

static bool BuildSockAddr(const char *addr, struct sockaddr_in *sockaddr) {
  std::string addrstr = addr;
  uint32_t *pip = reinterpret_cast<uint32_t*>(&sockaddr->sin_addr.s_addr);
  uint16_t *pport = reinterpret_cast<uint16_t*>(&sockaddr->sin_port);

  sockaddr->sin_family = AF_INET;
  return StringToIPv4(addrstr, pip, pport);
}

ITransport* ITransport::Connect(const char *addr) {
  if (!SocketsAvailable()) return NULL;

  SOCKET_HANDLE s = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  if (s == -1) {
    IPlatform::LogError("Failed to create connection socket.\n");
    return NULL;
  }

  struct sockaddr_in saddr;
  saddr.sin_family = AF_INET;
  saddr.sin_addr.s_addr = htonl(0x7F000001);
  saddr.sin_port = htons(4014);

  // Override portions address that are provided
  if (addr) BuildSockAddr(addr, &saddr);

  if (::connect(s, reinterpret_cast<sockaddr*>(&saddr), sizeof(saddr)) != 0) {
    closesocket(s);
    IPlatform::LogError("Failed to connect.\n");
    return NULL;
  }

  return new Transport(s);
}

ITransport* ITransport::Accept(const char *addr) {
  static bool listening = false;
  if (!SocketsAvailable()) return NULL;

  if (!listening) {
    struct sockaddr_in saddr;
    socklen_t addrlen = static_cast<socklen_t>(sizeof(saddr));
    saddr.sin_family = AF_INET;
    saddr.sin_addr.s_addr = htonl(0x7F000001);
    saddr.sin_port = htons(4014);

    // Override portions address that are provided
    if (addr) BuildSockAddr(addr, &saddr);

    // This is necessary to ensure that the TCP port is released
    // promptly when sel_ldr exits.  Without this, the TCP port might
    // only be released after a timeout, and later processes can fail
    // to bind it.
    int reuse_address = 1;
    setsockopt(s_ServerSock, SOL_SOCKET, SO_REUSEADDR,
               reinterpret_cast<char *>(&reuse_address),
               sizeof(reuse_address));

    struct sockaddr *psaddr = reinterpret_cast<struct sockaddr *>(&saddr);
    if (bind(s_ServerSock, psaddr, addrlen)) {
      IPlatform::LogError("Failed to bind server.\n");
      return NULL;
    }

    if (listen(s_ServerSock, 1)) {
      IPlatform::LogError("Failed to listen.\n");
      return NULL;
    }

    listening = true;
  }

  if (listening) {
    SOCKET_HANDLE s = ::accept(s_ServerSock, NULL, 0);
    if (-1 != s) return new Transport(s);
    return NULL;
  }

  return NULL;
}

void ITransport::Free(ITransport* itrans) {
  Transport* trans = static_cast<Transport*>(itrans);
  delete trans;
}

}  // namespace port
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2015, 2016, 2017, 2018, 2019, 2020, Intel Corporation
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in
 *       the documentation and/or other materials provided with the
 *       distribution.
 *
 *     * Neither the name of Intel Corporation nor the names of its
 *       contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY LOG OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <limits.h>
#include <math.h>

#include <iostream>

#include "geopm_agent.h"
#include "geopm_error.h"
#include "geopm_hash.h"
#include "OptionParser.hpp"

#include "config.h"

enum geopmagent_const {
    GEOPMAGENT_STRING_LENGTH = 512,
    GEOPMAGENT_DOUBLE_LENGTH = 100,
};

int main(int argc, char **argv)
{
    geopm::OptionParser parser{"geopmagent", std::cout, std::cerr, ""};
    parser.add_option("agent", 'a', "agent", "", "specify the name of the agent");
    parser.add_option("policy", 'p', "policy", "",
                      "values to be set for each policy in a comma-separated list");
    parser.add_example_usage("");
    parser.add_example_usage("[-a AGENT] [-p POLICY0,POLICY1,...]");
    bool early_exit = parser.parse(argc, argv);
    if (early_exit) {
        return 0;
    }

    int err = 0;
    auto pos_args = parser.get_positional_args();
    if (pos_args.size() > 0) {
        std::cerr << "Error: The following positional argument(s) are in error:" << std::endl;
        for (const std::string &arg : pos_args) {
            std::cerr << arg << std::endl;
        }
        err = EINVAL;
    }

    int output_num;
    double policy_vals[GEOPMAGENT_DOUBLE_LENGTH] = {0};
    char error_str[GEOPMAGENT_STRING_LENGTH] = {0};
    char policy_vals_str[GEOPMAGENT_STRING_LENGTH] = {0};
    char output_str[NAME_MAX * GEOPMAGENT_DOUBLE_LENGTH];
    const char *agent_ptr = NULL;
    char *policy_vals_ptr = NULL;

    try {
        std::string agent = parser.get_value("agent");
        if (agent != "") {
            agent_ptr = agent.c_str();
        }
        std::string policy = parser.get_value("policy");
        if (parser.get_value("policy") != "") {
            strncpy(policy_vals_str, policy.c_str(), GEOPMAGENT_STRING_LENGTH - 1);
            policy_vals_ptr = policy_vals_str;
        }
    }
    catch (...)
    {
        err = geopm::exception_handler(std::current_exception(), false);
    }

    if (!err && argc == 1) {
        err = geopm_agent_num_avail(&output_num);
        if (!err) {
            for(int i = 0; !err && i < output_num; ++i) {
                err = geopm_agent_name(i, sizeof(output_str), output_str);
                if (!err) {
                    printf("%s\n", output_str);
                }
            }
        }
    }
    else if (!err && agent_ptr != NULL && policy_vals_ptr == NULL) {
        err = geopm_agent_supported(agent_ptr);

        // Policies
        if (!err) {
            err = geopm_agent_num_policy(agent_ptr, &output_num);
        }

        if (!err) {
            printf("Policy: ");
            for (int i = 0; !err && i < output_num; ++i) {
                err = geopm_agent_policy_name(agent_ptr, i, sizeof(output_str), output_str);
                if (!err) {
                    if (i > 0) {
                        printf(",");
                    }
                    printf("%s", output_str);
                }
            }
            if (!err && output_num == 0) {
                printf("(none)\n");
            }
            else {
                printf("\n");
            }
        }

        // Samples
        if (!err) {
            err = geopm_agent_num_sample(agent_ptr, &output_num);
        }

        if (!err) {
            printf("Sample: ");
            for (int i = 0; !err && i < output_num; ++i) {
                err = geopm_agent_sample_name(agent_ptr, i, sizeof(output_str), output_str);
                if (!err) {
                    if (i > 0) {
                        printf(",");
                    }
                    printf("%s", output_str);
                }
            }
            if (!err && output_num == 0) {
                printf("(none)\n");
            }
            else {
                printf("\n");
            }
        }
    }
    else if (!err) {

        if (agent_ptr == NULL) {
            fprintf(stderr, "Error: Agent (-a) must be specified to create a policy.\n");
            err = EINVAL;
        }

        int num_policy = 0;
        if (!err) {
            err = geopm_agent_num_policy(agent_ptr, &num_policy);
        }

        int policy_count = 0;
        if (!err) {
            if (num_policy) {
                char *tok = strtok(policy_vals_ptr, ",");
                char *endptr = NULL;
                while (!err && tok != NULL) {
                    policy_vals[policy_count] = strtod(tok, &endptr);
                    if (tok == endptr) {
                        policy_vals[policy_count] = geopm_crc32_str(tok);
                    }
                    ++policy_count;
                    if (policy_count > GEOPMAGENT_DOUBLE_LENGTH) {
                        err = E2BIG;
                    }
                    tok = strtok(NULL, ",");
                }
                if (!err && policy_count > num_policy) {
                    fprintf(stderr, "Error: Number of policies read from command line is greater than expected for agent.\n");
                    err = EINVAL;
                }
            }
            else if (strncmp(policy_vals_ptr, "none", 4) != 0 &&
                     strncmp(policy_vals_ptr, "None", 4) != 0) {
                fprintf(stderr, "Error: Must specify \"None\" for the parameter option if agent takes no parameters.\n");
                err = EINVAL;
            }
        }
        if (!err) {
            err = geopm_agent_policy_json_partial(agent_ptr, policy_count, policy_vals,
                                                  sizeof(output_str), output_str);
            printf("%s\n", output_str);
        }
    }

    if (err) {
        geopm_error_message(err, error_str, GEOPMAGENT_STRING_LENGTH);
        fprintf(stderr, "Error: %s\n", error_str);
    }

    return err;
}
<commit_msg>Change geopmagent CLI policy parser to hash selectively<commit_after>/*
 * Copyright (c) 2015, 2016, 2017, 2018, 2019, 2020, Intel Corporation
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in
 *       the documentation and/or other materials provided with the
 *       distribution.
 *
 *     * Neither the name of Intel Corporation nor the names of its
 *       contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY LOG OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <limits.h>
#include <math.h>

#include <iostream>

#include "geopm_agent.h"
#include "geopm_error.h"
#include "geopm_hash.h"
#include "Agent.hpp"
#include "OptionParser.hpp"

#include "config.h"

enum geopmagent_const {
    GEOPMAGENT_STRING_LENGTH = 512,
    GEOPMAGENT_DOUBLE_LENGTH = 100,
};

int main(int argc, char **argv)
{
    geopm::OptionParser parser{"geopmagent", std::cout, std::cerr, ""};
    parser.add_option("agent", 'a', "agent", "", "specify the name of the agent");
    parser.add_option("policy", 'p', "policy", "",
                      "values to be set for each policy in a comma-separated list");
    parser.add_example_usage("");
    parser.add_example_usage("[-a AGENT] [-p POLICY0,POLICY1,...]");
    bool early_exit = parser.parse(argc, argv);
    if (early_exit) {
        return 0;
    }

    int err = 0;
    auto pos_args = parser.get_positional_args();
    if (pos_args.size() > 0) {
        std::cerr << "Error: The following positional argument(s) are in error:" << std::endl;
        for (const std::string &arg : pos_args) {
            std::cerr << arg << std::endl;
        }
        err = EINVAL;
    }

    int output_num;
    double policy_vals[GEOPMAGENT_DOUBLE_LENGTH] = {0};
    char error_str[GEOPMAGENT_STRING_LENGTH] = {0};
    char policy_vals_str[GEOPMAGENT_STRING_LENGTH] = {0};
    char output_str[NAME_MAX * GEOPMAGENT_DOUBLE_LENGTH];
    const char *agent_ptr = NULL;
    char *policy_vals_ptr = NULL;

    try {
        std::string agent = parser.get_value("agent");
        if (agent != "") {
            agent_ptr = agent.c_str();
        }
        std::string policy = parser.get_value("policy");
        if (parser.get_value("policy") != "") {
            strncpy(policy_vals_str, policy.c_str(), GEOPMAGENT_STRING_LENGTH - 1);
            policy_vals_ptr = policy_vals_str;
        }
    }
    catch (...)
    {
        err = geopm::exception_handler(std::current_exception(), false);
    }

    if (!err && argc == 1) {
        err = geopm_agent_num_avail(&output_num);
        if (!err) {
            for(int i = 0; !err && i < output_num; ++i) {
                err = geopm_agent_name(i, sizeof(output_str), output_str);
                if (!err) {
                    printf("%s\n", output_str);
                }
            }
        }
    }
    else if (!err && agent_ptr != NULL && policy_vals_ptr == NULL) {
        err = geopm_agent_supported(agent_ptr);

        // Policies
        if (!err) {
            err = geopm_agent_num_policy(agent_ptr, &output_num);
        }

        if (!err) {
            printf("Policy: ");
            for (int i = 0; !err && i < output_num; ++i) {
                err = geopm_agent_policy_name(agent_ptr, i, sizeof(output_str), output_str);
                if (!err) {
                    if (i > 0) {
                        printf(",");
                    }
                    printf("%s", output_str);
                }
            }
            if (!err && output_num == 0) {
                printf("(none)\n");
            }
            else {
                printf("\n");
            }
        }

        // Samples
        if (!err) {
            err = geopm_agent_num_sample(agent_ptr, &output_num);
        }

        if (!err) {
            printf("Sample: ");
            for (int i = 0; !err && i < output_num; ++i) {
                err = geopm_agent_sample_name(agent_ptr, i, sizeof(output_str), output_str);
                if (!err) {
                    if (i > 0) {
                        printf(",");
                    }
                    printf("%s", output_str);
                }
            }
            if (!err && output_num == 0) {
                printf("(none)\n");
            }
            else {
                printf("\n");
            }
        }
    }
    else if (!err) {

        if (agent_ptr == NULL) {
            fprintf(stderr, "Error: Agent (-a) must be specified to create a policy.\n");
            err = EINVAL;
        }

        int num_policy = 0;
        if (!err) {
            err = geopm_agent_num_policy(agent_ptr, &num_policy);
        }

        int policy_count = 0;
        if (!err) {
            if (num_policy) {
                char *tok = strtok(policy_vals_ptr, ",");
                char *endptr = NULL;
                while (!err && tok != NULL) {
                    policy_vals[policy_count] = strtod(tok, &endptr);
                    if (tok == endptr) {
                        std::string policy_name = geopm::Agent::policy_names(agent_ptr).at(policy_count);
                        if (policy_name.find("HASH") != std::string::npos ||
                            policy_name.find("hash") != std::string::npos) {
                            policy_vals[policy_count] = geopm_crc32_str(tok);
                        }
                        else {
                            fprintf(stderr, "Error: %s is not a valid floating-point number; "
                                            "use \"NAN\" to indicate default.\n", tok);
                            err = EINVAL;
                        }
                    }
                    ++policy_count;
                    if (policy_count > GEOPMAGENT_DOUBLE_LENGTH) {
                        err = E2BIG;
                    }
                    tok = strtok(NULL, ",");
                }
                if (!err && policy_count > num_policy) {
                    fprintf(stderr, "Error: Number of policies read from command line is greater than expected for agent.\n");
                    err = EINVAL;
                }
            }
            else if (strncmp(policy_vals_ptr, "none", 4) != 0 &&
                     strncmp(policy_vals_ptr, "None", 4) != 0) {
                fprintf(stderr, "Error: Must specify \"None\" for the parameter option if agent takes no parameters.\n");
                err = EINVAL;
            }
        }
        if (!err) {
            err = geopm_agent_policy_json_partial(agent_ptr, policy_count, policy_vals,
                                                  sizeof(output_str), output_str);
            printf("%s\n", output_str);
        }
    }

    if (err) {
        geopm_error_message(err, error_str, GEOPMAGENT_STRING_LENGTH);
        fprintf(stderr, "Error: %s\n", error_str);
    }

    return err;
}
<|endoftext|>


<commit_before>/*
 * 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
 *
 * 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.
 */
#if !defined(XALANUTF16WRITER_HEADER_GUARD_1357924680)
#define XALANUTF16WRITER_HEADER_GUARD_1357924680

#include <xalanc/XMLSupport/XalanFormatterWriter.hpp>

XALAN_CPP_NAMESPACE_BEGIN

class XalanUTF16Writer : public XalanFormatterWriter
{
public:

    typedef XalanDOMChar    value_type;

    XalanUTF16Writer(
                Writer&         writer,
                MemoryManager&  theMemoryManager);

    virtual
    ~XalanUTF16Writer()
    {
    }

    /**
     * Output a line break.
     */
    void
    outputNewline()
    {
        assert(m_newlineString != 0);
        assert(length(m_newlineString) == m_newlineStringLength);

        write(
            m_newlineString,
            m_newlineStringLength);
    }

    size_type
    writeCDATAChar(
                const XalanDOMChar  chars[],
                size_type           start,
                size_type           /*length*/,
                bool&               /* outsideCDATA */)
    {
        assert( chars != 0 );

        write(chars[start]);

        return start;
    }

    /**
     * Writes name chars , if not presentable, throws
     */
    void writeNameChar(const XalanDOMChar*            data,
                       size_type                theLength)
    {
        write(data, theLength);
    }

    /**
     * Writes name chars , if not presentable, throws
     */
    void writePIChars(const XalanDOMChar*       data,
                        size_type               theLength)
    {
        write(data, theLength);
    }

    /**
     * Writes name chars , if not presentable, throws
     */
    void writeCommentChars(const XalanDOMChar*      data,
                           size_type                theLength)
    {
        write(data, theLength);
    }

    void
    safeWriteContent(
            const XalanDOMChar*     theChars,
            size_type               theLength)
    {
        write(theChars, theLength);
    }

    void
    write(
            const value_type*   theChars,
            size_type           theLength)
    {
        if (theLength > sizeof(m_buffer))
        {
            flushBuffer();

            m_writer.write(theChars, 0, theLength);
        }
        else
        {
            if (m_bufferRemaining < theLength)
            {
                flushBuffer();
            }

            for(size_type i = 0; i < theLength; ++i)
            {
                *m_bufferPosition = theChars[i];

                ++m_bufferPosition;
            }

            m_bufferRemaining -= theLength;
        }

    }

    void
    write(const XalanDOMString&     theChars)
    {
        write(theChars.c_str(), theChars.length());
    }

    void
    write(value_type    theChar)
    {

        if (m_bufferRemaining == 0)
        {
            flushBuffer();
        }

        *m_bufferPosition = theChar;

        ++m_bufferPosition;
        --m_bufferRemaining;
    }

    size_type
    write(
            const value_type    chars[],
            size_type           start,
            size_type           /*length*/)
    {
        write(chars[start]);

        return start;
    }

    void
    writeSafe(
            const XalanDOMChar*     theChars,
            size_type               theLength)
    {
        write(theChars, theLength);
    }

    void
    write(const value_type* theChars)
    {
        write(theChars, XalanDOMString::length(theChars));
    }

    void
    flushBuffer()
    {
        m_writer.write(
            reinterpret_cast<const char*>(m_buffer),
            0,
            (m_bufferPosition - m_buffer) * sizeof m_buffer[0]);

        m_bufferPosition = m_buffer;
        m_bufferRemaining = kBufferSize;
    }

private:

    enum
    {
        kBufferSize = 512       // The size of the buffer
    };

    // Data members...
    value_type      m_buffer[kBufferSize];

    value_type*     m_bufferPosition;

    size_type       m_bufferRemaining;
};

XALAN_CPP_NAMESPACE_END

#endif  // XALANUTF16WRITER_HEADER_GUARD_1357924680
<commit_msg>Patch for Jira issue XALANC-630.<commit_after>/*
 * 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
 *
 * 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.
 */
#if !defined(XALANUTF16WRITER_HEADER_GUARD_1357924680)
#define XALANUTF16WRITER_HEADER_GUARD_1357924680

#include <xalanc/XMLSupport/XalanFormatterWriter.hpp>

XALAN_CPP_NAMESPACE_BEGIN

class XalanUTF16Writer : public XalanFormatterWriter
{
public:

    typedef XalanDOMChar    value_type;

    XalanUTF16Writer(
                Writer&         writer,
                MemoryManager&  theMemoryManager);

    virtual
    ~XalanUTF16Writer()
    {
    }

    /**
     * Output a line break.
     */
    void
    outputNewline()
    {
        assert(m_newlineString != 0);
        assert(length(m_newlineString) == m_newlineStringLength);

        write(
            m_newlineString,
            m_newlineStringLength);
    }

    size_type
    writeCDATAChar(
                const XalanDOMChar  chars[],
                size_type           start,
                size_type           /*length*/,
                bool&               /* outsideCDATA */)
    {
        assert( chars != 0 );

        write(chars[start]);

        return start;
    }

    /**
     * Writes name chars , if not presentable, throws
     */
    void writeNameChar(const XalanDOMChar*            data,
                       size_type                theLength)
    {
        write(data, theLength);
    }

    /**
     * Writes name chars , if not presentable, throws
     */
    void writePIChars(const XalanDOMChar*       data,
                        size_type               theLength)
    {
        write(data, theLength);
    }

    /**
     * Writes name chars , if not presentable, throws
     */
    void writeCommentChars(const XalanDOMChar*      data,
                           size_type                theLength)
    {
        write(data, theLength);
    }

    void
    safeWriteContent(
            const XalanDOMChar*     theChars,
            size_type               theLength)
    {
        write(theChars, theLength);
    }

    void
    write(
            const value_type*   theChars,
            size_type           theLength)
    {
        if (theLength > sizeof(m_buffer))
        {
            flushBuffer();

            m_writer.write(theChars, 0, theLength);
        }
        else
        {
            if (m_bufferRemaining < theLength)
            {
                flushBuffer();
            }

            for(size_type i = 0; i < theLength; ++i)
            {
                *m_bufferPosition = theChars[i];

                ++m_bufferPosition;
            }

            m_bufferRemaining -= theLength;
        }

    }

    void
    write(const XalanDOMString&     theChars)
    {
        write(theChars.c_str(), theChars.length());
    }

    void
    write(value_type    theChar)
    {

        if (m_bufferRemaining == 0)
        {
            flushBuffer();
        }

        *m_bufferPosition = theChar;

        ++m_bufferPosition;
        --m_bufferRemaining;
    }

    size_type
    write(
            const value_type    chars[],
            size_type           start,
            size_type           /*length*/)
    {
        write(chars[start]);

        return start;
    }

    void
    writeSafe(
            const XalanDOMChar*     theChars,
            size_type               theLength)
    {
        write(theChars, theLength);
    }

    void
    write(const value_type* theChars)
    {
        write(theChars, XalanDOMString::length(theChars));
    }

    void
    flushBuffer()
    {
        m_writer.write(
            m_buffer,
            0,
            m_bufferPosition - m_buffer);

        m_bufferPosition = m_buffer;
        m_bufferRemaining = kBufferSize;
    }

private:

    enum
    {
        kBufferSize = 512       // The size of the buffer
    };

    // Data members...
    value_type      m_buffer[kBufferSize];

    value_type*     m_bufferPosition;

    size_type       m_bufferRemaining;
};

XALAN_CPP_NAMESPACE_END

#endif  // XALANUTF16WRITER_HEADER_GUARD_1357924680
<|endoftext|>


<commit_before>#ifndef STAN_MATH_PRIM_SCAL_ERR_CHECK_POSITIVE_HPP
#define STAN_MATH_PRIM_SCAL_ERR_CHECK_POSITIVE_HPP

#include <stan/math/prim/scal/err/domain_error.hpp>
#include <stan/math/prim/scal/err/domain_error_vec.hpp>
#include <stan/math/prim/scal/meta/value_type.hpp>
#include <stan/math/prim/scal/meta/length.hpp>
#include <stan/math/prim/scal/meta/get.hpp>
#include <stan/math/prim/scal/meta/is_vector_like.hpp>

namespace stan {
namespace math {

namespace {

template <typename T_y, bool is_vec>
struct positive {
  static void check(const char* function, const char* name, const T_y& y) {
    // have to use not is_unsigned. is_signed will be false
    // floating point types that have no unsigned versions.
    if (!std::is_unsigned<T_y>::value && !(y > 0))
      domain_error(function, name, y, "is ", ", but must be > 0!");
  }
};

template <typename T_y>
struct positive<T_y, true> {
  static void check(const char* function, const char* name, const T_y& y) {
    using stan::length;
    for (size_t n = 0; n < length(y); n++) {
      if (!std::is_unsigned<typename value_type<T_y>::type>::value
          && !(stan::get(y, n) > 0))
        domain_error_vec(function, name, y, n, "is ", ", but must be > 0!");
    }
  }
};

}  // namespace

/**
 * Check if y is positive.
 *
 * This function is vectorized and will check each element of
 * y.
 *
 * @tparam T_y Type of y
 *
 * @param function Function name (for error messages)
 * @param name Variable name (for error messages)
 * @param y Variable to check
 *
 * @throw domain_error if y is negative or zero or
 *   if any element of y is NaN.
 */
template <typename T_y>
inline void check_positive(const char* function, const char* name,
                           const T_y& y) {
  positive<T_y, is_vector_like<T_y>::value>::check(function, name, y);
}

}  // namespace math
}  // namespace stan
#endif
<commit_msg>replace is_unsigned<commit_after>#ifndef STAN_MATH_PRIM_SCAL_ERR_CHECK_POSITIVE_HPP
#define STAN_MATH_PRIM_SCAL_ERR_CHECK_POSITIVE_HPP

#include <stan/math/prim/scal/err/domain_error.hpp>
#include <stan/math/prim/scal/err/domain_error_vec.hpp>
#include <stan/math/prim/scal/meta/value_type.hpp>
#include <stan/math/prim/scal/meta/length.hpp>
#include <stan/math/prim/scal/meta/get.hpp>
#include <stan/math/prim/scal/meta/is_vector_like.hpp>

namespace stan {
namespace math {

namespace {

template <typename T_y, bool is_vec>
struct positive {
  static void check(const char* function, const char* name, const T_y& y) {
    // have to use not is_unsigned. is_signed will be false
    // floating point types that have no unsigned versions.
    if (std::is_signed<T_y>::value && !(y > 0))
      domain_error(function, name, y, "is ", ", but must be > 0!");
  }
};

template <typename T_y>
struct positive<T_y, true> {
  static void check(const char* function, const char* name, const T_y& y) {
    using stan::length;
    for (size_t n = 0; n < length(y); n++) {
      if (std::is_signed<typename value_type<T_y>::type>::value
          && !(stan::get(y, n) > 0))
        domain_error_vec(function, name, y, n, "is ", ", but must be > 0!");
    }
  }
};

}  // namespace

/**
 * Check if y is positive.
 *
 * This function is vectorized and will check each element of
 * y.
 *
 * @tparam T_y Type of y
 *
 * @param function Function name (for error messages)
 * @param name Variable name (for error messages)
 * @param y Variable to check
 *
 * @throw domain_error if y is negative or zero or
 *   if any element of y is NaN.
 */
template <typename T_y>
inline void check_positive(const char* function, const char* name,
                           const T_y& y) {
  positive<T_y, is_vector_like<T_y>::value>::check(function, name, y);
}

}  // namespace math
}  // namespace stan
#endif
<|endoftext|>


<commit_before>#ifndef STAN_MATH_PRIM_SCAL_FUNCTOR_REDUCE_SUM_HPP
#define STAN_MATH_PRIM_SCAL_FUNCTOR_REDUCE_SUM_HPP

#include <stan/math/prim/meta/return_type.hpp>
#include <stan/math/prim/mat/fun/typedefs.hpp>

#include <boost/iterator/counting_iterator.hpp>

#include <tbb/task_arena.h>
#include <tbb/parallel_reduce.h>
#include <tbb/blocked_range.h>

#include <iostream>
#include <iterator>
#include <vector>

namespace stan {
namespace math {

namespace internal {

// base definition => compile error
template <typename ReduceFunction, typename Enable = void, typename M, typename T, typename... Args>
struct reduce_sum_impl {};

// todo, double check if I need enable if here
template <typename ReduceFunction, typename M, typename T, typename... Args>
struct reduce_sum_impl<ReduceFunction, M, T, double, Args...> {
  using vmapped_t = std::vector<M>;
  using arg1_t = std::vector<Arg1>;
  using arg2_t = std::vector<Arg2>;
  using arg3_t = std::vector<Arg3>;
  using arg4_t = std::vector<Arg4>;
  std::tuple<std::vector<Args>...> arg_;
  const vmapped_t& vmapped_;
  const arg1_t& arg1_;
  const arg2_t& arg2_;
  const arg3_t& arg3_;
  const arg4_t& arg4_;
  T terms_sum_;

  // todo(Steve): put back recursive reducer
    reduce_sum_impl(const vmapped_t& vmapped, const T& init, Args&&... args)
        : vmapped_(vmapped),
          arg_(std::make_tuple(std::forward<Args>(args)...))
          terms_sum_(value_of(init)) {}

    reduce_sum_impl(reduce_sum_impl& other, tbb::split)
        : vmapped_(other.vmapped_),
        arg_(other.arg_),
        terms_sum_(0.0) {}

    void operator()(const tbb::blocked_range<size_t>& r) {
      if (r.empty()) {
        return;
      }

      auto start = vmapped_.begin();
      std::advance(start, r.begin());
      auto end = vmapped_.begin();
      std::advance(end, r.end());

      const vmapped_t sub_slice(start, end);

      terms_sum_ += ReduceFunction()(r.begin(), r.end() - 1, sub_slice, arg1_,
                                     arg2_, arg3_, arg4_);
    }

    void join(const reduce_sum_impl& child) {
      terms_sum_ += child.terms_sum_;
    }

  // Todo: Better name for this than operator(), collect()?
  template <typename... OtherArgs>
  T operator()(const vmapped_t& vmapped, T init, std::size_t grainsize,
               Args&&... args) const {
    const std::size_t num_jobs = vmapped.size();
    reduce_sum_impl<ReduceFunction, M, T, OtherArgs...> worker(vmapped, init, args...);
    tbb::parallel_reduce(
        tbb::blocked_range<std::size_t>(0, num_jobs, grainsize), worker);
    return std::move(worker.terms_sum_);
  }
};

}  // namespace internal

/*
 * Note that the ReduceFunction is only passed in as type to prohibit
 * that any internal state of the functor is causing trouble. Thus,
 * the functor must be default constructible without any arguments.
 */
template <typename ReduceFunction, typename M, typename T, typename... Args>
constexpr T reduce_sum(const std::vector<M>& vmapped, T init,
                       std::size_t grainsize, Args&&... args) {
  typedef T return_base_t;
  // void here but need to figure out enable_if stuff
  // We do this somewhere in the opencl code
  return internal::reduce_sum_impl<ReduceFunction, M, T, void, Args...>()(
    vmapped, init, grainsize, std::forward<Args>(args)...);
}

}  // namespace math
}  // namespace stan

#endif
<commit_msg>start cleanup bits of the reduce_sum code. Mostly to get an idea of what I want it to look like<commit_after>#ifndef STAN_MATH_PRIM_SCAL_FUNCTOR_REDUCE_SUM_HPP
#define STAN_MATH_PRIM_SCAL_FUNCTOR_REDUCE_SUM_HPP

#include <stan/math/prim/meta/return_type.hpp>
#include <stan/math/prim/mat/fun/typedefs.hpp>

#include <boost/iterator/counting_iterator.hpp>

#include <tbb/task_arena.h>
#include <tbb/parallel_reduce.h>
#include <tbb/blocked_range.h>

#include <iostream>
#include <iterator>
#include <vector>

namespace stan {
namespace math {

namespace internal {

// base definition => compile error
template <typename ReduceFunction, typename Enable = void, typename M, typename T, typename... Args>
struct reduce_sum_impl {};

// todo, double check if I need enable if here
template <typename ReduceFunction, typename M, typename T, typename... Args>
struct reduce_sum_impl<ReduceFunction, require_arithmetic_t<T>, M, T, Args...> {
  using vmapped_t = std::vector<M>;
  using arg1_t = std::vector<Arg1>;
  using arg2_t = std::vector<Arg2>;
  using arg3_t = std::vector<Arg3>;
  using arg4_t = std::vector<Arg4>;
  // todo(Steve): Need helper funcs for manipulating / iterating tuples
  std::tuple<std::vector<Args>...> arg_;
  const vmapped_t& vmapped_;
  const arg1_t& arg1_;
  const arg2_t& arg2_;
  const arg3_t& arg3_;
  const arg4_t& arg4_;
  T terms_sum_;

  // todo(Steve): put back recursive reducer
    reduce_sum_impl(const vmapped_t& vmapped, const T& init, Args&&... args)
        : vmapped_(vmapped),
          arg_(std::make_tuple(std::forward<Args>(args)...))
          terms_sum_(value_of(init)) {}

    reduce_sum_impl(reduce_sum_impl& other, tbb::split)
        : vmapped_(other.vmapped_),
        arg_(other.arg_),
        terms_sum_(0.0) {}

    void operator()(const tbb::blocked_range<size_t>& r) {
      if (r.empty()) {
        return;
      }

      auto start = vmapped_.begin();
      std::advance(start, r.begin());
      auto end = vmapped_.begin();
      std::advance(end, r.end());

      const vmapped_t sub_slice(start, end);

      terms_sum_ += ReduceFunction()(r.begin(), r.end() - 1, sub_slice, arg1_,
                                     arg2_, arg3_, arg4_);
    }

    void join(const reduce_sum_impl& child) {
      terms_sum_ += child.terms_sum_;
    }

  // Todo: Better name for this than operator(), collect()?
  template <typename... OtherArgs>
  T operator()(const vmapped_t& vmapped, T init, std::size_t grainsize,
               Args&&... args) const {
    const std::size_t num_jobs = vmapped.size();
    reduce_sum_impl<ReduceFunction, M, T, OtherArgs...> worker(vmapped, init, args...);
    tbb::parallel_reduce(
        tbb::blocked_range<std::size_t>(0, num_jobs, grainsize), worker);
    return std::move(worker.terms_sum_);
  }
};

}  // namespace internal

/*
 * Note that the ReduceFunction is only passed in as type to prohibit
 * that any internal state of the functor is causing trouble. Thus,
 * the functor must be default constructible without any arguments.
 */
template <typename ReduceFunction, typename M, typename T, typename... Args>
constexpr T reduce_sum(const std::vector<M>& vmapped, T init,
                       std::size_t grainsize, Args&&... args) {
  typedef T return_base_t;
  // void here but need to figure out enable_if stuff
  // We do this somewhere in the opencl code
  return internal::reduce_sum_impl<ReduceFunction, M, T, void, Args...>()(
    vmapped, init, grainsize, std::forward<Args>(args)...);
}

}  // namespace math
}  // namespace stan

#endif
<|endoftext|>


<commit_before>/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved.

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

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

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

#include "paddle/fluid/framework/operator.h"
#include "paddle/fluid/platform/cpu_helper.h"
#include "paddle/fluid/platform/cpu_info.h"
#include "paddle/fluid/platform/device_context.h"
#include "paddle/fluid/platform/init.h"
#include "paddle/fluid/platform/place.h"
#include "paddle/fluid/string/piece.h"

DEFINE_int32(paddle_num_threads, 1,
             "Number of threads for each paddle instance.");

namespace paddle {
namespace framework {

std::once_flag gflags_init_flag;
std::once_flag p2p_init_flag;

void InitGflags(std::vector<std::string> argv) {
  std::call_once(gflags_init_flag, [&]() {
    argv.insert(argv.begin(), "dummy");
    int argc = argv.size();
    char **arr = new char *[argv.size()];
    std::string line;
    for (size_t i = 0; i < argv.size(); i++) {
      arr[i] = &argv[i][0];
      line += argv[i];
      line += ' ';
    }
    google::ParseCommandLineFlags(&argc, &arr, true);
    VLOG(1) << "Init commandline: " << line;
  });
}

void InitP2P(std::vector<int> devices) {
#ifdef PADDLE_WITH_CUDA
  std::call_once(p2p_init_flag, [&]() {
    int count = devices.size();
    for (int i = 0; i < count; ++i) {
      for (int j = 0; j < count; ++j) {
        if (devices[i] == devices[j]) continue;
        int can_acess = -1;
        PADDLE_ENFORCE(
            cudaDeviceCanAccessPeer(&can_acess, devices[i], devices[j]),
            "Failed to test P2P access.");
        if (can_acess != 1) {
          LOG(WARNING) << "Cannot enable P2P access from " << devices[i]
                       << " to " << devices[j];
        } else {
          cudaSetDevice(devices[i]);
          cudaDeviceEnablePeerAccess(devices[j], 0);
        }
      }
    }
  });
#endif
}

void InitDevices(bool init_p2p) {
  /*Init all available devices by default */
  std::vector<int> devices;
#ifdef PADDLE_WITH_CUDA
  try {
    int count = platform::GetCUDADeviceCount();
    for (int i = 0; i < count; ++i) {
      devices.push_back(i);
    }
  } catch (const std::exception &exp) {
    LOG(WARNING) << "Compiled with WITH_GPU, but no GPU found in runtime.";
  }
#endif
  InitDevices(init_p2p, devices);
}

void InitDevices(bool init_p2p, const std::vector<int> devices) {
  std::vector<platform::Place> places;
  int count = 0;
#ifdef PADDLE_WITH_CUDA
  try {
    count = platform::GetCUDADeviceCount();
  } catch (const std::exception &exp) {
    LOG(WARNING) << "Compiled with WITH_GPU, but no GPU found in runtime.";
  }
#endif

  for (size_t i = 0; i < devices.size(); ++i) {
    if (devices[i] >= count || devices[i] < 0) {
      LOG(WARNING) << "Invalid devices id.";
      continue;
    }
    places.emplace_back(platform::CUDAPlace(devices[i]));
  }
  if (init_p2p) {
    InitP2P(devices);
  }
  places.emplace_back(platform::CPUPlace());
  platform::DeviceContextPool::Init(places);
#ifndef PADDLE_WITH_MKLDNN
  platform::SetNumThreads(FLAGS_paddle_num_threads);
#endif

  if (platform::jit::MayIUse(platform::jit::avx512f)) {
#ifndef __AVX512F__
    LOG(WARNING) << "AVX512F is available, Please re-compile on local machine";
#endif
  }
  if (platform::jit::MayIUse(platform::jit::avx2)) {
#ifndef __AVX2__
    LOG(WARNING) << "AVX2 is available, Please re-compile on local machine";
#endif
  }
  if (platform::jit::MayIUse(platform::jit::avx)) {
#ifndef __AVX__
    LOG(WARNING) << "AVX is available, Please re-compile on local machine";
#endif
  }
}

void InitGLOG(const std::string &prog_name) {
  // glog will not hold the ARGV[0] inside.
  // Use strdup to alloc a new string.
  google::InitGoogleLogging(strdup(prog_name.c_str()));
  google::InstallFailureSignalHandler();
}

}  // namespace framework
}  // namespace paddle
<commit_msg>remove the warning log since do not have avx2, avx512 flags<commit_after>/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved.

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

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

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

#include "paddle/fluid/framework/operator.h"
#include "paddle/fluid/platform/cpu_helper.h"
#include "paddle/fluid/platform/cpu_info.h"
#include "paddle/fluid/platform/device_context.h"
#include "paddle/fluid/platform/init.h"
#include "paddle/fluid/platform/place.h"
#include "paddle/fluid/string/piece.h"

DEFINE_int32(paddle_num_threads, 1,
             "Number of threads for each paddle instance.");

namespace paddle {
namespace framework {

std::once_flag gflags_init_flag;
std::once_flag p2p_init_flag;

void InitGflags(std::vector<std::string> argv) {
  std::call_once(gflags_init_flag, [&]() {
    argv.insert(argv.begin(), "dummy");
    int argc = argv.size();
    char **arr = new char *[argv.size()];
    std::string line;
    for (size_t i = 0; i < argv.size(); i++) {
      arr[i] = &argv[i][0];
      line += argv[i];
      line += ' ';
    }
    google::ParseCommandLineFlags(&argc, &arr, true);
    VLOG(1) << "Init commandline: " << line;
  });
}

void InitP2P(std::vector<int> devices) {
#ifdef PADDLE_WITH_CUDA
  std::call_once(p2p_init_flag, [&]() {
    int count = devices.size();
    for (int i = 0; i < count; ++i) {
      for (int j = 0; j < count; ++j) {
        if (devices[i] == devices[j]) continue;
        int can_acess = -1;
        PADDLE_ENFORCE(
            cudaDeviceCanAccessPeer(&can_acess, devices[i], devices[j]),
            "Failed to test P2P access.");
        if (can_acess != 1) {
          LOG(WARNING) << "Cannot enable P2P access from " << devices[i]
                       << " to " << devices[j];
        } else {
          cudaSetDevice(devices[i]);
          cudaDeviceEnablePeerAccess(devices[j], 0);
        }
      }
    }
  });
#endif
}

void InitDevices(bool init_p2p) {
  /*Init all available devices by default */
  std::vector<int> devices;
#ifdef PADDLE_WITH_CUDA
  try {
    int count = platform::GetCUDADeviceCount();
    for (int i = 0; i < count; ++i) {
      devices.push_back(i);
    }
  } catch (const std::exception &exp) {
    LOG(WARNING) << "Compiled with WITH_GPU, but no GPU found in runtime.";
  }
#endif
  InitDevices(init_p2p, devices);
}

void InitDevices(bool init_p2p, const std::vector<int> devices) {
  std::vector<platform::Place> places;
  int count = 0;
#ifdef PADDLE_WITH_CUDA
  try {
    count = platform::GetCUDADeviceCount();
  } catch (const std::exception &exp) {
    LOG(WARNING) << "Compiled with WITH_GPU, but no GPU found in runtime.";
  }
#endif

  for (size_t i = 0; i < devices.size(); ++i) {
    if (devices[i] >= count || devices[i] < 0) {
      LOG(WARNING) << "Invalid devices id.";
      continue;
    }
    places.emplace_back(platform::CUDAPlace(devices[i]));
  }
  if (init_p2p) {
    InitP2P(devices);
  }
  places.emplace_back(platform::CPUPlace());
  platform::DeviceContextPool::Init(places);
#ifndef PADDLE_WITH_MKLDNN
  platform::SetNumThreads(FLAGS_paddle_num_threads);
#endif

  if (platform::jit::MayIUse(platform::jit::avx)) {
#ifndef __AVX__
    LOG(WARNING) << "AVX is available, Please re-compile on local machine";
#endif
  }
}

void InitGLOG(const std::string &prog_name) {
  // glog will not hold the ARGV[0] inside.
  // Use strdup to alloc a new string.
  google::InitGoogleLogging(strdup(prog_name.c_str()));
  google::InstallFailureSignalHandler();
}

}  // namespace framework
}  // namespace paddle
<|endoftext|>


<commit_before>// This file is for a basic string library so I do not have to use <cstring>

int getStringLength(char *str)
{
    int result= 0;

    for(int index = 0; str[index]; index++)
    {
        ++result;
    }
    return result;
}

// Utliity function
void clearTempStringsToNull(char *str)
{
    for(int index = 0; str[index] ; index++)
    {
        str[index] = 0;
    }
}

//TODO: make another compreString that is case insensitive
bool compareString(char *fString, char *sString) // first/second String
{
    int index = 0;
    bool result = false;

    while(fString[index])
    {
        if(fString[index] != sString[index])
        { break;}

        index++;
    }
    if (!sString[index])
    {
        result = true;

    }
    return result;
}

//NOTE(dustin): if you don't pass a placetoputcopiedstring then you will have to free the result
char* CopyString(char *strToCopy, char *placeToPutCopiedString=NULL)
{
    if(!placeToPutCopiedString)
    {
        char *result = (char*)calloc(getStringLength(strToCopy)+1, sizeof(char));

        for (int index = 0; strToCopy[index]; index++)
        {
            result[index] = strToCopy[index];
        }
        return result;
    }
    else
    {
        for (int index = 0; strToCopy[index]; index++)
        {
            placeToPutCopiedString[index] = strToCopy[index];
        }
        return placeToPutCopiedString; // if you check for a return, this make it not fail everytime
    }
}

//NOTE(Dustin): Enduser needs to free the resultstring
char* CatString(char *originString, char *strToCat, char *outputString=NULL)
{
    int originLength = getStringLength(originString);
    int catStrLength = getStringLength(strToCat);
    int outstringLength = (originLength + catStrLength);
    int catStrIndex = 0;

    if(!outputString)
    {
        char *result = ((char*)calloc(outstringLength+1, sizeof(char)));

        for(int index = 0; index < outstringLength; index++)
        {
            if(index < originLength)
            {
                result[index] = originString[index];
            }
            else
            {
                result[index] = strToCat[catStrIndex];
                catStrIndex++;
            }
        }
        return result;
    }
    else
    {
        for(int index = 0; index < outstringLength; index++)
        {
            if(index < originLength)
            {
                outputString[index] = originString[index];
            }
            else
            {
                outputString[index] =strToCat[catStrIndex];
                catStrLength++;
            }
        }
        return outputString; // if you check for a return, this  makes it not just fail
    }
}

// if no outputstring then calle has to free | if you don't give me a valid savePlace you get nothing back about where you were in the string/array
char* SplitString(char *inputString, char strDelim, char *savePlace, char *outputString=NULL)
{
    bool isParsingStringToDelim = true;
    int index = 0;
    int resultIndex = 0;

    if(inputString)
    {
        while (isParsingStringToDelim)
        {
            //TODO: make this take multiple possible delim characters
            if(inputString[index] == strDelim)
            {
                clearTempStringsToNull(savePlace);
                isParsingStringToDelim = false;
                index++;

                if (savePlace)
                {
                    for(int localIndex = 0; inputString[index]; localIndex++)
                    {
                        savePlace[localIndex] = inputString[index];
                        index++;
                    }
                }
            }
            else
            {
                if (inputString[index])
                {
                    resultIndex++;
                    index++;
                }
                else
                {
                    break;
                }
            }
        }

        if(resultIndex)
        {
            if(!outputString)
            {
                char *result = ((char*)calloc(resultIndex+1, sizeof(char)));

                for(int localIndex = 0; localIndex < resultIndex; localIndex++)
                {
                    result[localIndex] = inputString[localIndex];
                }

                return result;
            }
            else
            {
                for(int localIndex = 0; localIndex < resultIndex; localIndex++)
                {
                    outputString[localIndex] = inputString[localIndex];
                }
                return outputString; // make sure if this is in a if that it doesnt fail all the time
            }
        }
    }

    return NULL;
}
<commit_msg>Delete cStringLib.cpp<commit_after><|endoftext|>


<commit_before>

#include "Math/RMinimizer.h"
#include "Math/IFunction.h"
#include <TVectorD.h>
#include "Math/BasicMinimizer.h"
//#include "Math/MultiNumGradFunction.h"

namespace ROOT {
   namespace Math{

      const ROOT::Math::IMultiGenFunction *gFunction;
      const ROOT::Math::IMultiGradFunction *gGradFunction;

      double minfunction(TVectorD x){
	return (*gFunction)(x.GetMatrixArray());
      }
      TVectorD mingradfunction(const double * y){
         double * z;
         gGradFunction->Gradient(y,z);
         return z;
      }

RMinimizer::RMinimizer(Option_t *method){
	fMethod=method;
        if (fMethod.empty() ) fMethod="BFGS";

}

void RMinimizer::SetFunction(const ROOT::Math::IMultiGenFunction & func) {
   // set the function to minimizer
   // need to calculate numerically the derivatives: do via class MultiNumGradFunction
   gFunction = &func;
   //ROOT::Math::MultiNumGradFunction gradFunc(func);
   // function is cloned inside so can be delete afterwards
   // called base class method setfunction
   // (note: write explicitly otherwise it will call back itself)
   BasicMinimizer::SetFunction(func);
}

//SetFunctions

bool RMinimizer::Minimize()   {

   (gFunction)= ObjFunction();
   (gGradFunction) = GradObjFunction();
/*
 *"Nelder-Mead", "BFGS", "CG", "L-BFGS-B", "SANN", "Brent" (Brent only for 1D minimization)
 */

//std::cout<<"Number of dimension ="<< NDim()  << std::endl;
//pass function to R
ROOT::R::TRInterface &r=gR->Instance();

r["minfunction"] = ROOT::R::TRFunction((minfunction));
r["gradFunc"] = ROOT::R::TRFunction((mingradfunction));

r["method"] = fMethod.c_str();
std::vector<double> stepSizes(StepSizes(), StepSizes()+NDim());
std::vector<double> values(X(), X()+NDim());

r["stepsizes"] = stepSizes;
r["initialparams"] = values;

//find minimum in R

TString cmd = TString::Format("result <- optim( initialparams, minfunction,method='%s',control = list(ndeps=stepsizes,maxit=%d,trace=%d,abstol=%e))",fMethod.c_str(),MaxIterations(),PrintLevel(),Tolerance());
//std::cout << "Calling R with command " << cmd << std::endl;

r.Parse(cmd.Data());
//get result from R
TVectorD  vector=r.ParseEval("result$par").ToVector<Double_t>();
const double *min=vector.GetMatrixArray();
//std::cout.precision(8);
//print results
//std::cout<<"-----------------------------------------"<<std::endl;
//std::cout<<"Minimum x="<<min[0]<<" y="<<min[1]<<std::endl;
SetFinalValues(min);
SetMinValue((*gFunction)(min));
//std::cout<<"Value at minimum ="<<MinValue()<<std::endl;

r.Parse("optimHess(result$par, minfunction, gradFunc)");
TString cmd2 = TString::Format("hresult <- optim( initialparams, minfunction,NULL, method='%s',hessian = TRUE, control = list(ndeps=stepsizes,maxit=%d,trace=%d,abstol=%e))",fMethod.c_str(),MaxIterations(),PrintLevel(),Tolerance());
r.Parse(cmd2.Data());
//getting the min calculated with the gradient
TVectorD  hmin=r.ParseEval("hresult$par").ToVector<Double_t>();

return kTRUE;
}
   }
}
<commit_msg>bug fixes<commit_after>

#include "Math/RMinimizer.h"
#include "Math/IFunction.h"
#include <TVectorD.h>
#include "Math/BasicMinimizer.h"
//#include "Math/MultiNumGradFunction.h"

namespace ROOT {
   namespace Math{

      const ROOT::Math::IMultiGenFunction *gFunction;
      const ROOT::Math::IMultiGradFunction *gGradFunction;

      double minfunction(TVectorD x){
	return (*gFunction)(x.GetMatrixArray());
      }
      TVectorD mingradfunction(const double * y){
         TVectorD z;
         gGradFunction->Gradient(y,z);
         return z;
      }

RMinimizer::RMinimizer(Option_t *method){
	fMethod=method;
        if (fMethod.empty() ) fMethod="BFGS";

}

void RMinimizer::SetFunction(const ROOT::Math::IMultiGenFunction & func) {
   // set the function to minimizer
   // need to calculate numerically the derivatives: do via class MultiNumGradFunction
   gFunction = &func;
   //ROOT::Math::MultiNumGradFunction gradFunc(func);
   // function is cloned inside so can be delete afterwards
   // called base class method setfunction
   // (note: write explicitly otherwise it will call back itself)
   BasicMinimizer::SetFunction(func);
}

//SetFunctions

bool RMinimizer::Minimize()   {

   (gFunction)= ObjFunction();
   (gGradFunction) = GradObjFunction();
/*
 *"Nelder-Mead", "BFGS", "CG", "L-BFGS-B", "SANN", "Brent" (Brent only for 1D minimization)
 */

//std::cout<<"Number of dimension ="<< NDim()  << std::endl;
//pass function to R
ROOT::R::TRInterface &r=gR->Instance();

r["minfunction"] = ROOT::R::TRFunction((minfunction));
r["gradFunc"] = ROOT::R::TRFunction((mingradfunction));

r["method"] = fMethod.c_str();
std::vector<double> stepSizes(StepSizes(), StepSizes()+NDim());
std::vector<double> values(X(), X()+NDim());

r["stepsizes"] = stepSizes;
r["initialparams"] = values;

//find minimum in R

TString cmd = TString::Format("result <- optim( initialparams, minfunction,method='%s',control = list(ndeps=stepsizes,maxit=%d,trace=%d,abstol=%e))",fMethod.c_str(),MaxIterations(),PrintLevel(),Tolerance());
//std::cout << "Calling R with command " << cmd << std::endl;

r.Parse(cmd.Data());
//get result from R
TVectorD  vector=r.ParseEval("result$par").ToVector<Double_t>();
const double *min=vector.GetMatrixArray();
//std::cout.precision(8);
//print results
//std::cout<<"-----------------------------------------"<<std::endl;
//std::cout<<"Minimum x="<<min[0]<<" y="<<min[1]<<std::endl;
SetFinalValues(min);
SetMinValue((*gFunction)(min));
//std::cout<<"Value at minimum ="<<MinValue()<<std::endl;

r.Parse("optimHess(result$par, minfunction, gradFunc)");
TString cmd2 = TString::Format("hresult <- optim( initialparams, minfunction,NULL, method='%s',hessian = TRUE, control = list(ndeps=stepsizes,maxit=%d,trace=%d,abstol=%e))",fMethod.c_str(),MaxIterations(),PrintLevel(),Tolerance());
r.Parse(cmd2.Data());
//getting the min calculated with the gradient
TVectorD  hmin=r.ParseEval("hresult$par").ToVector<Double_t>();

return kTRUE;
}
   }
}
<|endoftext|>


<commit_before>#include "precompiled.h"
#include "engine/world/Room.h"
#include "engine/math/random.h"
#include "engine/math/AABB.h"

namespace engine {
namespace world {

	Room::Room(){
		//Initialize empty room
		roomType = ROOM_TYPE_EMPTY;

		Tile tempTile;
		tempTile.setType(TILE_VOID);

		for(int i = 0;i < (ROOM_WIDTH * ROOM_HEIGHT);++i){
			tiles[i] = tempTile;
		}
	}

	Tile* Room::getTile(const vec2 pos){
		return getTile(pos.x,pos.y);
	}

	Tile* Room::getTile(const int x,const int y){
		ASSERT_TILE_XY(x,y);

		return &tiles[(x * ROOM_HEIGHT) + y];
	}

	void Room::setTile(const vec2 pos,const Tile tile){
		setTile(pos.x,pos.y,tile);
	}

	void Room::setTile(const int x,const int y,const Tile tile){
		ASSERT_TILE_XY(x,y);
		tiles[(x * ROOM_HEIGHT) + y] = tile;
	}

	/*
	Tile* getVisual(const vec2 pos);
	Tile* getVisual(const int x,const int y);
	Tile* getVisualArray();

	void applyVisual(const vec2 pos);
	void applyVisual(const int x,const int y);
	*/

	/**
	 * Regenerate the room.
	 *
	 * Input: Reads roomType and builds on top of that.
	 */
	void Room::generate(){
		//Lets get the simple types out from the way first... air and water...

		Tile tempTile;

		switch(roomType){
		case ROOM_TYPE_EMPTY:
			//Loop trough all tiles and set them to void
			tempTile.setType(TILE_VOID);

			for(int i = 0;i < (ROOM_WIDTH * ROOM_HEIGHT);++i){
				tiles[i] = tempTile;
			}

			break;
		case ROOM_TYPE_WATER:
			tempTile.setType(TILE_WATER);

			for(int i = 0;i < (ROOM_WIDTH * ROOM_HEIGHT);++i){
				tiles[i] = tempTile;
			}

			break;
		case ROOM_TYPE_GROUND:
			tempTile.setType(TILE_GRASS);

			for(int i = 0;i < (ROOM_WIDTH * ROOM_HEIGHT);++i){
				tiles[i] = tempTile;
			}

			for(int i = 0;i < (ROOM_WIDTH * ROOM_HEIGHT);++i){
				if(randomRange(0,10) > 8){
					tiles[i] = Tile(TILE_TREE);
				}
			}

			break;
		case ROOM_TYPE_DUNGEON:
			generateDungeon();
			break;
		}
	}

	/**
	 * This room is generated to be a dungeon.
	 */
	void Room::generateDungeon() {
		std::vector<vec2> roomMarkers; //Markers to point out where are the rooms, used later on the generation.

		Tile tempTile(TILE_ROCK_FLOOR);

		//Fill with rocks
		for(int i = 0;i < (ROOM_WIDTH * ROOM_HEIGHT);++i){
			tiles[i] = Tile(TILE_SOLID_ROCK);
		}

		//Insert the random rooms
		int roomCount = randomRange(5,30);

		while(roomCount > 0){
			AABB room;
			//first size, then position, so we are sure it wont go over the limits
			room.size.x = randomRange(5,10);
			room.size.y = randomRange(4,10);

			room.pos.x = randomRange(1,(ROOM_WIDTH  - room.size.x - 1));  //One is to make sure the collision AABB doesn't go out of bounds.
			room.pos.y = randomRange(1,(ROOM_HEIGHT - room.size.y - 1));

			AABB roomCollision = room;

			//roomCollision is one larger than the room.
			--roomCollision.pos.x;
			--roomCollision.pos.y;
			++++roomCollision.size.x; //Double because --roomCollision moves it back
			++++roomCollision.size.y;

			//Only create room and tick the counter if the room is clear to be placed.
			if(AABBBlockCheck(roomCollision,false) == false){
				AABBSetTile(room,Tile(TILE_ROCK_FLOOR));
				/*
				roomMarkers.push_back(
					vec2(
						randomRange(room.pos.x, (room.pos.x + room.size.x - 1)) ,
						randomRange(room.pos.y, (room.pos.y + room.size.x - 1))
					));

				*/

				roomMarkers.push_back(room.pos);
			}
			--roomCount;
		}

		//Paths between the rooms
		int pathCount = randomRange(25,50);
		while (pathCount > 0) {
			//TODO: Add change of disconnected room.
			//Start from a marker, create a path until hits something

			vec2 pos = vec2(randomRange(0,ROOM_WIDTH - 1), randomRange(0,ROOM_HEIGHT -1));
			vec2 dir;
			dir.randomNSWE();
			int timer = -1;
			int miss = 0;

			for(;;){
				--timer;
				if(timer < 0){
					dir.randomNSWE();
					timer = randomRange(5,10);
				}

				if(miss > 5){
					//5 misses, stop pathing!
					break;
				}

				pos += dir;

				if(pos.x < 0 || pos.x > (ROOM_WIDTH - 1)|| pos.y < 0 || pos.y > (ROOM_HEIGHT - 1)){
					dir.randomNSWE();
					++miss;
					continue; //Hit a wall!
				}

				if(getTile(pos)->blocks == false){
					break; //Found non-blocking place, not going there!
				}

				setTile(pos,Tile(TILE_ROCK_FLOOR));
			}

			--pathCount;
		}

	}

	/**
	 * Returns direct access to the tile array, useful when raw access needed to the array.
	 */
	Tile* Room::getTileArray(){
		return tiles;
	}

	/**
	 * Prints the room layout to the cmd. Used for debugging.
	 */
	void Room::printLayout(){
		for(int y = 0;y < ROOM_HEIGHT;++y){
			for(int x = 0;x < ROOM_WIDTH;++x){
				printf("%c",getTile(x,y)->visual);
			}
			printf("\n");
		}
	}

	/**
	 *
	 * Checks if the block type is found.
	 */
	bool Room::AABBBlockCheck(AABB box,bool type){
		for(int x = box.pos.x; x < ( box.pos.x + box.size.x ); ++x){
			for(int y = box.pos.y; y < ( box.pos.y + box.size.y ); ++y){
				if (getTile(x,y)->blocks == type){
					return true;
				}
			}
		}

		return false;
	}

	/**
	 * Sets the AABB given to certain tile type.
	 */
	void Room::AABBSetTile(AABB area,Tile tile){
		for(int x = area.pos.x; x < ( area.pos.x + area.size.x ); ++x){
			for(int y = area.pos.y; y < ( area.pos.y + area.size.y ); ++y){
				setTile(x,y,tile);
			}
		}
	}

}
}
<commit_msg>Visual array helper functions should be set up.<commit_after>#include "precompiled.h"
#include "engine/world/Room.h"
#include "engine/math/random.h"
#include "engine/math/AABB.h"

namespace engine {
namespace world {

	Room::Room(){
		//Initialize empty room
		roomType = ROOM_TYPE_EMPTY;

		Tile tempTile;
		tempTile.setType(TILE_VOID);

		for(int i = 0;i < (ROOM_WIDTH * ROOM_HEIGHT);++i){
			tiles[i] = tempTile;
			visual[i] = tempTile;
		}
	}

	Tile* Room::getTile(const vec2 pos){
		return getTile(pos.x,pos.y);
	}

	/**
	 * Returns direct access to the tile array, useful when raw access needed to the array.
	 */
	Tile* Room::getTileArray(){
		return tiles;
	}

	Tile* Room::getTile(const int x,const int y){
		ASSERT_TILE_XY(x,y);

		return &tiles[(x * ROOM_HEIGHT) + y];
	}

	void Room::setTile(const vec2 pos,const Tile tile){
		setTile(pos.x,pos.y,tile);
	}

	void Room::setTile(const int x,const int y,const Tile tile){
		ASSERT_TILE_XY(x,y);
		tiles[(x * ROOM_HEIGHT) + y] = tile;
	}

	Tile* Room::getVisual(const vec2 pos){
		return getTile(pos.x, pos.y);
	}

	Tile* Room::getVisual(const int x,const int y){
		ASSERT_TILE_XY(x,y);
		return &visual[(x * ROOM_HEIGHT) + y];
	}

	Tile* Room::getVisualArray(){
		return visual;
	}

	void Room::applyVisual(const vec2 pos){
		applyVisual(pos.x, pos.y);
	}

	void Room::applyVisual(const int x,const int y){
		ASSERT_TILE_XY(x,y);

		visual[(x * ROOM_HEIGHT) + y] = tiles[(x * ROOM_HEIGHT) + y];
	}

	/**
	 * Regenerate the room.
	 *
	 * Input: Reads roomType and builds on top of that.
	 */
	void Room::generate(){
		//Lets get the simple types out from the way first... air and water...

		Tile tempTile;

		switch(roomType){
		case ROOM_TYPE_EMPTY:
			//Loop trough all tiles and set them to void
			tempTile.setType(TILE_VOID);

			for(int i = 0;i < (ROOM_WIDTH * ROOM_HEIGHT);++i){
				tiles[i] = tempTile;
			}

			break;
		case ROOM_TYPE_WATER:
			tempTile.setType(TILE_WATER);

			for(int i = 0;i < (ROOM_WIDTH * ROOM_HEIGHT);++i){
				tiles[i] = tempTile;
			}

			break;
		case ROOM_TYPE_GROUND:
			tempTile.setType(TILE_GRASS);

			for(int i = 0;i < (ROOM_WIDTH * ROOM_HEIGHT);++i){
				tiles[i] = tempTile;
			}

			for(int i = 0;i < (ROOM_WIDTH * ROOM_HEIGHT);++i){
				if(randomRange(0,10) > 8){
					tiles[i] = Tile(TILE_TREE);
				}
			}

			break;
		case ROOM_TYPE_DUNGEON:
			generateDungeon();
			break;
		}
	}

	/**
	 * This room is generated to be a dungeon.
	 */
	void Room::generateDungeon() {
		std::vector<vec2> roomMarkers; //Markers to point out where are the rooms, used later on the generation.

		Tile tempTile(TILE_ROCK_FLOOR);

		//Fill with rocks
		for(int i = 0;i < (ROOM_WIDTH * ROOM_HEIGHT);++i){
			tiles[i] = Tile(TILE_SOLID_ROCK);
		}

		//Insert the random rooms
		int roomCount = randomRange(5,30);

		while(roomCount > 0){
			AABB room;
			//first size, then position, so we are sure it wont go over the limits
			room.size.x = randomRange(5,10);
			room.size.y = randomRange(4,10);

			room.pos.x = randomRange(1,(ROOM_WIDTH  - room.size.x - 1));  //One is to make sure the collision AABB doesn't go out of bounds.
			room.pos.y = randomRange(1,(ROOM_HEIGHT - room.size.y - 1));

			AABB roomCollision = room;

			//roomCollision is one larger than the room.
			--roomCollision.pos.x;
			--roomCollision.pos.y;
			++++roomCollision.size.x; //Double because --roomCollision moves it back
			++++roomCollision.size.y;

			//Only create room and tick the counter if the room is clear to be placed.
			if(AABBBlockCheck(roomCollision,false) == false){
				AABBSetTile(room,Tile(TILE_ROCK_FLOOR));
				/*
				roomMarkers.push_back(
					vec2(
						randomRange(room.pos.x, (room.pos.x + room.size.x - 1)) ,
						randomRange(room.pos.y, (room.pos.y + room.size.x - 1))
					));

				*/

				roomMarkers.push_back(room.pos);
			}
			--roomCount;
		}

		//Paths between the rooms
		int pathCount = randomRange(25,50);
		while (pathCount > 0) {
			//TODO: Add change of disconnected room.
			//Start from a marker, create a path until hits something

			vec2 pos = vec2(randomRange(0,ROOM_WIDTH - 1), randomRange(0,ROOM_HEIGHT -1));
			vec2 dir;
			dir.randomNSWE();
			int timer = -1;
			int miss = 0;

			for(;;){
				--timer;
				if(timer < 0){
					dir.randomNSWE();
					timer = randomRange(5,10);
				}

				if(miss > 5){
					//5 misses, stop pathing!
					break;
				}

				pos += dir;

				if(pos.x < 0 || pos.x > (ROOM_WIDTH - 1)|| pos.y < 0 || pos.y > (ROOM_HEIGHT - 1)){
					dir.randomNSWE();
					++miss;
					continue; //Hit a wall!
				}

				if(getTile(pos)->blocks == false){
					break; //Found non-blocking place, not going there!
				}

				setTile(pos,Tile(TILE_ROCK_FLOOR));
			}

			--pathCount;
		}

	}

	/**
	 * Prints the room layout to the cmd. Used for debugging.
	 */
	void Room::printLayout(){
		for(int y = 0;y < ROOM_HEIGHT;++y){
			for(int x = 0;x < ROOM_WIDTH;++x){
				printf("%c",getTile(x,y)->visual);
			}
			printf("\n");
		}
	}

	/**
	 *
	 * Checks if the block type is found.
	 */
	bool Room::AABBBlockCheck(AABB box,bool type){
		for(int x = box.pos.x; x < ( box.pos.x + box.size.x ); ++x){
			for(int y = box.pos.y; y < ( box.pos.y + box.size.y ); ++y){
				if (getTile(x,y)->blocks == type){
					return true;
				}
			}
		}

		return false;
	}

	/**
	 * Sets the AABB given to certain tile type.
	 */
	void Room::AABBSetTile(AABB area,Tile tile){
		for(int x = area.pos.x; x < ( area.pos.x + area.size.x ); ++x){
			for(int y = area.pos.y; y < ( area.pos.y + area.size.y ); ++y){
				setTile(x,y,tile);
			}
		}
	}

}
}
<|endoftext|>


<commit_before>/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve.

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

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

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

#include "paddle/operators/gemm_conv2d_op.h"

namespace paddle {
namespace operators {

int outputSize(int input_size, int filter_size, int padding, int stride) {
  int output_size = (input_size - filter_size + 2 * padding) / stride + 1;
  return output_size;
}

class Conv2DOp : public framework::OperatorWithKernel {
 public:
  using framework::OperatorWithKernel::OperatorWithKernel;

 protected:
  void InferShape(const framework::InferShapeContext &ctx) const override {
    auto in = ctx.Input<Tensor>("Input");
    auto filter = ctx.Input<Tensor>("Filter");
    auto out = ctx.Output<framework::LoDTensor>("Output");
    std::vector<int> strides = Attr<std::vector<int>>("strides");
    std::vector<int> paddings = Attr<std::vector<int>>("paddings");
    int groups = Attr<int>("groups");
    int input_channels = in->dims()[1];
    int output_channels = filter->dims()[0];

    PADDLE_ENFORCE_EQ(in->dims().size(), 4, "Conv2DOp intput should be 4-D.");
    PADDLE_ENFORCE_EQ(filter->dims().size(), 4,
                      "Conv2DOp filter should be 4-D.");
    PADDLE_ENFORCE_EQ(input_channels, filter->dims()[1] * groups,
                      "The number of input channels should be equal to filter "
                      "channels * groups.");
    PADDLE_ENFORCE_EQ(
        output_channels % groups, 0,
        "The number of output channels should be divided by groups.");

    auto output_height =
        outputSize(in->dims()[2], filter->dims()[2], paddings[0], strides[0]);
    auto output_width =
        outputSize(in->dims()[3], filter->dims()[3], paddings[1], strides[1]);
    out->Resize(
        {in->dims()[0], filter->dims()[0], output_height, output_width});
  }
};

class Conv2DOpMaker : public framework::OpProtoAndCheckerMaker {
 public:
  Conv2DOpMaker(framework::OpProto *proto, framework::OpAttrChecker *op_checker)
      : OpProtoAndCheckerMaker(proto, op_checker) {
    AddInput(
        "Input",
        "The input tensor of convolution operator. "
        "The format of input tensor is NCHW. Where N is batch size, C is the "
        "number of channels, H and W is the height and width of image.");
    AddInput(
        "Filter",
        "The filter tensor of convolution operator."
        "The format of the filter tensor is MCHW, where M is the number of "
        "output image channels, C is the number of input image channels, "
        "H and W is height and width of filter. "
        "If the groups attribute is greater than 1, C equal the number of "
        "input image channels divided by the groups.");
    AddOutput("Output",
              "The output tensor of convolution operator."
              "The format of output tensor is also NCHW.");
    AddComment(R"DOC(
The convolution operation calculates the output based on the input, filter
and strides, paddings, groups parameters. The size of each dimension of the
parameters is checked in the infer-shape.
)DOC");
    AddAttr<std::vector<int>>("strides", "strides of convolution operator.");
    AddAttr<std::vector<int>>("paddings", "paddings of convolution operator.");
    AddAttr<int>(
        "groups",
        "group size of convolution operator. "
        "Refer to grouped convolution in Alex Krizhevsky's paper: "
        "when group=2, the first half of the filters are only connected to the "
        "first half of the input channels, and the second half only connected "
        "to the second half.")
        .SetDefault(1);
  }
};

class Conv2DOpGrad : public framework::OperatorWithKernel {
 public:
  using framework::OperatorWithKernel::OperatorWithKernel;

 protected:
  void InferShape(const framework::InferShapeContext &ctx) const override {
    auto in = ctx.Input<Tensor>("Input");
    auto filter = ctx.Input<Tensor>("Filter");
    auto d_in =
        ctx.Output<framework::LoDTensor>(framework::GradVarName("Input"));
    auto d_filter =
        ctx.Output<framework::LoDTensor>(framework::GradVarName("Filter"));
    d_in->Resize(in->dims());
    d_filter->Resize(filter->dims());
  }
};

}  // namespace operators
}  // namespace paddle

namespace ops = paddle::operators;
REGISTER_OP(conv2d, ops::Conv2DOp, ops::Conv2DOpMaker, conv2d_grad,
            ops::Conv2DOpGrad);

REGISTER_OP_CPU_KERNEL(
    conv2d, ops::GemmConv2DKernel<paddle::platform::CPUPlace, float>);
REGISTER_OP_CPU_KERNEL(
    conv2d_grad, ops::GemmConvGrad2DKernel<paddle::platform::CPUPlace, float>);
<commit_msg>Follow comments fix conv2d_op.cc<commit_after>/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve.

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

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

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

#include "paddle/operators/gemm_conv2d_op.h"

namespace paddle {
namespace operators {

int outputSize(int input_size, int filter_size, int padding, int stride) {
  int output_size = (input_size - filter_size + 2 * padding) / stride + 1;
  return output_size;
}

class Conv2DOp : public framework::OperatorWithKernel {
 public:
  using framework::OperatorWithKernel::OperatorWithKernel;

 protected:
  void InferShape(const framework::InferShapeContext &ctx) const override {
    auto in = ctx.Input<Tensor>("Input");
    auto filter = ctx.Input<Tensor>("Filter");
    auto out = ctx.Output<framework::LoDTensor>("Output");
    std::vector<int> strides = Attr<std::vector<int>>("strides");
    std::vector<int> paddings = Attr<std::vector<int>>("paddings");
    int groups = Attr<int>("groups");
    int input_channels = in->dims()[1];
    int output_channels = filter->dims()[0];

    PADDLE_ENFORCE_EQ(in->dims().size(), 4, "Conv2DOp input should be 4-D.");
    PADDLE_ENFORCE_EQ(filter->dims().size(), 4,
                      "Conv2DOp filter should be 4-D.");
    PADDLE_ENFORCE_EQ(input_channels, filter->dims()[1] * groups,
                      "The number of input channels should be equal to filter "
                      "channels * groups.");
    PADDLE_ENFORCE_EQ(
        output_channels % groups, 0,
        "The number of output channels should be divided by groups.");

    auto output_height =
        outputSize(in->dims()[2], filter->dims()[2], paddings[0], strides[0]);
    auto output_width =
        outputSize(in->dims()[3], filter->dims()[3], paddings[1], strides[1]);
    out->Resize(
        {in->dims()[0], filter->dims()[0], output_height, output_width});
  }
};

class Conv2DOpMaker : public framework::OpProtoAndCheckerMaker {
 public:
  Conv2DOpMaker(framework::OpProto *proto, framework::OpAttrChecker *op_checker)
      : OpProtoAndCheckerMaker(proto, op_checker) {
    AddInput(
        "Input",
        "The input tensor of convolution operator. "
        "The format of input tensor is NCHW. Where N is batch size, C is the "
        "number of channels, H and W is the height and width of image.");
    AddInput(
        "Filter",
        "The filter tensor of convolution operator."
        "The format of the filter tensor is MCHW, where M is the number of "
        "output image channels, C is the number of input image channels, "
        "H and W is height and width of filter. "
        "If the groups attribute is greater than 1, C equal the number of "
        "input image channels divided by the groups.");
    AddOutput("Output",
              "The output tensor of convolution operator."
              "The format of output tensor is also NCHW.");
    AddAttr<std::vector<int>>("strides", "strides of convolution operator.")
        .SetDefault({1, 1});
    AddAttr<std::vector<int>>("paddings", "paddings of convolution operator.")
        .SetDefault({0, 0});
    AddAttr<int>(
        "groups",
        "group size of convolution operator. "
        "Refer to grouped convolution in Alex Krizhevsky's paper: "
        "when group=2, the first half of the filters are only connected to the "
        "first half of the input channels, and the second half only connected "
        "to the second half.")
        .SetDefault(1);
    AddComment(R"DOC(
The convolution operation calculates the output based on the input, filter
and strides, paddings, groups parameters. The size of each dimension of the
parameters is checked in the infer-shape.
)DOC");
  }
};

class Conv2DOpGrad : public framework::OperatorWithKernel {
 public:
  using framework::OperatorWithKernel::OperatorWithKernel;

 protected:
  void InferShape(const framework::InferShapeContext &ctx) const override {
    auto in = ctx.Input<Tensor>("Input");
    auto filter = ctx.Input<Tensor>("Filter");
    auto d_in =
        ctx.Output<framework::LoDTensor>(framework::GradVarName("Input"));
    auto d_filter =
        ctx.Output<framework::LoDTensor>(framework::GradVarName("Filter"));
    d_in->Resize(in->dims());
    d_filter->Resize(filter->dims());
  }
};

}  // namespace operators
}  // namespace paddle

namespace ops = paddle::operators;
REGISTER_OP(conv2d, ops::Conv2DOp, ops::Conv2DOpMaker, conv2d_grad,
            ops::Conv2DOpGrad);

REGISTER_OP_CPU_KERNEL(
    conv2d, ops::GemmConv2DKernel<paddle::platform::CPUPlace, float>);
REGISTER_OP_CPU_KERNEL(
    conv2d_grad, ops::GemmConvGrad2DKernel<paddle::platform::CPUPlace, float>);
<|endoftext|>