<commit_before>#ifndef K3_RUNTIME_BUILTINS_H
#define K3_RUNTIME_BUILTINS_H

#include <ctime>
#include <chrono>
#include <climits>
#include <functional>

namespace K3 {
  //class Builtins: public __k3_context {
  //  public:

  //    Builtins() {
  //      // seed the random number generator
  //      std::srand(std::time(0));
  //    }

  //    int random(int x) { return std::rand(x); }

  //    double randomFraction(unit_t) { return (double)rand() / RAND_MAX; }

  //    <template t>
  //      int hash(t x) { return static_cast<int>std::hash<t>(x); }

  //    int truncate(double x) { return (int)x; }

  //    double real_of_int(int x) { return (double)x; }

  //    int get_max_int(unit_t x) { return INT_MAX; }
  //};

  F<F<F<unit_t(string)>(string)>(string)> openBuiltin =
    [] (string chan_id) {
      return [=] (string builtin_chan_id) {
        return [=] (string format) {
          engine.openBuiltin(chan_id, builtin_chan_id);
          return unit_t();
        };
      };
    };

  F<F<F<F<unit_t(string)>(string)>(string)>(string)> openFile =
    [] (string chan_id) {
      return [=] (string path) {
          return [=] (string fmt) {
              return [=] (string mode) {
                  IOMode iomode = engine.ioMode(mode);
                  engine.openFile(chan_id, path, iomode);
                  return unit_t();
              };
          };
      };
  };

  unit_t close(string chan_id) {
      engine.close(chan_id);
      return unit_t();
  }

  unit_t printLine(string message) {
    std::cout << message << endl;
    return unit_t();
  }

  string itos(int i) {
    return to_string(i);
  }

  unit_t haltEngine(unit_t) {
    engine.forceTerminateEngine();
    return unit_t();
  }

  // ms
  int now(unit_t) {
    auto t = std::chrono::system_clock::now();
    auto elapsed =std::chrono::duration_cast<std::chrono::milliseconds>(t.time_since_epoch());
    return elapsed.count();
  }
}
#endif /* K3_RUNTIME_BUILTINS_H */
<commit_msg>Add hacky file reading for C++<commit_after>#ifndef K3_RUNTIME_BUILTINS_H
#define K3_RUNTIME_BUILTINS_H

#include <ctime>
#include <chrono>
#include <climits>
#include <fstream>
#include <sstream>
#include <string>
#include <functional>

namespace K3 {
  //class Builtins: public __k3_context {
  //  public:

  //    Builtins() {
  //      // seed the random number generator
  //      std::srand(std::time(0));
  //    }

  //    int random(int x) { return std::rand(x); }

  //    double randomFraction(unit_t) { return (double)rand() / RAND_MAX; }

  //    <template t>
  //      int hash(t x) { return static_cast<int>std::hash<t>(x); }

  //    int truncate(double x) { return (int)x; }

  //    double real_of_int(int x) { return (double)x; }

  //    int get_max_int(unit_t x) { return INT_MAX; }
  //};

  F<F<F<unit_t(string)>(string)>(string)> openBuiltin =
    [] (string chan_id) {
      return [=] (string builtin_chan_id) {
        return [=] (string format) {
          engine.openBuiltin(chan_id, builtin_chan_id);
          return unit_t();
        };
      };
    };

  F<F<F<F<unit_t(string)>(string)>(string)>(string)> openFile =
    [] (string chan_id) {
      return [=] (string path) {
          return [=] (string fmt) {
              return [=] (string mode) {
                  IOMode iomode = engine.ioMode(mode);
                  engine.openFile(chan_id, path, iomode);
                  return unit_t();
              };
          };
      };
  };

  unit_t close(string chan_id) {
      engine.close(chan_id);
      return unit_t();
  }

  unit_t printLine(string message) {
    std::cout << message << endl;
    return unit_t();
  }

  string itos(int i) {
    return to_string(i);
  }

  unit_t haltEngine(unit_t) {
    engine.forceTerminateEngine();
    return unit_t();
  }

  // ms
  int now(unit_t) {
    auto t = std::chrono::system_clock::now();
    auto elapsed =std::chrono::duration_cast<std::chrono::milliseconds>(t.time_since_epoch());
    return elapsed.count();
  }

  template <class Elem>
  F<unit_t(K3::Collection<Elem>&)> loadCollection(string filepath) {
    F<unit_t(K3::Collection<Elem>&)> r = [filepath] (K3::Collection<Elem>& c) {
      string s;
      std::ifstream infile(filepath);
      cout << "hi!" << endl;
      while (std::getline(infile,s)) {
        Elem e;
        do_patch<Elem>(s,e);
        c.insert(e);
        cout << e.pageURL << endl;
      }
      return unit_t();
    };
    return r;
  }
}
#endif /* K3_RUNTIME_BUILTINS_H */
<|endoftext|>


<commit_before>#ifndef INC_AL_LUA_HPP
#define INC_AL_LUA_HPP

/*	Allocore --
	Multimedia / virtual environment application class library

	Copyright (C) 2009. AlloSphere Research Group, Media Arts & Technology, UCSB.
	Copyright (C) 2006-2008. The Regents of the University of California (REGENTS).
	All Rights Reserved.

	Permission to use, copy, modify, distribute, and distribute modified versions
	of this software and its documentation without fee and without a signed
	licensing agreement, is hereby granted, provided that the above copyright
	notice, the list of contributors, this paragraph and the following two paragraphs
	appear in all copies, modifications, and distributions.

	IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
	SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
	OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
	BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

	REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
	THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
	PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
	HEREUNDER IS PROVIDED "AS IS". REGENTS HAS  NO OBLIGATION TO PROVIDE
	MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

	File description:
	Utilities for working with Lua

	File author(s):
	Graham Wakefield, 2012, grrrwaaa@gmail.com
*/

#include "lua.hpp"

namespace al {

///! A wrapper around the lua_State:
class Lua {
public:

	Lua() : L(0) {
		L = lua_open();
		luaL_openlibs(L);
	}

	///! destructor calls
	~Lua() {
		if (L) {
			lua_close(L);
			L = 0;
		}
	}

	int lerror(lua_State * L, int err) {
		if (err) {
			printf("error: %s\n", lua_tostring(L, -1));
			lua_pop(L, 1);
		}
		return err;
	}

	int pcall(lua_State * L, int nargs) {
		int debug_idx = -nargs-3;
		// put debug.traceback just below the function & args
		{
			lua_getglobal(L, "debug");
			lua_pushliteral(L, "traceback");
			lua_gettable(L, -2);
			lua_insert(L, debug_idx);
			lua_pop(L, 1); // pop debug table
		}
		int top = lua_gettop(L);
		int res = lerror(L, lua_pcall(L, nargs, LUA_MULTRET, -nargs-2));
		int nres = lua_gettop(L) - top;
	//	int nres = lua_gettop(L) - top + nargs + 1;
		lua_remove(L, -(nres+nargs+2)); // remove debug function from stack
		return res;
	}

	int dostring(const std::string& code, int nargs=0) {
		return lerror(L, luaL_loadstring(L, code.c_str())) || pcall(L, nargs);
	}

	int dofile(const std::string& path, int nargs=0) {
		return lerror(L, luaL_loadfile(L, path.c_str())) || pcall(L, nargs);
	}

	///! allow the Lua object to be used in place of a lua_State *
	operator lua_State *() { return L; }
	operator const lua_State *() { return L; }

protected:
	lua_State * L;
};

} // al::

#endif<commit_msg>lua wrapper update<commit_after>#ifndef INC_AL_LUA_HPP
#define INC_AL_LUA_HPP

/*	Allocore --
	Multimedia / virtual environment application class library

	Copyright (C) 2009. AlloSphere Research Group, Media Arts & Technology, UCSB.
	Copyright (C) 2006-2008. The Regents of the University of California (REGENTS).
	All Rights Reserved.

	Permission to use, copy, modify, distribute, and distribute modified versions
	of this software and its documentation without fee and without a signed
	licensing agreement, is hereby granted, provided that the above copyright
	notice, the list of contributors, this paragraph and the following two paragraphs
	appear in all copies, modifications, and distributions.

	IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
	SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
	OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
	BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

	REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
	THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
	PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
	HEREUNDER IS PROVIDED "AS IS". REGENTS HAS  NO OBLIGATION TO PROVIDE
	MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

	File description:
	Utilities for working with Lua

	File author(s):
	Graham Wakefield, 2012, grrrwaaa@gmail.com
*/

#include "lua.hpp"

namespace al {

///! A wrapper around the lua_State:
class Lua {
public:

	Lua() : L(0) {
		L = lua_open();
		luaL_openlibs(L);
	}

	///! destructor calls
	~Lua() {
		if (L) {
			lua_close(L);
			L = 0;
		}
	}

	Lua& setglobal(const std::string& name, std::string& value) {
        lua_pushstring(L, value.c_str());
        lua_setglobal(L, name.c_str());
        return *this;
	}

	int lerror(lua_State * L, int err) {
		if (err) {
			printf("error: %s\n", lua_tostring(L, -1));
			lua_pop(L, 1);
		}
		return err;
	}

	int pcall(lua_State * L, int nargs) {
		int debug_idx = -nargs-3;
		// put debug.traceback just below the function & args
		{
			lua_getglobal(L, "debug");
			lua_pushliteral(L, "traceback");
			lua_gettable(L, -2);
			lua_insert(L, debug_idx);
			lua_pop(L, 1); // pop debug table
		}
		int top = lua_gettop(L);
		int res = lerror(L, lua_pcall(L, nargs, LUA_MULTRET, -nargs-2));
		int nres = lua_gettop(L) - top;
	//	int nres = lua_gettop(L) - top + nargs + 1;
		lua_remove(L, -(nres+nargs+2)); // remove debug function from stack
		return res;
	}

	int dostring(const std::string& code, int nargs=0) {
		return lerror(L, luaL_loadstring(L, code.c_str())) || pcall(L, nargs);
	}

	int dofile(const std::string& path, int nargs=0) {
		return lerror(L, luaL_loadfile(L, path.c_str())) || pcall(L, nargs);
	}

	///! allow the Lua object to be used in place of a lua_State *
	operator lua_State *() { return L; }
	operator const lua_State *() { return L; }

protected:
	lua_State * L;
};

} // al::

#endif
<|endoftext|>


<commit_before>/*
This file is part of Bohrium and copyright (c) 2012 the Bohrium
team <http://www.bh107.org>.

Bohrium is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation, either version 3
of the License, or (at your option) any later version.

Bohrium is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the
GNU Lesser General Public License along with Bohrium.

If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once

#include <vector>
#include <sstream>
#include <stdexcept>
#include <bh_util.hpp>

namespace bohrium {

class MallocCache {
public:
    typedef std::function<void *(uint64_t)> FuncAllocT;
    typedef std::function<void(void *, uint64_t)> FuncFreeT;

private:
    struct Segment {
        std::uint64_t nbytes;
        void *mem;
    };
    std::vector<Segment> _segments;
    uint64_t _total_num_bytes = 0;
    uint64_t _total_num_lookups = 0;
    uint64_t _total_num_misses = 0;
    uint64_t _total_mem_allocated = 0;
    uint64_t _max_mem_allocated = 0;
    FuncAllocT _func_alloc;
    FuncFreeT _func_free;
    uint64_t _limit_num_bytes;

    void *_malloc(uint64_t nbytes) {
        void *ret = _func_alloc(nbytes);
        _total_mem_allocated += nbytes;
        if (_total_mem_allocated > _max_mem_allocated) {
            _max_mem_allocated = _total_mem_allocated;
        }
//        std::cout << "malloc       - nbytes: " << nbytes << ",  addr: " << ret << std::endl;
        return ret;
    }

    void _free(void *mem, uint64_t nbytes) {
//        std::cout << "free         - nbytes: " << nbytes << ",  addr: " << mem << std::endl;
        assert(mem != nullptr);
        _func_free(mem, nbytes);
        assert(_total_mem_allocated >= nbytes);
        _total_mem_allocated -= nbytes;
    }

    void _erase(std::vector<Segment>::iterator first, std::vector<Segment>::iterator last, bool call_free) {
        for (auto it = first; it != last; ++it) {
            if (call_free) {
                _free(it->mem, it->nbytes);
            }
            _total_num_bytes -= it->nbytes;
        }
        _segments.erase(first, last);
    }

    void _erase(std::vector<Segment>::iterator position, bool call_free) {
        _erase(position, std::next(position), call_free);
    }

    void _erase(std::vector<Segment>::reverse_iterator position, bool call_free) {
        // Notice, we need to iterate `position` once when converting from reverse to regular iterator
        _erase(std::next(position).base(), call_free);
    }

public:

    MallocCache(FuncAllocT func_alloc, FuncFreeT func_free, uint64_t limit_num_bytes) :
            _func_alloc(func_alloc), _func_free(func_free), _limit_num_bytes(limit_num_bytes) {}

    std::string pprint() {
        std::stringstream ss;
        ss << "Malloc Cache: \n";
        for (const Segment &seg: _segments) {
            ss << "  (" << seg.nbytes << "B, " << seg.mem << ")\n";
        }
        return ss.str();
    }

    uint64_t shrink(uint64_t nbytes) {
        uint64_t count = 0;
        std::vector<Segment>::iterator it;
        for (it = _segments.begin(); it != _segments.end() and count < nbytes; ++it) {
            count += it->nbytes;
        }
        _erase(_segments.begin(), it, true);
        return count;
    }

    uint64_t shrinkToFit(uint64_t total_num_bytes) {
        if (total_num_bytes < _total_num_bytes) {
            shrink(_total_num_bytes - total_num_bytes);
        }
        return _total_num_bytes;
    }

    void *alloc(uint64_t nbytes) {
        if (nbytes == 0) {
            return nullptr;
        }
        ++_total_num_lookups;
        // Check for segment of size `nbytes`, which is a cache hit!
        for (auto it = _segments.rbegin(); it != _segments.rend(); ++it) { // Search in reverse
            if (it->nbytes == nbytes) {
                void *ret = it->mem;
                assert(ret != nullptr);
                _erase(it, false);
//               std::cout << "cache hit!   - nbytes: " << nbytes << ",  addr: " << ret << std::endl;
                return ret;
            }
        }
        ++_total_num_misses;
        void *ret = _malloc(nbytes); // Cache miss
//      std::cout << "cache miss!  - nbytes: " << nbytes << ",  addr: " << ret << std::endl;
        return ret;
    }

    void free(uint64_t nbytes, void *memory) {
        // Let's make sure that we don't exceed `MAX_NBYTES`
        if (nbytes > _limit_num_bytes) {
            return _free(memory, nbytes);
        }
        shrinkToFit(_limit_num_bytes - nbytes);

        // Insert the segment at the end of `_segments`
        Segment seg;
        seg.nbytes = nbytes;
        seg.mem = memory;
        _segments.push_back(seg);
        _total_num_bytes += nbytes;
//        std::cout << "cache insert - nbytes: " << nbytes << ",  addr: " << seg.mem << std::endl;
    }

    ~MallocCache() {
        shrinkToFit(0);
        assert(_total_num_bytes == 0);
    }

    void setLimit(uint64_t nbytes) {
        shrinkToFit(nbytes);
        _limit_num_bytes = nbytes;
    };

    uint64_t getTotalNumBytes() const {
        return _total_num_bytes;
    }

    uint64_t getTotalNumLookups() const {
        return _total_num_lookups;
    }

    uint64_t getTotalNumMisses() const {
        return _total_num_misses;
    }

    uint64_t getMaxMemAllocated() const {
        return _max_mem_allocated;
    }
};

} // Namespace bohrium
<commit_msg>malloc: now we shrink on alloc<commit_after>/*
This file is part of Bohrium and copyright (c) 2012 the Bohrium
team <http://www.bh107.org>.

Bohrium is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation, either version 3
of the License, or (at your option) any later version.

Bohrium is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the
GNU Lesser General Public License along with Bohrium.

If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once

#include <vector>
#include <sstream>
#include <stdexcept>
#include <bh_util.hpp>

namespace bohrium {

class MallocCache {
public:
    typedef std::function<void *(uint64_t)> FuncAllocT;
    typedef std::function<void(void *, uint64_t)> FuncFreeT;

private:
    struct Segment {
        std::uint64_t nbytes;
        void *mem;
    };
    std::vector<Segment> _segments;
    FuncAllocT _func_alloc;
    FuncFreeT _func_free;

    uint64_t _cache_size = 0; // Current size of the cache (in bytes)
    uint64_t _mem_allocated = 0; // Current memory allocated inside and outside the cache (in bytes)
    uint64_t _mem_allocated_limit; // The limit of `_mem_allocated`

    // Some statistics
    uint64_t _stat_lookups = 0;
    uint64_t _stat_misses = 0;
    uint64_t _stat_allocated_max = 0;

    void *_malloc(uint64_t nbytes) {
        void *ret = _func_alloc(nbytes);
        _mem_allocated += nbytes;
        if (_mem_allocated > _stat_allocated_max) {
            _stat_allocated_max = _mem_allocated;
        }
//        std::cout << "malloc       - nbytes: " << nbytes << ",  addr: " << ret << std::endl;
        return ret;
    }

    void _free(void *mem, uint64_t nbytes) {
//        std::cout << "free         - nbytes: " << nbytes << ",  addr: " << mem << std::endl;
        assert(mem != nullptr);
        _func_free(mem, nbytes);
        assert(_mem_allocated >= nbytes);
        _mem_allocated -= nbytes;
    }

    void _erase(std::vector<Segment>::iterator first, std::vector<Segment>::iterator last, bool call_free) {
        for (auto it = first; it != last; ++it) {
            if (call_free) {
                _free(it->mem, it->nbytes);
            }
            _cache_size -= it->nbytes;
        }
        _segments.erase(first, last);
    }

    void _erase(std::vector<Segment>::iterator position, bool call_free) {
        _erase(position, std::next(position), call_free);
    }

    void _erase(std::vector<Segment>::reverse_iterator position, bool call_free) {
        // Notice, we need to iterate `position` once when converting from reverse to regular iterator
        _erase(std::next(position).base(), call_free);
    }

public:

    /** Constructor
     *
     * @param func_alloc A function that takes size and returns a new memory allocation
     * @param func_free  A function that takes a memory allocation and size and frees the allocation
     * @param limit_num_bytes
     */
    MallocCache(FuncAllocT func_alloc, FuncFreeT func_free, uint64_t limit_num_bytes) :
            _func_alloc(func_alloc), _func_free(func_free), _mem_allocated_limit(limit_num_bytes) {}

    /** Pretty print the cache */
    std::string pprint() {
        std::stringstream ss;
        ss << "Malloc Cache: \n";
        for (const Segment &seg: _segments) {
            ss << "  (" << seg.nbytes << "B, " << seg.mem << ")\n";
        }
        return ss.str();
    }

    /** Shrink to size of the cache with at least `nbytes`
     *
     * @param nbytes The minimum amount of bytes to shrink with
     * @return The actual size reduction
     */
    uint64_t shrink(uint64_t nbytes) {
        uint64_t count = 0;
        std::vector<Segment>::iterator it;
        for (it = _segments.begin(); it != _segments.end() and count < nbytes; ++it) {
            count += it->nbytes;
        }
        _erase(_segments.begin(), it, true);
        return count;
    }

    /** Makes sure that the size of the cache is at most `nbytes`
     *
     * @param nbytes The maximum size of the cache size
     * @return The size reduction (if any)
     */
    uint64_t shrinkToFit(uint64_t nbytes) {
        if (nbytes < _cache_size) {
            return shrink(_cache_size - nbytes);
        }
        return 0;
    }

    /** Alloc a memory allocation of size `nbytes`
     *
     * @param nbytes Number of bytes to allocate
     * @return The memory allocation
     */
    void *alloc(uint64_t nbytes) {
        if (nbytes == 0) {
            return nullptr;
        }
        ++_stat_lookups;
        // Check for segment of size `nbytes`, which is a cache hit!
        for (auto it = _segments.rbegin(); it != _segments.rend(); ++it) { // Search in reverse
            if (it->nbytes == nbytes) {
                void *ret = it->mem;
                assert(ret != nullptr);
                _erase(it, false);
//               std::cout << "cache hit!   - nbytes: " << nbytes << ",  addr: " << ret << std::endl;
                return ret;
            }
        }
        ++_stat_misses;

        // Since we are allocating new memory, we might have to shrink to fit `_mem_allocated_limit`
        // Notice, we cannot do anything about memory allocation not in the cache; we can only shrink the cache to zero
        {
            assert(_mem_allocated > _cache_size);
            const uint64_t new_mem_not_in_cache = _mem_allocated - _cache_size + nbytes;
            if (new_mem_not_in_cache < _mem_allocated_limit) {
                shrinkToFit(_mem_allocated_limit - new_mem_not_in_cache);
            } else {
                shrinkToFit(0);
            }
        }

        void *ret = _malloc(nbytes); // Cache miss
//      std::cout << "cache miss!  - nbytes: " << nbytes << ",  addr: " << ret << std::endl;
        return ret;
    }

    /** Frees a memory allocation of size `nbytes`
     *
     * @param nbytes The size of the memory allocation
     * @param memory The memory allocation
     */
    void free(uint64_t nbytes, void *memory) {
        // Insert the segment at the end of `_segments`
        Segment seg;
        seg.nbytes = nbytes;
        seg.mem = memory;
        _segments.push_back(seg);
        _cache_size += nbytes;
//        std::cout << "cache insert - nbytes: " << nbytes << ",  addr: " << seg.mem << std::endl;
    }

    /** Destructor */
    ~MallocCache() {
        shrinkToFit(0);
        assert(_cache_size == 0);
    }

    void setLimit(uint64_t nbytes) {
        shrinkToFit(nbytes);
        _mem_allocated_limit = nbytes;
    };

    uint64_t getTotalNumBytes() const {
        return _cache_size;
    }

    uint64_t getTotalNumLookups() const {
        return _stat_lookups;
    }

    uint64_t getTotalNumMisses() const {
        return _stat_misses;
    }

    uint64_t getMaxMemAllocated() const {
        return _stat_allocated_max;
    }
};

} // Namespace bohrium
<|endoftext|>


<commit_before>#pragma once

#include <iosfwd>
#include <memory>

namespace crab {

// An adaptor for std::ostream that avoids polluting all crab header
// files with iostream stuff
class crab_os {

  static std::unique_ptr<crab_os> m_cout;
  static std::unique_ptr<crab_os> m_cerr;

public:
  static crab_os &cout();
  static crab_os &cerr();

private:
  std::ostream *m_os;

protected:
  crab_os();

public:
  crab_os(std::ostream *os);

  crab_os(const crab_os &o) = delete;

  crab_os &operator=(const crab_os &o) = delete;

  virtual ~crab_os();

  virtual crab_os &operator<<(char C);
  virtual crab_os &operator<<(unsigned char C);
  virtual crab_os &operator<<(signed char C);
  virtual crab_os &operator<<(const char *Str);
  virtual crab_os &operator<<(const std::string &Str);
  virtual crab_os &operator<<(unsigned long N);
  virtual crab_os &operator<<(long N);
  virtual crab_os &operator<<(unsigned long long N);
  virtual crab_os &operator<<(long long N);
  virtual crab_os &operator<<(const void *P);
  virtual crab_os &operator<<(unsigned int N);
  virtual crab_os &operator<<(int N);
  virtual crab_os &operator<<(double N);
};

extern crab_os &outs();
extern crab_os &errs();

// An adaptor for std::ostringstream
class crab_string_os : public crab_os {

  std::ostringstream *m_string_os;

public:
  crab_string_os();

  ~crab_string_os();

  std::string str();

  crab_os &operator<<(char C);
  crab_os &operator<<(unsigned char C);
  crab_os &operator<<(signed char C);
  crab_os &operator<<(const char *Str);
  crab_os &operator<<(const std::string &Str);
  crab_os &operator<<(unsigned long N);
  crab_os &operator<<(long N);
  crab_os &operator<<(unsigned long long N);
  crab_os &operator<<(long long N);
  crab_os &operator<<(const void *P);
  crab_os &operator<<(unsigned int N);
  crab_os &operator<<(int N);
  crab_os &operator<<(double N);
};

} // namespace crab
<commit_msg>fix: remove warning<commit_after>#pragma once

#include <iosfwd>
#include <memory>

namespace crab {

// An adaptor for std::ostream that avoids polluting all crab header
// files with iostream stuff
class crab_os {

  static std::unique_ptr<crab_os> m_cout;
  static std::unique_ptr<crab_os> m_cerr;

public:
  static crab_os &cout();
  static crab_os &cerr();

private:
  std::ostream *m_os;

protected:
  crab_os();

public:
  crab_os(std::ostream *os);

  crab_os(const crab_os &o) = delete;

  crab_os &operator=(const crab_os &o) = delete;

  virtual ~crab_os();

  virtual crab_os &operator<<(char C);
  virtual crab_os &operator<<(unsigned char C);
  virtual crab_os &operator<<(signed char C);
  virtual crab_os &operator<<(const char *Str);
  virtual crab_os &operator<<(const std::string &Str);
  virtual crab_os &operator<<(unsigned long N);
  virtual crab_os &operator<<(long N);
  virtual crab_os &operator<<(unsigned long long N);
  virtual crab_os &operator<<(long long N);
  virtual crab_os &operator<<(const void *P);
  virtual crab_os &operator<<(unsigned int N);
  virtual crab_os &operator<<(int N);
  virtual crab_os &operator<<(double N);
};

extern crab_os &outs();
extern crab_os &errs();

// An adaptor for std::ostringstream
class crab_string_os : public crab_os {

  std::ostringstream *m_string_os;

public:
  crab_string_os();

  ~crab_string_os();

  std::string str();

  crab_os &operator<<(char C) override;
  crab_os &operator<<(unsigned char C) override;
  crab_os &operator<<(signed char C) override;
  crab_os &operator<<(const char *Str) override;
  crab_os &operator<<(const std::string &Str) override;
  crab_os &operator<<(unsigned long N) override;
  crab_os &operator<<(long N) override;
  crab_os &operator<<(unsigned long long N) override;
  crab_os &operator<<(long long N) override;
  crab_os &operator<<(const void *P) override;
  crab_os &operator<<(unsigned int N) override;
  crab_os &operator<<(int N) override;
  crab_os &operator<<(double N) override;
};

} // namespace crab
<|endoftext|>


<commit_before><commit_msg>protect against self-assignment<commit_after><|endoftext|>


<commit_before>/*
 * Copyright 2014-2019, CNRS
 * Copyright 2018-2020, INRIA
 */

#ifndef __eigenpy_eigenpy_hpp__
#define __eigenpy_eigenpy_hpp__

#include "eigenpy/fwd.hpp"
#include "eigenpy/deprecated.hpp"
#include "eigenpy/config.hpp"

#if EIGEN_VERSION_AT_LEAST(3,2,0)
#include "eigenpy/ref.hpp"

#define ENABLE_SPECIFIC_MATRIX_TYPE(TYPE) \
  ::eigenpy::enableEigenPySpecific<TYPE>(); \
  ::eigenpy::enableEigenPySpecific< eigenpy::Ref<TYPE> >();

#else // if EIGEN_VERSION_AT_LEAST(3,2,0)

#define ENABLE_SPECIFIC_MATRIX_TYPE(TYPE) \
  ::eigenpy::enableEigenPySpecific<TYPE>();

#endif // if EIGEN_VERSION_AT_LEAST(3,2,0)

namespace eigenpy
{

  /* Enable Eigen-Numpy serialization for a set of standard MatrixBase instance. */
  void EIGENPY_DLLEXPORT enableEigenPy();

  template<typename MatType>
  void enableEigenPySpecific();

  /* Enable the Eigen--Numpy serialization for the templated MatrixBase class.
   * The second template argument is used for inheritance of Eigen classes. If
   * using a native Eigen::MatrixBase, simply repeat the same arg twice. */
  template<typename MatType,typename EigenEquivalentType>
  EIGENPY_DEPRECATED void enableEigenPySpecific();

} // namespace eigenpy

#include "eigenpy/details.hpp"

#endif // ifndef __eigenpy_eigenpy_hpp__

<commit_msg>core: add exposeType function to faciltate exposition of new Types<commit_after>/*
 * Copyright 2014-2019, CNRS
 * Copyright 2018-2020, INRIA
 */

#ifndef __eigenpy_eigenpy_hpp__
#define __eigenpy_eigenpy_hpp__

#include "eigenpy/fwd.hpp"
#include "eigenpy/deprecated.hpp"
#include "eigenpy/config.hpp"

#if EIGEN_VERSION_AT_LEAST(3,2,0)
#include "eigenpy/ref.hpp"

#define ENABLE_SPECIFIC_MATRIX_TYPE(TYPE) \
  ::eigenpy::enableEigenPySpecific<TYPE>(); \
  ::eigenpy::enableEigenPySpecific< eigenpy::Ref<TYPE> >();

#else // if EIGEN_VERSION_AT_LEAST(3,2,0)

#define ENABLE_SPECIFIC_MATRIX_TYPE(TYPE) \
  ::eigenpy::enableEigenPySpecific<TYPE>();

#endif // if EIGEN_VERSION_AT_LEAST(3,2,0)

#define EIGENPY_MAKE_TYPEDEFS(Type, TypeSuffix, Size, SizeSuffix)   \
  /** \ingroup matrixtypedefs */                                    \
  typedef Eigen::Matrix<Type, Size, Size> Matrix##SizeSuffix##TypeSuffix;  \
  /** \ingroup matrixtypedefs */                                    \
  typedef Eigen::Matrix<Type, Size, 1>    Vector##SizeSuffix##TypeSuffix;  \
  /** \ingroup matrixtypedefs */                                    \
  typedef Eigen::Matrix<Type, 1, Size>    RowVector##SizeSuffix##TypeSuffix;

#define EIGENPY_MAKE_FIXED_TYPEDEFS(Type, TypeSuffix, Size)         \
  /** \ingroup matrixtypedefs */                                    \
  typedef Eigen::Matrix<Type, Size, Eigen::Dynamic> Matrix##Size##X##TypeSuffix;  \
  /** \ingroup matrixtypedefs */                                    \
  typedef Eigen::Matrix<Type, Eigen::Dynamic, Size> Matrix##X##Size##TypeSuffix;

#define EIGENPY_MAKE_TYPEDEFS_ALL_SIZES(Type, TypeSuffix) \
  EIGENPY_MAKE_TYPEDEFS(Type, TypeSuffix, 2, 2) \
  EIGENPY_MAKE_TYPEDEFS(Type, TypeSuffix, 3, 3) \
  EIGENPY_MAKE_TYPEDEFS(Type, TypeSuffix, 4, 4) \
  EIGENPY_MAKE_TYPEDEFS(Type, TypeSuffix, Eigen::Dynamic, X) \
  EIGENPY_MAKE_FIXED_TYPEDEFS(Type, TypeSuffix, 2) \
  EIGENPY_MAKE_FIXED_TYPEDEFS(Type, TypeSuffix, 3) \
  EIGENPY_MAKE_FIXED_TYPEDEFS(Type, TypeSuffix, 4)

namespace eigenpy
{

  /* Enable Eigen-Numpy serialization for a set of standard MatrixBase instance. */
  void EIGENPY_DLLEXPORT enableEigenPy();

  /* Enable the Eigen--Numpy serialization for the templated MatrixBase class.
   * The second template argument is used for inheritance of Eigen classes. If
   * using a native Eigen::MatrixBase, simply repeat the same arg twice. */
  template<typename MatType>
  void enableEigenPySpecific();

  /* Enable the Eigen--Numpy serialization for the templated MatrixBase class.
   * The second template argument is used for inheritance of Eigen classes. If
   * using a native Eigen::MatrixBase, simply repeat the same arg twice. */
  template<typename MatType,typename EigenEquivalentType>
  EIGENPY_DEPRECATED void enableEigenPySpecific();

  template<typename Scalar>
  EIGEN_DONT_INLINE void exposeType()
  {
    EIGENPY_MAKE_TYPEDEFS_ALL_SIZES(Scalar,s);

    ENABLE_SPECIFIC_MATRIX_TYPE(Vector2s);
    ENABLE_SPECIFIC_MATRIX_TYPE(RowVector2s);
    ENABLE_SPECIFIC_MATRIX_TYPE(Matrix2s);
    ENABLE_SPECIFIC_MATRIX_TYPE(Matrix2Xs);
    ENABLE_SPECIFIC_MATRIX_TYPE(MatrixX2s);

    ENABLE_SPECIFIC_MATRIX_TYPE(Vector3s);
    ENABLE_SPECIFIC_MATRIX_TYPE(RowVector3s);
    ENABLE_SPECIFIC_MATRIX_TYPE(Matrix3s);
    ENABLE_SPECIFIC_MATRIX_TYPE(Matrix3Xs);
    ENABLE_SPECIFIC_MATRIX_TYPE(MatrixX3s);

    ENABLE_SPECIFIC_MATRIX_TYPE(Vector4s);
    ENABLE_SPECIFIC_MATRIX_TYPE(RowVector4s);
    ENABLE_SPECIFIC_MATRIX_TYPE(Matrix4s);
    ENABLE_SPECIFIC_MATRIX_TYPE(Matrix4Xs);
    ENABLE_SPECIFIC_MATRIX_TYPE(MatrixX4s);

    ENABLE_SPECIFIC_MATRIX_TYPE(VectorXs);
    ENABLE_SPECIFIC_MATRIX_TYPE(RowVectorXs);
    ENABLE_SPECIFIC_MATRIX_TYPE(MatrixXs);
  }

} // namespace eigenpy

#include "eigenpy/details.hpp"

#endif // ifndef __eigenpy_eigenpy_hpp__
<|endoftext|>


<commit_before>//=======================================================================
// Copyright (c) 2014 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#ifndef ETL_FAST_MATRIX_HPP
#define ETL_FAST_MATRIX_HPP

#include<array>
#include<string>

#include "assert.hpp"
#include "traits.hpp"
#include "fast_op.hpp"
#include "fast_expr.hpp"

namespace etl {

namespace matrix_detail {

template<size_t F, size_t... Dims>
struct matrix_size  : std::integral_constant<std::size_t, F * matrix_size<Dims...>::value> {};

template<size_t F>
struct matrix_size<F> : std::integral_constant<std::size_t, F> {};

template<typename M, size_t I, typename Enable = void>
struct matrix_subsize  : std::integral_constant<std::size_t, M::template dim<I+1>() * matrix_subsize<M, I+1>::value> {};

template<typename M, size_t I>
struct matrix_subsize<M, I, enable_if_t<I == M::n_dimensions - 1>> : std::integral_constant<std::size_t, 1> {};

template<size_t S, size_t I, size_t F, size_t... Dims>
struct matrix_dimension {
    template<size_t S2, size_t I2, typename Enable = void>
    struct matrix_dimension_int : std::integral_constant<std::size_t, matrix_dimension<S, I+1, Dims...>::value> {};

    template<size_t S2, size_t I2>
    struct matrix_dimension_int<S2, I2, enable_if_t<S2 == I2>> : std::integral_constant<std::size_t, F> {};

    static constexpr const std::size_t value = matrix_dimension_int<S, I>::value;
};

template<typename M, size_t I, size_t Stop, typename S1, typename... S>
struct matrix_index {
    template<size_t I2, typename Enable = void>
    struct matrix_index_int {
        static size_t compute(S1 first, S... args){
            etl_assert(first < M::template dim<I2>(), "Out of bounds");

            return matrix_subsize<M, I>::value * first + matrix_index<M, I+1, Stop, S...>::compute(args...);
        }
    };

    template<size_t I2>
    struct matrix_index_int<I2, enable_if_t<I2 == Stop>> {
        static size_t compute(S1 first){
            etl_assert(first < M::template dim<I2>(), "Out of bounds");

            return first;
        }
    };

    static size_t compute(S1 first, S... args){
        return matrix_index_int<I>::compute(first, args...);
    }
};

} //end of namespace detail

template<typename T, size_t... Dims>
struct fast_matrix {
    static_assert(sizeof...(Dims) > 1, "At least two dimension must be specified");

public:
    static constexpr const std::size_t n_dimensions = sizeof...(Dims);
    static constexpr const std::size_t etl_size = matrix_detail::matrix_size<Dims...>::value;

    using       value_type = T;
    using     storage_impl = std::array<value_type, etl_size>;
    using         iterator = typename storage_impl::iterator;
    using   const_iterator = typename storage_impl::const_iterator;
    using        this_type = fast_matrix<T, Dims...>;

private:
    storage_impl _data;

    template<typename... S>
    static constexpr std::size_t index(S... args){
        return matrix_detail::matrix_index<this_type, 0, n_dimensions - 1, S...>::compute(args...);
    }

    template<typename... S>
    value_type& access(S... args){
        return _data[index(args...)];
    }

    template<typename... S>
    const value_type& access(S... args) const {
        return _data[index(args...)];
    }

public:

    ///{{{ Construction

    fast_matrix(){
        //Nothing to init
    }

    template<typename VT, enable_if_u<or_u<std::is_convertible<VT, value_type>::value, std::is_assignable<T&, VT>::value>::value> = detail::dummy>
    explicit fast_matrix(const VT& value){
        std::fill(_data.begin(), _data.end(), value);
    }

    fast_matrix(std::initializer_list<value_type> l){
        etl_assert(l.size() == size(), "Cannot copy from an initializer of different size");

        std::copy(l.begin(), l.end(), begin());
    }

    explicit fast_matrix(const fast_matrix& rhs){
        std::copy(rhs.begin(), rhs.end(), begin());
    }

    fast_matrix(fast_matrix&& rhs){
        std::copy(rhs.begin(), rhs.end(), begin());
    }

    template<typename LE, typename Op, typename RE>
    explicit fast_matrix(const binary_expr<value_type, LE, Op, RE>& e){
        ensure_same_size(*this, e);

        for(std::size_t i = 0; i < size(); ++i){
            _data[i] = e[i];
        }
    }

    template<typename E, typename Op>
    explicit fast_matrix(const unary_expr<value_type, E, Op>& e){
        ensure_same_size(*this, e);

        for(std::size_t i = 0; i < size(); ++i){
            _data[i] = e[i];
        }
    }

    template<typename E>
    explicit fast_matrix(const transform_expr<value_type, E>& e){
        //TODO This will only support 2D Expressions

        ensure_same_size(*this, e);

        for(std::size_t i = 0; i < dim<0>(); ++i){
            for(std::size_t j = 0; j < dim<1>(); ++j){
                _data[index(i,j)] = e(i,j);
            }
        }
    }

    //}}}

    //{{{ Assignment

    //Copy assignment operator

    fast_matrix& operator=(const fast_matrix& rhs){
        std::copy(rhs.begin(), rhs.end(), begin());

        return *this;
    }

    //Allow copy from other containers

    template<typename Container, enable_if_u<std::is_same<typename Container::value_type, value_type>::value> = detail::dummy>
    fast_matrix& operator=(const Container& vec){
        std::copy(vec.begin(), vec.end(), begin());

        return *this;
    }

    //Construct from expression

    template<typename LE, typename Op, typename RE>
    fast_matrix& operator=(binary_expr<value_type, LE, Op, RE>&& e){
        ensure_same_size(*this, e);

        for(std::size_t i = 0; i < size(); ++i){
            _data[i] = e[i];
        }

        return *this;
    }

    template<typename E, typename Op>
    fast_matrix& operator=(unary_expr<value_type, E, Op>&& e){
        ensure_same_size(*this, e);

        for(std::size_t i = 0; i < size(); ++i){
            _data[i] = e[i];
        }

        return *this;
    }

    template<typename E>
    fast_matrix& operator=(transform_expr<value_type, E>&& e){
        //TODO This will only support 2D Expressions

        ensure_same_size(*this, e);

        for(std::size_t i = 0; i < dim<0>(); ++i){
            for(std::size_t j = 0; j < dim<1>(); ++j){
                _data[index(i,j)] = e(i,j);
            }
        }

        return *this;
    }

    //Set the same value to each element of the matrix
    template<typename VT, enable_if_u<or_u<std::is_convertible<VT, value_type>::value, std::is_assignable<T&, VT>::value>::value> = detail::dummy>
    fast_matrix& operator=(const VT& value){
        std::fill(_data.begin(), _data.end(), value);

        return *this;
    }

    //Prohibit move
    fast_matrix& operator=(fast_matrix&& rhs) = delete;

    //}}}

    //{{{ Accessors

    static constexpr size_t size(){
        return etl_size;
    }

    static constexpr size_t rows(){
        return dim<0>();
    }

    static constexpr enable_if_t<(sizeof...(Dims) > 1), std::size_t> columns(){
        return dim<1>();
    }

    static constexpr size_t dimensions(){
        return n_dimensions;
    }

    template<size_t D>
    static constexpr size_t dim(){
        return matrix_detail::matrix_dimension<D, 0, Dims...>::value;
    }

    //TODO Would probably be useful to have dim(size_t i)

    template<typename... S>
    value_type& operator()(S... args){
        static_assert(sizeof...(S) == sizeof...(Dims), "Invalid number of parameters");
        static_assert(all_convertible_to<std::size_t, S...>::value, "Invalid size types");

        return access(static_cast<size_t>(args)...);
    }

    template<typename... S>
    const value_type& operator()(S... args) const {
        static_assert(sizeof...(S) == sizeof...(Dims), "Invalid number of parameters");
        static_assert(all_convertible_to<std::size_t, S...>::value, "Invalid size types");

        return access(static_cast<size_t>(args)...);
    }

    const value_type& operator[](size_t i) const {
        etl_assert(i < size(), "Out of bounds");

        return _data[i];
    }

    value_type& operator[](size_t i){
        etl_assert(i < size(), "Out of bounds");

        return _data[i];
    }

    const_iterator begin() const {
        return _data.begin();
    }

    const_iterator end() const {
        return _data.end();
    }

    iterator begin(){
        return _data.begin();
    }

    iterator end(){
        return _data.end();
    }

    //}}}
};

} //end of namespace etl

#endif
<commit_msg>Fix TODO<commit_after>//=======================================================================
// Copyright (c) 2014 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#ifndef ETL_FAST_MATRIX_HPP
#define ETL_FAST_MATRIX_HPP

#include<array>
#include<string>

#include "assert.hpp"
#include "traits.hpp"
#include "fast_op.hpp"
#include "fast_expr.hpp"

namespace etl {

namespace matrix_detail {

template<size_t F, size_t... Dims>
struct matrix_size  : std::integral_constant<std::size_t, F * matrix_size<Dims...>::value> {};

template<size_t F>
struct matrix_size<F> : std::integral_constant<std::size_t, F> {};

template<typename M, size_t I, typename Enable = void>
struct matrix_subsize  : std::integral_constant<std::size_t, M::template dim<I+1>() * matrix_subsize<M, I+1>::value> {};

template<typename M, size_t I>
struct matrix_subsize<M, I, enable_if_t<I == M::n_dimensions - 1>> : std::integral_constant<std::size_t, 1> {};

template<size_t S, size_t I, size_t F, size_t... Dims>
struct matrix_dimension {
    template<size_t S2, size_t I2, typename Enable = void>
    struct matrix_dimension_int : std::integral_constant<std::size_t, matrix_dimension<S, I+1, Dims...>::value> {};

    template<size_t S2, size_t I2>
    struct matrix_dimension_int<S2, I2, enable_if_t<S2 == I2>> : std::integral_constant<std::size_t, F> {};

    static constexpr const std::size_t value = matrix_dimension_int<S, I>::value;
};

template<typename M, size_t I, size_t Stop, typename S1, typename... S>
struct matrix_index {
    template<size_t I2, typename Enable = void>
    struct matrix_index_int {
        static size_t compute(S1 first, S... args){
            etl_assert(first < M::template dim<I2>(), "Out of bounds");

            return matrix_subsize<M, I>::value * first + matrix_index<M, I+1, Stop, S...>::compute(args...);
        }
    };

    template<size_t I2>
    struct matrix_index_int<I2, enable_if_t<I2 == Stop>> {
        static size_t compute(S1 first){
            etl_assert(first < M::template dim<I2>(), "Out of bounds");

            return first;
        }
    };

    static size_t compute(S1 first, S... args){
        return matrix_index_int<I>::compute(first, args...);
    }
};

} //end of namespace detail

template<typename T, size_t... Dims>
struct fast_matrix {
    static_assert(sizeof...(Dims) > 1, "At least two dimension must be specified");

public:
    static constexpr const std::size_t n_dimensions = sizeof...(Dims);
    static constexpr const std::size_t etl_size = matrix_detail::matrix_size<Dims...>::value;

    using       value_type = T;
    using     storage_impl = std::array<value_type, etl_size>;
    using         iterator = typename storage_impl::iterator;
    using   const_iterator = typename storage_impl::const_iterator;
    using        this_type = fast_matrix<T, Dims...>;

private:
    storage_impl _data;

    template<typename... S>
    static constexpr std::size_t index(S... args){
        return matrix_detail::matrix_index<this_type, 0, n_dimensions - 1, S...>::compute(args...);
    }

    template<typename... S>
    value_type& access(S... args){
        return _data[index(args...)];
    }

    template<typename... S>
    const value_type& access(S... args) const {
        return _data[index(args...)];
    }

public:

    ///{{{ Construction

    fast_matrix(){
        //Nothing to init
    }

    template<typename VT, enable_if_u<or_u<std::is_convertible<VT, value_type>::value, std::is_assignable<T&, VT>::value>::value> = detail::dummy>
    explicit fast_matrix(const VT& value){
        std::fill(_data.begin(), _data.end(), value);
    }

    fast_matrix(std::initializer_list<value_type> l){
        etl_assert(l.size() == size(), "Cannot copy from an initializer of different size");

        std::copy(l.begin(), l.end(), begin());
    }

    explicit fast_matrix(const fast_matrix& rhs){
        std::copy(rhs.begin(), rhs.end(), begin());
    }

    fast_matrix(fast_matrix&& rhs){
        std::copy(rhs.begin(), rhs.end(), begin());
    }

    template<typename LE, typename Op, typename RE>
    explicit fast_matrix(const binary_expr<value_type, LE, Op, RE>& e){
        ensure_same_size(*this, e);

        for(std::size_t i = 0; i < size(); ++i){
            _data[i] = e[i];
        }
    }

    template<typename E, typename Op>
    explicit fast_matrix(const unary_expr<value_type, E, Op>& e){
        ensure_same_size(*this, e);

        for(std::size_t i = 0; i < size(); ++i){
            _data[i] = e[i];
        }
    }

    template<typename E>
    explicit fast_matrix(const transform_expr<value_type, E>& e){
        static_assert(n_dimensions == 2, "Transform expressions are only 2D-valid for now");

        ensure_same_size(*this, e);

        for(std::size_t i = 0; i < dim<0>(); ++i){
            for(std::size_t j = 0; j < dim<1>(); ++j){
                _data[index(i,j)] = e(i,j);
            }
        }
    }

    //}}}

    //{{{ Assignment

    //Copy assignment operator

    fast_matrix& operator=(const fast_matrix& rhs){
        std::copy(rhs.begin(), rhs.end(), begin());

        return *this;
    }

    //Allow copy from other containers

    template<typename Container, enable_if_u<std::is_same<typename Container::value_type, value_type>::value> = detail::dummy>
    fast_matrix& operator=(const Container& vec){
        std::copy(vec.begin(), vec.end(), begin());

        return *this;
    }

    //Construct from expression

    template<typename LE, typename Op, typename RE>
    fast_matrix& operator=(binary_expr<value_type, LE, Op, RE>&& e){
        ensure_same_size(*this, e);

        for(std::size_t i = 0; i < size(); ++i){
            _data[i] = e[i];
        }

        return *this;
    }

    template<typename E, typename Op>
    fast_matrix& operator=(unary_expr<value_type, E, Op>&& e){
        ensure_same_size(*this, e);

        for(std::size_t i = 0; i < size(); ++i){
            _data[i] = e[i];
        }

        return *this;
    }

    template<typename E>
    fast_matrix& operator=(transform_expr<value_type, E>&& e){
        //TODO This will only support 2D Expressions

        ensure_same_size(*this, e);

        for(std::size_t i = 0; i < dim<0>(); ++i){
            for(std::size_t j = 0; j < dim<1>(); ++j){
                _data[index(i,j)] = e(i,j);
            }
        }

        return *this;
    }

    //Set the same value to each element of the matrix
    template<typename VT, enable_if_u<or_u<std::is_convertible<VT, value_type>::value, std::is_assignable<T&, VT>::value>::value> = detail::dummy>
    fast_matrix& operator=(const VT& value){
        std::fill(_data.begin(), _data.end(), value);

        return *this;
    }

    //Prohibit move
    fast_matrix& operator=(fast_matrix&& rhs) = delete;

    //}}}

    //{{{ Accessors

    static constexpr size_t size(){
        return etl_size;
    }

    static constexpr size_t rows(){
        return dim<0>();
    }

    static constexpr enable_if_t<(sizeof...(Dims) > 1), std::size_t> columns(){
        return dim<1>();
    }

    static constexpr size_t dimensions(){
        return n_dimensions;
    }

    template<size_t D>
    static constexpr size_t dim(){
        return matrix_detail::matrix_dimension<D, 0, Dims...>::value;
    }

    //TODO Would probably be useful to have dim(size_t i)

    template<typename... S>
    value_type& operator()(S... args){
        static_assert(sizeof...(S) == sizeof...(Dims), "Invalid number of parameters");
        static_assert(all_convertible_to<std::size_t, S...>::value, "Invalid size types");

        return access(static_cast<size_t>(args)...);
    }

    template<typename... S>
    const value_type& operator()(S... args) const {
        static_assert(sizeof...(S) == sizeof...(Dims), "Invalid number of parameters");
        static_assert(all_convertible_to<std::size_t, S...>::value, "Invalid size types");

        return access(static_cast<size_t>(args)...);
    }

    const value_type& operator[](size_t i) const {
        etl_assert(i < size(), "Out of bounds");

        return _data[i];
    }

    value_type& operator[](size_t i){
        etl_assert(i < size(), "Out of bounds");

        return _data[i];
    }

    const_iterator begin() const {
        return _data.begin();
    }

    const_iterator end() const {
        return _data.end();
    }

    iterator begin(){
        return _data.begin();
    }

    iterator end(){
        return _data.end();
    }

    //}}}
};

} //end of namespace etl

#endif
<|endoftext|>


<commit_before>/*
  This file is part of Ingen.
  Copyright 2007-2016 David Robillard <http://drobilla.net/>

  Ingen is free software: you can redistribute it and/or modify it under the
  terms of the GNU Affero General Public License as published by the Free
  Software Foundation, either version 3 of the License, or any later version.

  Ingen is distributed in the hope that it will be useful, but WITHOUT ANY
  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  A PARTICULAR PURPOSE.  See the GNU Affero General Public License for details.

  You should have received a copy of the GNU Affero General Public License
  along with Ingen.  If not, see <http://www.gnu.org/licenses/>.
*/

/**
   @defgroup Ingen Core Interfaces
*/

#ifndef INGEN_INTERFACE_HPP
#define INGEN_INTERFACE_HPP

#include "ingen/Message.hpp"
#include "ingen/Properties.hpp"
#include "ingen/Resource.hpp"
#include "ingen/Status.hpp"
#include "ingen/ingen.h"

#include <cstdint>
#include <memory>
#include <string>

namespace raul {
class Path;
} // namespace raul

namespace ingen {

class Atom;
class URI;

/** Abstract interface for Ingen servers and clients.
 *
 * @ingroup Ingen
 */
class INGEN_API Interface
{
public:
	using result_type = void;

	Interface() = default;

	virtual ~Interface() = default;

	virtual URI uri() const = 0;

	virtual std::shared_ptr<Interface> respondee() const { return nullptr; }

	virtual void set_respondee(const std::shared_ptr<Interface>& respondee) {}

	virtual void message(const Message& msg) = 0;

	/** @name Convenience API
	 * @{
	 */

	void operator()(const Message& msg) { message(msg); }

	void set_response_id(int32_t id) { _seq = id; }

	void bundle_begin() { message(BundleBegin{_seq++}); }
	void bundle_end()   { message(BundleEnd{_seq++}); }

	void put(const URI&        uri,
	                const Properties& properties,
	                Resource::Graph   ctx = Resource::Graph::DEFAULT)
	{
		message(Put{_seq++, uri, properties, ctx});
	}

	void delta(const URI&        uri,
	                  const Properties& remove,
	                  const Properties& add,
	                  Resource::Graph   ctx = Resource::Graph::DEFAULT)
	{
		message(Delta{_seq++, uri, remove, add, ctx});
	}

	void copy(const URI& old_uri, const URI& new_uri)
	{
		message(Copy{_seq++, old_uri, new_uri});
	}

	void move(const raul::Path& old_path, const raul::Path& new_path)
	{
		message(Move{_seq++, old_path, new_path});
	}

	void del(const URI& uri) { message(Del{_seq++, uri}); }

	void connect(const raul::Path& tail, const raul::Path& head)
	{
		message(Connect{_seq++, tail, head});
	}

	void disconnect(const raul::Path& tail, const raul::Path& head)
	{
		message(Disconnect{_seq++, tail, head});
	}

	void disconnect_all(const raul::Path& graph, const raul::Path& path)
	{
		message(DisconnectAll{_seq++, graph, path});
	}

	void set_property(const URI&      subject,
	                         const URI&      predicate,
	                         const Atom&     value,
	                         Resource::Graph ctx = Resource::Graph::DEFAULT)
	{
		message(SetProperty{_seq++, subject, predicate, value, ctx});
	}

	void undo() { message(Undo{_seq++}); }

	void redo() { message(Redo{_seq++}); }

	void get(const URI& uri) { message(Get{_seq++, uri}); }

	void response(int32_t id, Status status, const std::string& subject)
	{
		message(Response{id, status, subject});
	}

	void error(const std::string& error_message)
	{
		message(Error{_seq++, error_message});
	}

	/** @} */

private:
	int32_t _seq = 0;
};

} // namespace ingen

#endif // INGEN_INTERFACE_HPP
<commit_msg>Fix indentation<commit_after>/*
  This file is part of Ingen.
  Copyright 2007-2016 David Robillard <http://drobilla.net/>

  Ingen is free software: you can redistribute it and/or modify it under the
  terms of the GNU Affero General Public License as published by the Free
  Software Foundation, either version 3 of the License, or any later version.

  Ingen is distributed in the hope that it will be useful, but WITHOUT ANY
  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  A PARTICULAR PURPOSE.  See the GNU Affero General Public License for details.

  You should have received a copy of the GNU Affero General Public License
  along with Ingen.  If not, see <http://www.gnu.org/licenses/>.
*/

/**
   @defgroup Ingen Core Interfaces
*/

#ifndef INGEN_INTERFACE_HPP
#define INGEN_INTERFACE_HPP

#include "ingen/Message.hpp"
#include "ingen/Properties.hpp"
#include "ingen/Resource.hpp"
#include "ingen/Status.hpp"
#include "ingen/ingen.h"

#include <cstdint>
#include <memory>
#include <string>

namespace raul {
class Path;
} // namespace raul

namespace ingen {

class Atom;
class URI;

/** Abstract interface for Ingen servers and clients.
 *
 * @ingroup Ingen
 */
class INGEN_API Interface
{
public:
	using result_type = void;

	Interface() = default;

	virtual ~Interface() = default;

	virtual URI uri() const = 0;

	virtual std::shared_ptr<Interface> respondee() const { return nullptr; }

	virtual void set_respondee(const std::shared_ptr<Interface>& respondee) {}

	virtual void message(const Message& msg) = 0;

	/** @name Convenience API
	 * @{
	 */

	void operator()(const Message& msg) { message(msg); }

	void set_response_id(int32_t id) { _seq = id; }

	void bundle_begin() { message(BundleBegin{_seq++}); }
	void bundle_end()   { message(BundleEnd{_seq++}); }

	void put(const URI&        uri,
	         const Properties& properties,
	         Resource::Graph   ctx = Resource::Graph::DEFAULT)
	{
		message(Put{_seq++, uri, properties, ctx});
	}

	void delta(const URI&        uri,
	           const Properties& remove,
	           const Properties& add,
	           Resource::Graph   ctx = Resource::Graph::DEFAULT)
	{
		message(Delta{_seq++, uri, remove, add, ctx});
	}

	void copy(const URI& old_uri, const URI& new_uri)
	{
		message(Copy{_seq++, old_uri, new_uri});
	}

	void move(const raul::Path& old_path, const raul::Path& new_path)
	{
		message(Move{_seq++, old_path, new_path});
	}

	void del(const URI& uri) { message(Del{_seq++, uri}); }

	void connect(const raul::Path& tail, const raul::Path& head)
	{
		message(Connect{_seq++, tail, head});
	}

	void disconnect(const raul::Path& tail, const raul::Path& head)
	{
		message(Disconnect{_seq++, tail, head});
	}

	void disconnect_all(const raul::Path& graph, const raul::Path& path)
	{
		message(DisconnectAll{_seq++, graph, path});
	}

	void set_property(const URI&      subject,
	                  const URI&      predicate,
	                  const Atom&     value,
	                  Resource::Graph ctx = Resource::Graph::DEFAULT)
	{
		message(SetProperty{_seq++, subject, predicate, value, ctx});
	}

	void undo() { message(Undo{_seq++}); }

	void redo() { message(Redo{_seq++}); }

	void get(const URI& uri) { message(Get{_seq++, uri}); }

	void response(int32_t id, Status status, const std::string& subject)
	{
		message(Response{id, status, subject});
	}

	void error(const std::string& error_message)
	{
		message(Error{_seq++, error_message});
	}

	/** @} */

private:
	int32_t _seq = 0;
};

} // namespace ingen

#endif // INGEN_INTERFACE_HPP
<|endoftext|>


<commit_before>/*

Copyright (c) 2007, Arvid Norberg
All rights reserved.

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 the author 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 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef TORRENT_TIME_HPP_INCLUDED
#define TORRENT_TIME_HPP_INCLUDED

#ifndef _WIN32
#include <unistd.h>
#endif

#if (!defined (__MACH__) && !defined (_WIN32) && !defined(_POSIX_MONOTONIC_CLOCK) || _POSIX_MONOTONIC_CLOCK < 0) || defined (TORRENT_USE_BOOST_DATE_TIME)

#include <boost/date_time/posix_time/posix_time.hpp>

namespace libtorrent
{
	typedef boost::posix_time::ptime ptime;
	typedef boost::posix_time::time_duration time_duration;
	inline ptime time_now()
	{ return boost::posix_time::microsec_clock::universal_time(); }
	inline ptime min_time()
	{ return boost::posix_time::ptime(boost::posix_time::min_date_time); }
	inline ptime max_time()
	{ return boost::posix_time::ptime(boost::posix_time::max_date_time); }
	inline time_duration seconds(int s) { return boost::posix_time::seconds(s); }
	inline time_duration milliseconds(int s) { return boost::posix_time::milliseconds(s); }
	inline time_duration microsec(int s) { return boost::posix_time::microsec(s); }
	inline time_duration minutes(int s) { return boost::posix_time::minutes(s); }
	inline time_duration hours(int s) { return boost::posix_time::hours(s); }

	inline int total_seconds(time_duration td)
	{ return td.total_seconds(); }
	inline int total_milliseconds(time_duration td)
	{ return td.total_milliseconds(); }
	inline boost::int64_t total_microseconds(time_duration td)
	{ return td.total_microseconds(); }

}

#else

#include <asio/time_traits.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/cstdint.hpp>

namespace libtorrent
{
	// libtorrent time_duration type
	struct time_duration
	{
		time_duration() {}
		explicit time_duration(boost::int64_t d) : diff(d) {}
		boost::int64_t diff;
	};

	inline bool is_negative(time_duration dt) { return dt.diff < 0; }
	inline bool operator<(time_duration lhs, time_duration rhs)
	{ return lhs.diff < rhs.diff; }
	inline bool operator>(time_duration lhs, time_duration rhs)
	{ return lhs.diff > rhs.diff; }

	// libtorrent time type
	struct ptime
	{
		ptime() {}
		explicit ptime(boost::int64_t t): time(t) {}
		boost::int64_t time;
	};

	inline bool operator>(ptime lhs, ptime rhs)
	{ return lhs.time > rhs.time; }
	inline bool operator>=(ptime lhs, ptime rhs)
	{ return lhs.time >= rhs.time; }
	inline bool operator<=(ptime lhs, ptime rhs)
	{ return lhs.time <= rhs.time; }
	inline bool operator<(ptime lhs, ptime rhs)
	{ return lhs.time < rhs.time; }
	inline bool operator!=(ptime lhs, ptime rhs)
	{ return lhs.time != rhs.time;}
	inline bool operator==(ptime lhs, ptime rhs)
	{ return lhs.time == rhs.time;}
	inline time_duration operator-(ptime lhs, ptime rhs)
	{ return time_duration(lhs.time - rhs.time); }
	inline ptime operator+(ptime lhs, time_duration rhs)
	{ return ptime(lhs.time + rhs.diff); }
	inline ptime operator+(time_duration lhs, ptime rhs)
	{ return ptime(rhs.time + lhs.diff); }
	inline ptime operator-(ptime lhs, time_duration rhs)
	{ return ptime(lhs.time - rhs.diff); }

	ptime time_now();
	inline ptime min_time() { return ptime(0); }
	inline ptime max_time() { return ptime((std::numeric_limits<boost::int64_t>::max)()); }
	int total_seconds(time_duration td);
	int total_milliseconds(time_duration td);
	boost::int64_t total_microseconds(time_duration td);
}

// asio time_traits
namespace asio
{
	template<>
	struct time_traits<libtorrent::ptime>
	{
		typedef libtorrent::ptime time_type;
		typedef libtorrent::time_duration duration_type;
		static time_type now()
		{ return time_type(libtorrent::time_now()); }
		static time_type add(time_type t, duration_type d)
		{ return time_type(t.time + d.diff);}
		static duration_type subtract(time_type t1, time_type t2)
		{ return duration_type(t1 - t2); }
		static bool less_than(time_type t1, time_type t2)
		{ return t1 < t2; }
		static boost::posix_time::time_duration to_posix_duration(
			duration_type d)
		{ return boost::posix_time::microseconds(libtorrent::total_microseconds(d)); }
	};
}

#if defined(__MACH__)

#include <mach/mach_time.h>
#include <boost/cstdint.hpp>

// high precision timer for darwin intel and ppc

namespace libtorrent
{
	namespace aux
	{
		inline boost::int64_t absolutetime_to_microseconds(boost::int64_t at)
		{
			static mach_timebase_info_data_t timebase_info = {0,0};
			if (timebase_info.denom == 0)
				mach_timebase_info(&timebase_info);
			// make sure we don't overflow
			assert((at >= 0 && at >= at / 1000 * timebase_info.numer / timebase_info.denom)
				|| (at < 0 && at < at / 1000 * timebase_info.numer / timebase_info.denom));
			return at / 1000 * timebase_info.numer / timebase_info.denom;
		}

		inline boost::int64_t microseconds_to_absolutetime(boost::int64_t ms)
		{
			static mach_timebase_info_data_t timebase_info = {0,0};
			if (timebase_info.denom == 0)
			{
				mach_timebase_info(&timebase_info);
				assert(timebase_info.numer > 0);
				assert(timebase_info.denom > 0);
			}
			// make sure we don't overflow
			assert((ms >= 0 && ms <= ms * timebase_info.denom / timebase_info.numer * 1000)
				|| (ms < 0 && ms > ms * timebase_info.denom / timebase_info.numer * 1000));
			return ms * timebase_info.denom / timebase_info.numer * 1000;
		}
	}

	inline int total_seconds(time_duration td)
	{
		return aux::absolutetime_to_microseconds(td.diff)
			/ 1000000;
	}
	inline int total_milliseconds(time_duration td)
	{
		return aux::absolutetime_to_microseconds(td.diff)
			/ 1000;
	}
	inline boost::int64_t total_microseconds(time_duration td)
	{
		return aux::absolutetime_to_microseconds(td.diff);
	}

	inline ptime time_now() { return ptime(mach_absolute_time()); }

	inline time_duration microsec(boost::int64_t s)
	{
		return time_duration(aux::microseconds_to_absolutetime(s));
	}
	inline time_duration milliseconds(boost::int64_t s)
	{
		return time_duration(aux::microseconds_to_absolutetime(s * 1000));
	}
	inline time_duration seconds(boost::int64_t s)
	{
		return time_duration(aux::microseconds_to_absolutetime(s * 1000000));
	}
	inline time_duration minutes(boost::int64_t s)
	{
		return time_duration(aux::microseconds_to_absolutetime(s * 1000000 * 60));
	}
	inline time_duration hours(boost::int64_t s)
	{
		return time_duration(aux::microseconds_to_absolutetime(s * 1000000 * 60 * 60));
	}

}
#elif defined(_WIN32)

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <Windows.h>

namespace libtorrent
{
	namespace aux
	{
		inline boost::int64_t performance_counter_to_microseconds(boost::int64_t pc)
		{
			static LARGE_INTEGER performace_counter_frequency = {0,0};
			if (performace_counter_frequency.QuadPart == 0)
				QueryPerformanceFrequency(&performace_counter_frequency);

			return pc * 1000000 / performace_counter_frequency.QuadPart;
		}

		inline boost::int64_t microseconds_to_performance_counter(boost::int64_t ms)
		{
			static LARGE_INTEGER performace_counter_frequency = {0,0};
			if (performace_counter_frequency.QuadPart == 0)
				QueryPerformanceFrequency(&performace_counter_frequency);
			return ms * performace_counter_frequency.QuadPart / 1000000;
		}
	}

	inline int total_seconds(time_duration td)
	{
		return aux::performance_counter_to_microseconds(td.diff)
			/ 1000000;
	}
	inline int total_milliseconds(time_duration td)
	{
		return aux::performance_counter_to_microseconds(td.diff)
			/ 1000;
	}
	inline boost::int64_t total_microseconds(time_duration td)
	{
		return aux::performance_counter_to_microseconds(td.diff);
	}

	inline ptime time_now()
	{
		LARGE_INTEGER now;
		QueryPerformanceCounter(&now);
		return ptime(now.QuadPart);
	}

	inline time_duration microsec(boost::int64_t s)
	{
		return time_duration(aux::microseconds_to_performance_counter(s));
	}
	inline time_duration milliseconds(boost::int64_t s)
	{
		return time_duration(aux::microseconds_to_performance_counter(
			s * 1000));
	}
	inline time_duration seconds(boost::int64_t s)
	{
		return time_duration(aux::microseconds_to_performance_counter(
			s * 1000000));
	}
	inline time_duration minutes(boost::int64_t s)
	{
		return time_duration(aux::microseconds_to_performance_counter(
			s * 1000000 * 60));
	}
	inline time_duration hours(boost::int64_t s)
	{
		return time_duration(aux::microseconds_to_performance_counter(
			s * 1000000 * 60 * 60));
	}

}

#elif defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK >= 0

#include <time.h>

namespace libtorrent
{
	inline int total_seconds(time_duration td)
	{
		return td.diff / 1000000;
	}
	inline int total_milliseconds(time_duration td)
	{
		return td.diff / 1000;
	}
	inline boost::int64_t total_microseconds(time_duration td)
	{
		return td.diff;
	}

	inline ptime time_now()
	{
		timespec ts;
		clock_gettime(CLOCK_MONOTONIC, &ts);
		return ptime(boost::int64_t(ts.tv_sec) + ts.nsec / 1000);
	}

	inline time_duration microsec(boost::int64_t s)
	{
		return time_duration(s);
	}
	inline time_duration milliseconds(boost::int64_t s)
	{
		return time_duration(s * 1000);
	}
	inline time_duration seconds(boost::int64_t s)
	{
		return time_duration(s * 1000000);
	}
	inline time_duration minutes(boost::int64_t s)
	{
		return time_duration(s * 1000000 * 60);
	}
	inline time_duration hours(boost::int64_t s)
	{
		return time_duration(s * 1000000 * 60 * 60);
	}

}

#endif

#endif
#endif

<commit_msg>fixed typo in previous check-in<commit_after>/*

Copyright (c) 2007, Arvid Norberg
All rights reserved.

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 the author 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 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef TORRENT_TIME_HPP_INCLUDED
#define TORRENT_TIME_HPP_INCLUDED

#ifndef _WIN32
#include <unistd.h>
#endif

#if (!defined (__MACH__) && !defined (_WIN32) && !defined(_POSIX_MONOTONIC_CLOCK) || _POSIX_MONOTONIC_CLOCK < 0) || defined (TORRENT_USE_BOOST_DATE_TIME)

#include <boost/date_time/posix_time/posix_time.hpp>

namespace libtorrent
{
	typedef boost::posix_time::ptime ptime;
	typedef boost::posix_time::time_duration time_duration;
	inline ptime time_now()
	{ return boost::posix_time::microsec_clock::universal_time(); }
	inline ptime min_time()
	{ return boost::posix_time::ptime(boost::posix_time::min_date_time); }
	inline ptime max_time()
	{ return boost::posix_time::ptime(boost::posix_time::max_date_time); }
	inline time_duration seconds(int s) { return boost::posix_time::seconds(s); }
	inline time_duration milliseconds(int s) { return boost::posix_time::milliseconds(s); }
	inline time_duration microsec(int s) { return boost::posix_time::microsec(s); }
	inline time_duration minutes(int s) { return boost::posix_time::minutes(s); }
	inline time_duration hours(int s) { return boost::posix_time::hours(s); }

	inline int total_seconds(time_duration td)
	{ return td.total_seconds(); }
	inline int total_milliseconds(time_duration td)
	{ return td.total_milliseconds(); }
	inline boost::int64_t total_microseconds(time_duration td)
	{ return td.total_microseconds(); }

}

#else

#include <asio/time_traits.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/cstdint.hpp>

namespace libtorrent
{
	// libtorrent time_duration type
	struct time_duration
	{
		time_duration() {}
		explicit time_duration(boost::int64_t d) : diff(d) {}
		boost::int64_t diff;
	};

	inline bool is_negative(time_duration dt) { return dt.diff < 0; }
	inline bool operator<(time_duration lhs, time_duration rhs)
	{ return lhs.diff < rhs.diff; }
	inline bool operator>(time_duration lhs, time_duration rhs)
	{ return lhs.diff > rhs.diff; }

	// libtorrent time type
	struct ptime
	{
		ptime() {}
		explicit ptime(boost::int64_t t): time(t) {}
		boost::int64_t time;
	};

	inline bool operator>(ptime lhs, ptime rhs)
	{ return lhs.time > rhs.time; }
	inline bool operator>=(ptime lhs, ptime rhs)
	{ return lhs.time >= rhs.time; }
	inline bool operator<=(ptime lhs, ptime rhs)
	{ return lhs.time <= rhs.time; }
	inline bool operator<(ptime lhs, ptime rhs)
	{ return lhs.time < rhs.time; }
	inline bool operator!=(ptime lhs, ptime rhs)
	{ return lhs.time != rhs.time;}
	inline bool operator==(ptime lhs, ptime rhs)
	{ return lhs.time == rhs.time;}
	inline time_duration operator-(ptime lhs, ptime rhs)
	{ return time_duration(lhs.time - rhs.time); }
	inline ptime operator+(ptime lhs, time_duration rhs)
	{ return ptime(lhs.time + rhs.diff); }
	inline ptime operator+(time_duration lhs, ptime rhs)
	{ return ptime(rhs.time + lhs.diff); }
	inline ptime operator-(ptime lhs, time_duration rhs)
	{ return ptime(lhs.time - rhs.diff); }

	ptime time_now();
	inline ptime min_time() { return ptime(0); }
	inline ptime max_time() { return ptime((std::numeric_limits<boost::int64_t>::max)()); }
	int total_seconds(time_duration td);
	int total_milliseconds(time_duration td);
	boost::int64_t total_microseconds(time_duration td);
}

// asio time_traits
namespace asio
{
	template<>
	struct time_traits<libtorrent::ptime>
	{
		typedef libtorrent::ptime time_type;
		typedef libtorrent::time_duration duration_type;
		static time_type now()
		{ return time_type(libtorrent::time_now()); }
		static time_type add(time_type t, duration_type d)
		{ return time_type(t.time + d.diff);}
		static duration_type subtract(time_type t1, time_type t2)
		{ return duration_type(t1 - t2); }
		static bool less_than(time_type t1, time_type t2)
		{ return t1 < t2; }
		static boost::posix_time::time_duration to_posix_duration(
			duration_type d)
		{ return boost::posix_time::microseconds(libtorrent::total_microseconds(d)); }
	};
}

#if defined(__MACH__)

#include <mach/mach_time.h>
#include <boost/cstdint.hpp>

// high precision timer for darwin intel and ppc

namespace libtorrent
{
	namespace aux
	{
		inline boost::int64_t absolutetime_to_microseconds(boost::int64_t at)
		{
			static mach_timebase_info_data_t timebase_info = {0,0};
			if (timebase_info.denom == 0)
				mach_timebase_info(&timebase_info);
			// make sure we don't overflow
			assert((at >= 0 && at >= at / 1000 * timebase_info.numer / timebase_info.denom)
				|| (at < 0 && at < at / 1000 * timebase_info.numer / timebase_info.denom));
			return at / 1000 * timebase_info.numer / timebase_info.denom;
		}

		inline boost::int64_t microseconds_to_absolutetime(boost::int64_t ms)
		{
			static mach_timebase_info_data_t timebase_info = {0,0};
			if (timebase_info.denom == 0)
			{
				mach_timebase_info(&timebase_info);
				assert(timebase_info.numer > 0);
				assert(timebase_info.denom > 0);
			}
			// make sure we don't overflow
			assert((ms >= 0 && ms <= ms * timebase_info.denom / timebase_info.numer * 1000)
				|| (ms < 0 && ms > ms * timebase_info.denom / timebase_info.numer * 1000));
			return ms * timebase_info.denom / timebase_info.numer * 1000;
		}
	}

	inline int total_seconds(time_duration td)
	{
		return aux::absolutetime_to_microseconds(td.diff)
			/ 1000000;
	}
	inline int total_milliseconds(time_duration td)
	{
		return aux::absolutetime_to_microseconds(td.diff)
			/ 1000;
	}
	inline boost::int64_t total_microseconds(time_duration td)
	{
		return aux::absolutetime_to_microseconds(td.diff);
	}

	inline ptime time_now() { return ptime(mach_absolute_time()); }

	inline time_duration microsec(boost::int64_t s)
	{
		return time_duration(aux::microseconds_to_absolutetime(s));
	}
	inline time_duration milliseconds(boost::int64_t s)
	{
		return time_duration(aux::microseconds_to_absolutetime(s * 1000));
	}
	inline time_duration seconds(boost::int64_t s)
	{
		return time_duration(aux::microseconds_to_absolutetime(s * 1000000));
	}
	inline time_duration minutes(boost::int64_t s)
	{
		return time_duration(aux::microseconds_to_absolutetime(s * 1000000 * 60));
	}
	inline time_duration hours(boost::int64_t s)
	{
		return time_duration(aux::microseconds_to_absolutetime(s * 1000000 * 60 * 60));
	}

}
#elif defined(_WIN32)

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <Windows.h>

namespace libtorrent
{
	namespace aux
	{
		inline boost::int64_t performance_counter_to_microseconds(boost::int64_t pc)
		{
			static LARGE_INTEGER performace_counter_frequency = {0,0};
			if (performace_counter_frequency.QuadPart == 0)
				QueryPerformanceFrequency(&performace_counter_frequency);

			return pc * 1000000 / performace_counter_frequency.QuadPart;
		}

		inline boost::int64_t microseconds_to_performance_counter(boost::int64_t ms)
		{
			static LARGE_INTEGER performace_counter_frequency = {0,0};
			if (performace_counter_frequency.QuadPart == 0)
				QueryPerformanceFrequency(&performace_counter_frequency);
			return ms * performace_counter_frequency.QuadPart / 1000000;
		}
	}

	inline int total_seconds(time_duration td)
	{
		return aux::performance_counter_to_microseconds(td.diff)
			/ 1000000;
	}
	inline int total_milliseconds(time_duration td)
	{
		return aux::performance_counter_to_microseconds(td.diff)
			/ 1000;
	}
	inline boost::int64_t total_microseconds(time_duration td)
	{
		return aux::performance_counter_to_microseconds(td.diff);
	}

	inline ptime time_now()
	{
		LARGE_INTEGER now;
		QueryPerformanceCounter(&now);
		return ptime(now.QuadPart);
	}

	inline time_duration microsec(boost::int64_t s)
	{
		return time_duration(aux::microseconds_to_performance_counter(s));
	}
	inline time_duration milliseconds(boost::int64_t s)
	{
		return time_duration(aux::microseconds_to_performance_counter(
			s * 1000));
	}
	inline time_duration seconds(boost::int64_t s)
	{
		return time_duration(aux::microseconds_to_performance_counter(
			s * 1000000));
	}
	inline time_duration minutes(boost::int64_t s)
	{
		return time_duration(aux::microseconds_to_performance_counter(
			s * 1000000 * 60));
	}
	inline time_duration hours(boost::int64_t s)
	{
		return time_duration(aux::microseconds_to_performance_counter(
			s * 1000000 * 60 * 60));
	}

}

#elif defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK >= 0

#include <time.h>

namespace libtorrent
{
	inline int total_seconds(time_duration td)
	{
		return td.diff / 1000000;
	}
	inline int total_milliseconds(time_duration td)
	{
		return td.diff / 1000;
	}
	inline boost::int64_t total_microseconds(time_duration td)
	{
		return td.diff;
	}

	inline ptime time_now()
	{
		timespec ts;
		clock_gettime(CLOCK_MONOTONIC, &ts);
		return ptime(boost::int64_t(ts.tv_sec) + ts.tv_nsec / 1000);
	}

	inline time_duration microsec(boost::int64_t s)
	{
		return time_duration(s);
	}
	inline time_duration milliseconds(boost::int64_t s)
	{
		return time_duration(s * 1000);
	}
	inline time_duration seconds(boost::int64_t s)
	{
		return time_duration(s * 1000000);
	}
	inline time_duration minutes(boost::int64_t s)
	{
		return time_duration(s * 1000000 * 60);
	}
	inline time_duration hours(boost::int64_t s)
	{
		return time_duration(s * 1000000 * 60 * 60);
	}

}

#endif

#endif
#endif

<|endoftext|>


<commit_before>/*

Copyright (c) 2007, Arvid Norberg
All rights reserved.

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 the author 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 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef TORRENT_UPNP_HPP
#define TORRENT_UPNP_HPP

#include "libtorrent/socket.hpp"
#include "libtorrent/http_connection.hpp"

#include <boost/function.hpp>
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition.hpp>
#include <set>

#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
#include <fstream>
#endif

namespace libtorrent
{

// int: external tcp port
// int: external udp port
// std::string: error message
typedef boost::function<void(int, int, std::string const&)> portmap_callback_t;

class upnp : boost::noncopyable
{
public:
	upnp(io_service& ios, address const& listen_interface
		, std::string const& user_agent, portmap_callback_t const& cb);
	~upnp();

	void rebind(address const& listen_interface);

	// maps the ports, if a port is set to 0
	// it will not be mapped
	void set_mappings(int tcp, int udp);

	void close();

private:

	static address_v4 upnp_multicast_address;
	static udp::endpoint upnp_multicast_endpoint;

	enum { num_mappings = 2 };
	enum { default_lease_time = 3600 };

	void update_mapping(int i, int port);
	void resend_request(asio::error_code const& e);
	void on_reply(asio::error_code const& e
		, std::size_t bytes_transferred);
	void discover_device();

	struct rootdevice;

	void on_upnp_xml(asio::error_code const& e
		, libtorrent::http_parser const& p, rootdevice& d);
	void on_upnp_map_response(asio::error_code const& e
		, libtorrent::http_parser const& p, rootdevice& d
		, int mapping);
	void on_upnp_unmap_response(asio::error_code const& e
		, libtorrent::http_parser const& p, rootdevice& d
		, int mapping);
	void on_expire(asio::error_code const& e);

	void post(rootdevice& d, std::stringstream const& s
		, std::string const& soap_action);
	void map_port(rootdevice& d, int i);
	void unmap_port(rootdevice& d, int i);

	struct mapping_t
	{
		mapping_t()
			: need_update(false)
			, local_port(0)
			, external_port(0)
			, protocol(1)
		{}

		// the time the port mapping will expire
		ptime expires;

		bool need_update;

		// the local port for this mapping. If this is set
		// to 0, the mapping is not in use
		int local_port;

		// the external (on the NAT router) port
		// for the mapping. This is the port we
		// should announce to others
		int external_port;

		// 1 = udp, 0 = tcp
		int protocol;
	};

	struct rootdevice
	{
		rootdevice(): lease_duration(default_lease_time)
			, supports_specific_external(true)
		{
			mapping[0].protocol = 0;
			mapping[1].protocol = 1;
		}

		// the interface url, through which the list of
		// supported interfaces are fetched
		std::string url;

		// the url to the WANIP or WANPPP interface
		std::string control_url;
		// either the WANIP namespace or the WANPPP namespace
		std::string service_namespace;

		mapping_t mapping[num_mappings];

		std::string hostname;
		int port;
		std::string path;

		int lease_duration;
		// true if the device supports specifying a
		// specific external port, false if it doesn't
		bool supports_specific_external;

		boost::shared_ptr<http_connection> upnp_connection;

		void close() const { if (upnp_connection) upnp_connection->close(); }

		bool operator<(rootdevice const& rhs) const
		{ return url < rhs.url; }
	};

	int m_udp_local_port;
	int m_tcp_local_port;

	std::string const& m_user_agent;

	// the set of devices we've found
	std::set<rootdevice> m_devices;

	portmap_callback_t m_callback;

	// current retry count
	int m_retry_count;

	// used to receive responses in
	char m_receive_buffer[1024];

	// the endpoint we received the message from
	udp::endpoint m_remote;

	// the local address we're listening on
	address_v4 m_local_ip;

	// the udp socket used to send and receive
	// multicast messages on the network
	datagram_socket m_socket;

	// used to resend udp packets in case
	// they time out
	deadline_timer m_broadcast_timer;

	// timer used to refresh mappings
	deadline_timer m_refresh_timer;

	asio::strand m_strand;

	bool m_disabled;
	bool m_closing;

#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
	std::ofstream m_log;
#endif
};

}

#endif

<commit_msg>fixed upnp header define<commit_after>/*

Copyright (c) 2007, Arvid Norberg
All rights reserved.

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 the author 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 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef TORRENT_UPNP_HPP
#define TORRENT_UPNP_HPP

#include "libtorrent/socket.hpp"
#include "libtorrent/http_connection.hpp"

#include <boost/function.hpp>
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition.hpp>
#include <set>

#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
#include <fstream>
#endif

namespace libtorrent
{

// int: external tcp port
// int: external udp port
// std::string: error message
typedef boost::function<void(int, int, std::string const&)> portmap_callback_t;

class upnp : boost::noncopyable
{
public:
	upnp(io_service& ios, address const& listen_interface
		, std::string const& user_agent, portmap_callback_t const& cb);
	~upnp();

	void rebind(address const& listen_interface);

	// maps the ports, if a port is set to 0
	// it will not be mapped
	void set_mappings(int tcp, int udp);

	void close();

private:

	static address_v4 upnp_multicast_address;
	static udp::endpoint upnp_multicast_endpoint;

	enum { num_mappings = 2 };
	enum { default_lease_time = 3600 };

	void update_mapping(int i, int port);
	void resend_request(asio::error_code const& e);
	void on_reply(asio::error_code const& e
		, std::size_t bytes_transferred);
	void discover_device();

	struct rootdevice;

	void on_upnp_xml(asio::error_code const& e
		, libtorrent::http_parser const& p, rootdevice& d);
	void on_upnp_map_response(asio::error_code const& e
		, libtorrent::http_parser const& p, rootdevice& d
		, int mapping);
	void on_upnp_unmap_response(asio::error_code const& e
		, libtorrent::http_parser const& p, rootdevice& d
		, int mapping);
	void on_expire(asio::error_code const& e);

	void post(rootdevice& d, std::stringstream const& s
		, std::string const& soap_action);
	void map_port(rootdevice& d, int i);
	void unmap_port(rootdevice& d, int i);

	struct mapping_t
	{
		mapping_t()
			: need_update(false)
			, local_port(0)
			, external_port(0)
			, protocol(1)
		{}

		// the time the port mapping will expire
		ptime expires;

		bool need_update;

		// the local port for this mapping. If this is set
		// to 0, the mapping is not in use
		int local_port;

		// the external (on the NAT router) port
		// for the mapping. This is the port we
		// should announce to others
		int external_port;

		// 1 = udp, 0 = tcp
		int protocol;
	};

	struct rootdevice
	{
		rootdevice(): lease_duration(default_lease_time)
			, supports_specific_external(true)
		{
			mapping[0].protocol = 0;
			mapping[1].protocol = 1;
		}

		// the interface url, through which the list of
		// supported interfaces are fetched
		std::string url;

		// the url to the WANIP or WANPPP interface
		std::string control_url;
		// either the WANIP namespace or the WANPPP namespace
		std::string service_namespace;

		mapping_t mapping[num_mappings];

		std::string hostname;
		int port;
		std::string path;

		int lease_duration;
		// true if the device supports specifying a
		// specific external port, false if it doesn't
		bool supports_specific_external;

		boost::shared_ptr<http_connection> upnp_connection;

		void close() const { if (upnp_connection) upnp_connection->close(); }

		bool operator<(rootdevice const& rhs) const
		{ return url < rhs.url; }
	};

	int m_udp_local_port;
	int m_tcp_local_port;

	std::string const& m_user_agent;

	// the set of devices we've found
	std::set<rootdevice> m_devices;

	portmap_callback_t m_callback;

	// current retry count
	int m_retry_count;

	// used to receive responses in
	char m_receive_buffer[1024];

	// the endpoint we received the message from
	udp::endpoint m_remote;

	// the local address we're listening on
	address_v4 m_local_ip;

	// the udp socket used to send and receive
	// multicast messages on the network
	datagram_socket m_socket;

	// used to resend udp packets in case
	// they time out
	deadline_timer m_broadcast_timer;

	// timer used to refresh mappings
	deadline_timer m_refresh_timer;

	asio::strand m_strand;

	bool m_disabled;
	bool m_closing;

#ifdef TORRENT_UPNP_LOGGING
	std::ofstream m_log;
#endif
};

}

#endif

<|endoftext|>


<commit_before>// Copyright 2016-2017 Francesco Biscani (bluescarni@gmail.com)
//
// This file is part of the mp++ library.
//
// 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/.

#ifndef MPPP_DETAIL_GMP_HPP
#define MPPP_DETAIL_GMP_HPP

#include <cassert>
#include <gmp.h>
#include <type_traits>
#include <utility>

#if __GNU_MP_VERSION < 5

#error Minimum supported GMP version is 5.

#endif

namespace mppp
{

inline namespace detail
{

// mpz_t is an array of some struct.
using mpz_struct_t = std::remove_extent<::mpz_t>::type;
// Integral types used for allocation size and number of limbs.
using mpz_alloc_t = decltype(std::declval<mpz_struct_t>()._mp_alloc);
using mpz_size_t = decltype(std::declval<mpz_struct_t>()._mp_size);

// Simple RAII holder for GMP integers.
struct mpz_raii {
    mpz_raii()
    {
        ::mpz_init(&m_mpz);
        assert(m_mpz._mp_alloc >= 0);
    }
    mpz_raii(const mpz_raii &) = delete;
    mpz_raii(mpz_raii &&) = delete;
    mpz_raii &operator=(const mpz_raii &) = delete;
    mpz_raii &operator=(mpz_raii &&) = delete;
    ~mpz_raii()
    {
        // NOTE: even in recent GMP versions, with lazy allocation,
        // it seems like the pointer always points to something:
        // https://gmplib.org/repo/gmp/file/835f8974ff6e/mpz/init.c
        assert(m_mpz._mp_d != nullptr);
        ::mpz_clear(&m_mpz);
    }
    mpz_struct_t m_mpz;
};

// mpq_t is an array of some struct.
using mpq_struct_t = std::remove_extent<::mpq_t>::type;

// Simple RAII holder for GMP rationals.
struct mpq_raii {
    mpq_raii()
    {
        ::mpq_init(&m_mpq);
    }
    mpq_raii(const mpq_raii &) = delete;
    mpq_raii(mpq_raii &&) = delete;
    mpq_raii &operator=(const mpq_raii &) = delete;
    mpq_raii &operator=(mpq_raii &&) = delete;
    ~mpq_raii()
    {
        ::mpq_clear(&m_mpq);
    }
    mpq_struct_t m_mpq;
};

// mpf_t is an array of some struct.
using mpf_struct_t = std::remove_extent<::mpf_t>::type;

// Simple RAII holder for GMP floats.
struct mpf_raii {
    mpf_raii(::mp_bitcnt_t prec)
    {
        ::mpf_init2(&m_mpf, prec);
    }
    mpf_raii(const mpf_raii &) = delete;
    mpf_raii(mpf_raii &&) = delete;
    mpf_raii &operator=(const mpf_raii &) = delete;
    mpf_raii &operator=(mpf_raii &&) = delete;
    ~mpf_raii()
    {
        ::mpf_clear(&m_mpf);
    }
    mpf_struct_t m_mpf;
};
}
}

#endif
<commit_msg>Make an internal constructor explicit.<commit_after>// Copyright 2016-2017 Francesco Biscani (bluescarni@gmail.com)
//
// This file is part of the mp++ library.
//
// 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/.

#ifndef MPPP_DETAIL_GMP_HPP
#define MPPP_DETAIL_GMP_HPP

#include <cassert>
#include <gmp.h>
#include <type_traits>
#include <utility>

#if __GNU_MP_VERSION < 5

#error Minimum supported GMP version is 5.

#endif

namespace mppp
{

inline namespace detail
{

// mpz_t is an array of some struct.
using mpz_struct_t = std::remove_extent<::mpz_t>::type;
// Integral types used for allocation size and number of limbs.
using mpz_alloc_t = decltype(std::declval<mpz_struct_t>()._mp_alloc);
using mpz_size_t = decltype(std::declval<mpz_struct_t>()._mp_size);

// Simple RAII holder for GMP integers.
struct mpz_raii {
    mpz_raii()
    {
        ::mpz_init(&m_mpz);
        assert(m_mpz._mp_alloc >= 0);
    }
    mpz_raii(const mpz_raii &) = delete;
    mpz_raii(mpz_raii &&) = delete;
    mpz_raii &operator=(const mpz_raii &) = delete;
    mpz_raii &operator=(mpz_raii &&) = delete;
    ~mpz_raii()
    {
        // NOTE: even in recent GMP versions, with lazy allocation,
        // it seems like the pointer always points to something:
        // https://gmplib.org/repo/gmp/file/835f8974ff6e/mpz/init.c
        assert(m_mpz._mp_d != nullptr);
        ::mpz_clear(&m_mpz);
    }
    mpz_struct_t m_mpz;
};

// mpq_t is an array of some struct.
using mpq_struct_t = std::remove_extent<::mpq_t>::type;

// Simple RAII holder for GMP rationals.
struct mpq_raii {
    mpq_raii()
    {
        ::mpq_init(&m_mpq);
    }
    mpq_raii(const mpq_raii &) = delete;
    mpq_raii(mpq_raii &&) = delete;
    mpq_raii &operator=(const mpq_raii &) = delete;
    mpq_raii &operator=(mpq_raii &&) = delete;
    ~mpq_raii()
    {
        ::mpq_clear(&m_mpq);
    }
    mpq_struct_t m_mpq;
};

// mpf_t is an array of some struct.
using mpf_struct_t = std::remove_extent<::mpf_t>::type;

// Simple RAII holder for GMP floats.
struct mpf_raii {
    explicit mpf_raii(::mp_bitcnt_t prec)
    {
        ::mpf_init2(&m_mpf, prec);
    }
    mpf_raii(const mpf_raii &) = delete;
    mpf_raii(mpf_raii &&) = delete;
    mpf_raii &operator=(const mpf_raii &) = delete;
    mpf_raii &operator=(mpf_raii &&) = delete;
    ~mpf_raii()
    {
        ::mpf_clear(&m_mpf);
    }
    mpf_struct_t m_mpf;
};
}
}

#endif
<|endoftext|>