<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.

*/

#if defined TORRENT_DEBUG || defined TORRENT_ASIO_DEBUGGING || TORRENT_RELEASE_ASSERTS

#include "libtorrent/config.hpp"

#ifdef __APPLE__
#include <AvailabilityMacros.h>
#endif

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

// uClibc++ doesn't have cxxabi.h
#if defined __GNUC__ && __GNUC__ >= 3 \
	&& !defined __UCLIBCXX_MAJOR__

#include <cxxabi.h>

std::string demangle(char const* name)
{
// in case this string comes
	// this is needed on linux
	char const* start = strchr(name, '(');
	if (start != 0)
	{
		++start;
	}
	else
	{
		// this is needed on macos x
		start = strstr(name, "0x");
		if (start != 0)
		{
			start = strchr(start, ' ');
			if (start != 0) ++start;
			else start = name;
		}
		else start = name;
	}

	char const* end = strchr(start, '+');
	if (end) while (*(end-1) == ' ') --end;

	std::string in;
	if (end == 0) in.assign(start);
	else in.assign(start, end);

	size_t len;
	int status;
	char* unmangled = ::abi::__cxa_demangle(in.c_str(), 0, &len, &status);
	if (unmangled == 0) return in;
	std::string ret(unmangled);
	free(unmangled);
	return ret;
}
#elif defined WIN32

#undef _WIN32_WINNT
#define _WIN32_WINNT 0x0501 // XP

#include "windows.h"
#include "dbghelp.h"

std::string demangle(char const* name)
{
	char demangled_name[256];
	if (UnDecorateSymbolName(name, demangled_name, sizeof(demangled_name), UNDNAME_NO_THROW_SIGNATURES) == 0)
		demangled_name[0] = 0;
	return demangled_name;
}

#else
std::string demangle(char const* name) { return name; }
#endif

#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include "libtorrent/version.hpp"

// execinfo.h is available in the MacOS X 10.5 SDK.
#if (defined __linux__ || (defined __APPLE__ && MAC_OS_X_VERSION_MIN_REQUIRED >= 1050))
#include <execinfo.h>

void print_backtrace(char* out, int len)
{
	void* stack[50];
	int size = backtrace(stack, 50);
	char** symbols = backtrace_symbols(stack, size);

	for (int i = 1; i < size && len > 0; ++i)
	{
		int ret = snprintf(out, len, "%d: %s\n", i, demangle(symbols[i]).c_str());
		out += ret;
		len -= ret;
	}

	free(symbols);
}

#elif defined WIN32

#undef _WIN32_WINNT
#define _WIN32_WINNT 0x0501 // XP

#include "windows.h"
#include "libtorrent/utf8.hpp"

#include "winbase.h"
#include "dbghelp.h"

void print_backtrace(char* out, int len)
{
	typedef USHORT (*RtlCaptureStackBackTrace_t)(
		__in ULONG FramesToSkip,
		__in ULONG FramesToCapture,
		__out PVOID *BackTrace,
		__out_opt PULONG BackTraceHash);

	static RtlCaptureStackBackTrace_t RtlCaptureStackBackTrace = 0;

	if (RtlCaptureStackBackTrace == 0)
	{
		// we don't actually have to free this library, everyone has it loaded
		HMODULE lib = LoadLibrary(TEXT("kernel32.dll"));
		RtlCaptureStackBackTrace = (RtlCaptureStackBackTrace_t)GetProcAddress(lib, "RtlCaptureStackBackTrace");
		if (RtlCaptureStackBackTrace == 0)
		{
			out[0] = 0;
			return;
		}
	}

	int i;
	void* stack[50];
	int size = CaptureStackBackTrace(0, 50, stack, 0);

	SYMBOL_INFO* symbol = (SYMBOL_INFO*)calloc(sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR), 1);
	symbol->MaxNameLen = MAX_SYM_NAME;
	symbol->SizeOfStruct = sizeof(SYMBOL_INFO);

	HANDLE p = GetCurrentProcess();
	static bool sym_initialized = false;
	if (!sym_initialized)
	{
		sym_initialized = true;
		SymInitialize(p, NULL, true);
	}
	for (i = 0; i < size && len > 0; ++i)
	{
		int ret;
		if (SymFromAddr(p, uintptr_t(stack[i]), 0, symbol))
			ret = snprintf(out, len, "%d: %s\n", i, symbol->Name);
		else
			ret = snprintf(out, len, "%d: <unknown>\n", i);

		out += ret;
		len -= ret;
	}
	free(symbol);
}

#else

void print_backtrace(char* out, int len) {}

#endif

#if TORRENT_PRODUCTION_ASSERTS
char const* libtorrent_assert_log = "asserts.log";
#endif

TORRENT_EXPORT void assert_fail(char const* expr, int line, char const* file
	, char const* function, char const* value)
{
#if TORRENT_PRODUCTION_ASSERTS
	FILE* out = fopen(libtorrent_assert_log, "a+");
	if (out == 0) out = stderr;
#else
	FILE* out = stderr;
#endif

	char stack[8192];
	print_backtrace(stack, sizeof(stack));

	fprintf(out, "assertion failed. Please file a bugreport at "
		"http://code.rasterbar.com/libtorrent/newticket\n"
		"Please include the following information:\n\n"
		"version: " LIBTORRENT_VERSION "\n"
		"%s\n"
		"file: '%s'\n"
		"line: %d\n"
		"function: %s\n"
		"expression: %s\n"
		"%s%s\n"
		"stack:\n"
		"%s\n"
		, LIBTORRENT_REVISION, file, line, function, expr
		, value ? value : "", value ? "\n" : ""
		, stack);

	// if production asserts are defined, don't abort, just print the error
#if TORRENT_PRODUCTION_ASSERTS
	if (out != stderr) fclose(out);
#else
 	// send SIGINT to the current process
 	// to break into the debugger
 	raise(SIGINT);
 	abort();
#endif
}

#else

void assert_fail(char const* expr, int line, char const* file, char const* function) {}

#endif

<commit_msg>export assert_fail<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.

*/

#if defined TORRENT_DEBUG || defined TORRENT_ASIO_DEBUGGING || TORRENT_RELEASE_ASSERTS

#include "libtorrent/config.hpp"

#ifdef __APPLE__
#include <AvailabilityMacros.h>
#endif

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

// uClibc++ doesn't have cxxabi.h
#if defined __GNUC__ && __GNUC__ >= 3 \
	&& !defined __UCLIBCXX_MAJOR__

#include <cxxabi.h>

std::string demangle(char const* name)
{
// in case this string comes
	// this is needed on linux
	char const* start = strchr(name, '(');
	if (start != 0)
	{
		++start;
	}
	else
	{
		// this is needed on macos x
		start = strstr(name, "0x");
		if (start != 0)
		{
			start = strchr(start, ' ');
			if (start != 0) ++start;
			else start = name;
		}
		else start = name;
	}

	char const* end = strchr(start, '+');
	if (end) while (*(end-1) == ' ') --end;

	std::string in;
	if (end == 0) in.assign(start);
	else in.assign(start, end);

	size_t len;
	int status;
	char* unmangled = ::abi::__cxa_demangle(in.c_str(), 0, &len, &status);
	if (unmangled == 0) return in;
	std::string ret(unmangled);
	free(unmangled);
	return ret;
}
#elif defined WIN32

#undef _WIN32_WINNT
#define _WIN32_WINNT 0x0501 // XP

#include "windows.h"
#include "dbghelp.h"

std::string demangle(char const* name)
{
	char demangled_name[256];
	if (UnDecorateSymbolName(name, demangled_name, sizeof(demangled_name), UNDNAME_NO_THROW_SIGNATURES) == 0)
		demangled_name[0] = 0;
	return demangled_name;
}

#else
std::string demangle(char const* name) { return name; }
#endif

#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include "libtorrent/version.hpp"

// execinfo.h is available in the MacOS X 10.5 SDK.
#if (defined __linux__ || (defined __APPLE__ && MAC_OS_X_VERSION_MIN_REQUIRED >= 1050))
#include <execinfo.h>

void print_backtrace(char* out, int len)
{
	void* stack[50];
	int size = backtrace(stack, 50);
	char** symbols = backtrace_symbols(stack, size);

	for (int i = 1; i < size && len > 0; ++i)
	{
		int ret = snprintf(out, len, "%d: %s\n", i, demangle(symbols[i]).c_str());
		out += ret;
		len -= ret;
	}

	free(symbols);
}

#elif defined WIN32

#undef _WIN32_WINNT
#define _WIN32_WINNT 0x0501 // XP

#include "windows.h"
#include "libtorrent/utf8.hpp"

#include "winbase.h"
#include "dbghelp.h"

void print_backtrace(char* out, int len)
{
	typedef USHORT (*RtlCaptureStackBackTrace_t)(
		__in ULONG FramesToSkip,
		__in ULONG FramesToCapture,
		__out PVOID *BackTrace,
		__out_opt PULONG BackTraceHash);

	static RtlCaptureStackBackTrace_t RtlCaptureStackBackTrace = 0;

	if (RtlCaptureStackBackTrace == 0)
	{
		// we don't actually have to free this library, everyone has it loaded
		HMODULE lib = LoadLibrary(TEXT("kernel32.dll"));
		RtlCaptureStackBackTrace = (RtlCaptureStackBackTrace_t)GetProcAddress(lib, "RtlCaptureStackBackTrace");
		if (RtlCaptureStackBackTrace == 0)
		{
			out[0] = 0;
			return;
		}
	}

	int i;
	void* stack[50];
	int size = CaptureStackBackTrace(0, 50, stack, 0);

	SYMBOL_INFO* symbol = (SYMBOL_INFO*)calloc(sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR), 1);
	symbol->MaxNameLen = MAX_SYM_NAME;
	symbol->SizeOfStruct = sizeof(SYMBOL_INFO);

	HANDLE p = GetCurrentProcess();
	static bool sym_initialized = false;
	if (!sym_initialized)
	{
		sym_initialized = true;
		SymInitialize(p, NULL, true);
	}
	for (i = 0; i < size && len > 0; ++i)
	{
		int ret;
		if (SymFromAddr(p, uintptr_t(stack[i]), 0, symbol))
			ret = snprintf(out, len, "%d: %s\n", i, symbol->Name);
		else
			ret = snprintf(out, len, "%d: <unknown>\n", i);

		out += ret;
		len -= ret;
	}
	free(symbol);
}

#else

void print_backtrace(char* out, int len) {}

#endif

#if TORRENT_PRODUCTION_ASSERTS
char const* libtorrent_assert_log = "asserts.log";
#endif

TORRENT_EXPORT void assert_fail(char const* expr, int line, char const* file
	, char const* function, char const* value)
{
#if TORRENT_PRODUCTION_ASSERTS
	FILE* out = fopen(libtorrent_assert_log, "a+");
	if (out == 0) out = stderr;
#else
	FILE* out = stderr;
#endif

	char stack[8192];
	print_backtrace(stack, sizeof(stack));

	fprintf(out, "assertion failed. Please file a bugreport at "
		"http://code.rasterbar.com/libtorrent/newticket\n"
		"Please include the following information:\n\n"
		"version: " LIBTORRENT_VERSION "\n"
		"%s\n"
		"file: '%s'\n"
		"line: %d\n"
		"function: %s\n"
		"expression: %s\n"
		"%s%s\n"
		"stack:\n"
		"%s\n"
		, LIBTORRENT_REVISION, file, line, function, expr
		, value ? value : "", value ? "\n" : ""
		, stack);

	// if production asserts are defined, don't abort, just print the error
#if TORRENT_PRODUCTION_ASSERTS
	if (out != stderr) fclose(out);
#else
 	// send SIGINT to the current process
 	// to break into the debugger
 	raise(SIGINT);
 	abort();
#endif
}

#else

TORRENT_EXPORT void assert_fail(char const* expr, int line, char const* file, char const* function) {}

#endif

<|endoftext|>


<commit_before>#include "batoid.h"
#include "ray.h"
#include "surface.h"
#include "medium.h"
#include "utils.h"
#include "intersection.h"
#include <numeric>

namespace batoid{
    Ray reflect(const Ray& r, const Surface& surface) {
        if (r.failed)
            return Ray(true);
        double n = 1.0 / r.v.Magnitude();
        Vec3 nv = r.v * n;
        Vec3 normal = surface.normal(r.p0.x, r.p0.y);
        double c1 = DotProduct(nv, normal);
        return Ray(r.p0, (nv - 2*c1*normal).UnitVec3()/n, r.t0, r.wavelength, r.isVignetted);
    }

    std::vector<Ray> reflect(const std::vector<Ray>& rays, const Surface& surface) {
        auto result = std::vector<Ray>(rays.size());
        parallelTransform(
            rays.cbegin(), rays.cend(), result.begin(),
            [&](const Ray& r){ return reflect(r, surface); },
            2000
        );
        return result;
    }

    Ray refract(const Ray& r, const Surface& surface, const double n1, const double n2) {
        if (r.failed)
            return Ray(true);
        Vec3 nv = r.v * n1;
        Vec3 normal = surface.normal(r.p0.x, r.p0.y);
        double alpha = DotProduct(nv, normal);
        double a = 1.;
        double b = 2*alpha;
        double c = (1. - (n2*n2)/(n1*n1));
        double k1, k2;
        solveQuadratic(a, b, c, k1, k2);
        Vec3 f1 = (nv+k1*normal).UnitVec3();
        Vec3 f2 = (nv+k2*normal).UnitVec3();
        if (DotProduct(f1, nv) > DotProduct(f2, nv))
            return Ray(r.p0, f1/n2, r.t0, r.wavelength, r.isVignetted);
        else
            return Ray(r.p0, f2/n2, r.t0, r.wavelength, r.isVignetted);

    }

    std::vector<Ray> refract(const std::vector<Ray>& rays, const Surface& surface,
                             const double n1, const double n2) {
        auto result = std::vector<Ray>(rays.size());
        parallelTransform(
            rays.cbegin(), rays.cend(), result.begin(),
            [&](const Ray& r){ return refract(r, surface, n1, n2); },
            2000
        );
        return result;
    }

    Ray refract(const Ray& r, const Surface& surface, const Medium& m1, const Medium& m2) {
        if (r.failed)
            return Ray(true);
        double n1 = m1.getN(r.wavelength);
        double n2 = m2.getN(r.wavelength);
        return refract(r, surface, n1, n2);
    }

    std::vector<Ray> refract(const std::vector<Ray>& rays, const Surface& surface,
                             const Medium& m1, const Medium& m2) {
        auto result = std::vector<Ray>(rays.size());
        parallelTransform(
            rays.cbegin(), rays.cend(), result.begin(),
            [&](const Ray& r){ return refract(r, surface, m1, m2); },
            2000
        );
        return result;
    }

    std::vector<Ray> rayGrid(double dist, double length,
                             double xcos, double ycos,
                             int nside, double wavelength,
                             double n) {
        std::vector<Ray> result;
        result.reserve(nside*nside);

        // The "velocities" of all the rays in the grid are the same.
        auto v = Vec3(xcos, ycos, -sqrt(1-xcos*xcos-ycos*ycos))/n;

        double dx = length/(nside-1);
        double x0 = -length/2;
        double x = x0;
        for(int ix=0; ix<nside; ix++) {
            double y = x0;
            for(int iy=0; iy<nside; iy++) {
                Vec3 r(x,y,0);  // The position of the ray when it intersects the pupil
                // We want adjust the t0 of the Rays such that for a given time t, they all
                // lie on a plane perpendicular to v.  Can do this by solving
                // DotProduct(r + v*t + n*v*dist, v) == 0 for t
                // implies
                // t = -r.v / v.v - n*d
                //   = -r.v * n^2 - n*d
                double t = -DotProduct(r,v)*n*n - n*dist;
                result.push_back(Ray(r,v,-t,wavelength,false).propagatedToTime(0));
                y += dx;
            }
            x += dx;
        }
        return result;
    }

    std::vector<Ray> rayGrid(double dist, double length,
                             double xcos, double ycos,
                             int nside, double wavelength,
                             const Medium& m) {
        double n = m.getN(wavelength);
        return rayGrid(dist, length, xcos, ycos, nside, wavelength, n);
    }

    std::vector<Ray> circularGrid(double dist, double outer, double inner,
                                  double xcos, double ycos,
                                  int nradii, int naz, double wavelength, double n) {

        // Determine number of rays at each radius
        std::vector<int> nphis(nradii);
        double drfrac = (outer-inner)/(nradii-1)/outer;
        double rfrac = 1.0;
        for (int i=0; i<nradii; i++) {
            nphis[i] = int(std::ceil(naz*rfrac));
            rfrac -= drfrac;
        }
        int nray = std::accumulate(nphis.begin(), nphis.end(), 0);
        std::vector<Ray> result;
        result.reserve(nray);

        // The "velocities" of all the rays in the grid are the same.
        auto v = Vec3(xcos, ycos, -sqrt(1-xcos*xcos-ycos*ycos))/n;

        rfrac = 1.0;
        for (int i=0; i<nradii; i++) {
            double az = 0.0;
            double daz = 2*M_PI/nphis[i];
            double radius = rfrac*outer;
            for (int j=0; j<nphis[i]; j++) {
                Vec3 r(radius*std::cos(az), radius*std::sin(az), 0);
                double t = -DotProduct(r,v)*n*n - n*dist;
                result.push_back(Ray(r,v,-t,wavelength,false).propagatedToTime(0));
                az += daz;
            }
            rfrac -= drfrac;
        }
        return result;
    }

    std::vector<Ray> circularGrid(double dist, double outer, double inner,
                                  double xcos, double ycos,
                                  int nradii, int naz, double wavelength, const Medium& m) {
        double n = m.getN(wavelength);
        return circularGrid(dist, outer, inner, xcos, ycos, nradii, naz, wavelength, n);
    }

    std::vector<Ray> trimVignetted(const std::vector<Ray>& rays) {
        std::vector<Ray> result;
        result.reserve(rays.size());
        for (const auto& r : rays) {
            if (!r.isVignetted)
                result.push_back(r);
        }
        return result;
    }

    void trimVignettedInPlace(std::vector<Ray>& rays) {
        rays.erase(
            std::remove_if(
                rays.begin(),
                rays.end(),
                [](const Ray& r){ return r.isVignetted; }
            ),
            rays.end()
        );
    }

}
<commit_msg>failed means vignetted<commit_after>#include "batoid.h"
#include "ray.h"
#include "surface.h"
#include "medium.h"
#include "utils.h"
#include "intersection.h"
#include <numeric>

namespace batoid{
    Ray reflect(const Ray& r, const Surface& surface) {
        if (r.failed)
            return Ray(true);
        double n = 1.0 / r.v.Magnitude();
        Vec3 nv = r.v * n;
        Vec3 normal = surface.normal(r.p0.x, r.p0.y);
        double c1 = DotProduct(nv, normal);
        return Ray(r.p0, (nv - 2*c1*normal).UnitVec3()/n, r.t0, r.wavelength, r.isVignetted);
    }

    std::vector<Ray> reflect(const std::vector<Ray>& rays, const Surface& surface) {
        auto result = std::vector<Ray>(rays.size());
        parallelTransform(
            rays.cbegin(), rays.cend(), result.begin(),
            [&](const Ray& r){ return reflect(r, surface); },
            2000
        );
        return result;
    }

    Ray refract(const Ray& r, const Surface& surface, const double n1, const double n2) {
        if (r.failed)
            return Ray(true);
        Vec3 nv = r.v * n1;
        Vec3 normal = surface.normal(r.p0.x, r.p0.y);
        double alpha = DotProduct(nv, normal);
        double a = 1.;
        double b = 2*alpha;
        double c = (1. - (n2*n2)/(n1*n1));
        double k1, k2;
        solveQuadratic(a, b, c, k1, k2);
        Vec3 f1 = (nv+k1*normal).UnitVec3();
        Vec3 f2 = (nv+k2*normal).UnitVec3();
        if (DotProduct(f1, nv) > DotProduct(f2, nv))
            return Ray(r.p0, f1/n2, r.t0, r.wavelength, r.isVignetted);
        else
            return Ray(r.p0, f2/n2, r.t0, r.wavelength, r.isVignetted);

    }

    std::vector<Ray> refract(const std::vector<Ray>& rays, const Surface& surface,
                             const double n1, const double n2) {
        auto result = std::vector<Ray>(rays.size());
        parallelTransform(
            rays.cbegin(), rays.cend(), result.begin(),
            [&](const Ray& r){ return refract(r, surface, n1, n2); },
            2000
        );
        return result;
    }

    Ray refract(const Ray& r, const Surface& surface, const Medium& m1, const Medium& m2) {
        if (r.failed)
            return Ray(true);
        double n1 = m1.getN(r.wavelength);
        double n2 = m2.getN(r.wavelength);
        return refract(r, surface, n1, n2);
    }

    std::vector<Ray> refract(const std::vector<Ray>& rays, const Surface& surface,
                             const Medium& m1, const Medium& m2) {
        auto result = std::vector<Ray>(rays.size());
        parallelTransform(
            rays.cbegin(), rays.cend(), result.begin(),
            [&](const Ray& r){ return refract(r, surface, m1, m2); },
            2000
        );
        return result;
    }

    std::vector<Ray> rayGrid(double dist, double length,
                             double xcos, double ycos,
                             int nside, double wavelength,
                             double n) {
        std::vector<Ray> result;
        result.reserve(nside*nside);

        // The "velocities" of all the rays in the grid are the same.
        auto v = Vec3(xcos, ycos, -sqrt(1-xcos*xcos-ycos*ycos))/n;

        double dx = length/(nside-1);
        double x0 = -length/2;
        double x = x0;
        for(int ix=0; ix<nside; ix++) {
            double y = x0;
            for(int iy=0; iy<nside; iy++) {
                Vec3 r(x,y,0);  // The position of the ray when it intersects the pupil
                // We want adjust the t0 of the Rays such that for a given time t, they all
                // lie on a plane perpendicular to v.  Can do this by solving
                // DotProduct(r + v*t + n*v*dist, v) == 0 for t
                // implies
                // t = -r.v / v.v - n*d
                //   = -r.v * n^2 - n*d
                double t = -DotProduct(r,v)*n*n - n*dist;
                result.push_back(Ray(r,v,-t,wavelength,false).propagatedToTime(0));
                y += dx;
            }
            x += dx;
        }
        return result;
    }

    std::vector<Ray> rayGrid(double dist, double length,
                             double xcos, double ycos,
                             int nside, double wavelength,
                             const Medium& m) {
        double n = m.getN(wavelength);
        return rayGrid(dist, length, xcos, ycos, nside, wavelength, n);
    }

    std::vector<Ray> circularGrid(double dist, double outer, double inner,
                                  double xcos, double ycos,
                                  int nradii, int naz, double wavelength, double n) {

        // Determine number of rays at each radius
        std::vector<int> nphis(nradii);
        double drfrac = (outer-inner)/(nradii-1)/outer;
        double rfrac = 1.0;
        for (int i=0; i<nradii; i++) {
            nphis[i] = int(std::ceil(naz*rfrac));
            rfrac -= drfrac;
        }
        int nray = std::accumulate(nphis.begin(), nphis.end(), 0);
        std::vector<Ray> result;
        result.reserve(nray);

        // The "velocities" of all the rays in the grid are the same.
        auto v = Vec3(xcos, ycos, -sqrt(1-xcos*xcos-ycos*ycos))/n;

        rfrac = 1.0;
        for (int i=0; i<nradii; i++) {
            double az = 0.0;
            double daz = 2*M_PI/nphis[i];
            double radius = rfrac*outer;
            for (int j=0; j<nphis[i]; j++) {
                Vec3 r(radius*std::cos(az), radius*std::sin(az), 0);
                double t = -DotProduct(r,v)*n*n - n*dist;
                result.push_back(Ray(r,v,-t,wavelength,false).propagatedToTime(0));
                az += daz;
            }
            rfrac -= drfrac;
        }
        return result;
    }

    std::vector<Ray> circularGrid(double dist, double outer, double inner,
                                  double xcos, double ycos,
                                  int nradii, int naz, double wavelength, const Medium& m) {
        double n = m.getN(wavelength);
        return circularGrid(dist, outer, inner, xcos, ycos, nradii, naz, wavelength, n);
    }

    std::vector<Ray> trimVignetted(const std::vector<Ray>& rays) {
        std::vector<Ray> result;
        result.reserve(rays.size());
        for (const auto& r : rays) {
            if (!r.isVignetted)
                result.push_back(r);
        }
        return result;
    }

    void trimVignettedInPlace(std::vector<Ray>& rays) {
        rays.erase(
            std::remove_if(
                rays.begin(),
                rays.end(),
                [](const Ray& r){ return r.failed || r.isVignetted; }
            ),
            rays.end()
        );
    }

}
<|endoftext|>


<commit_before>/***********************************************************************
    filename:   CEGUIOpenGLGeometryBuffer.cpp
    created:    Thu Jan 8 2009
    authors:    Paul D Turner <paul@cegui.org.uk>
                Lukas E Meindl
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2013 Paul D Turner & The CEGUI Development Team
 *
 *   Permission is hereby granted, free of charge, to any person obtaining
 *   a copy of this software and associated documentation files (the
 *   "Software"), to deal in the Software without restriction, including
 *   without limitation the rights to use, copy, modify, merge, publish,
 *   distribute, sublicense, and/or sell copies of the Software, and to
 *   permit persons to whom the Software is furnished to do so, subject to
 *   the following conditions:
 *
 *   The above copyright notice and this permission notice shall be
 *   included in all copies or substantial portions of the Software.
 *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *   OTHER DEALINGS IN THE SOFTWARE.
 ***************************************************************************/
#include <GL/glew.h>
#include "CEGUI/RendererModules/OpenGL/GLGeometryBuffer.h"
#include "CEGUI/RendererModules/OpenGL/GLRenderer.h"
#include "CEGUI/RenderEffect.h"
#include "CEGUI/Vertex.h"
#include "CEGUI/RendererModules/OpenGL/GlmPimpl.h"
#include "glm/gtc/type_ptr.hpp"

// Start of CEGUI namespace section
namespace CEGUI
{
//----------------------------------------------------------------------------//
OpenGLGeometryBuffer::OpenGLGeometryBuffer(OpenGLRenderer& owner, CEGUI::RefCounted<RenderMaterial> renderMaterial) :
    OpenGLGeometryBufferBase(owner, renderMaterial)
{
}

//----------------------------------------------------------------------------//
void OpenGLGeometryBuffer::draw() const
{
    if(d_vertexData.empty())
        return;

    CEGUI::Rectf viewPort = d_owner->getActiveViewPort();

    if (d_clippingActive)
    {
        glScissor(static_cast<GLint>(d_clipRect.left()),
            static_cast<GLint>(viewPort.getHeight() - d_clipRect.bottom()),
            static_cast<GLint>(d_clipRect.getWidth()),
            static_cast<GLint>(d_clipRect.getHeight()));

        glEnable(GL_SCISSOR_TEST);
    }
    else
        glDisable(GL_SCISSOR_TEST);

    // apply the transformations we need to use.
    if (!d_matrixValid)
        updateMatrix();

    glMatrixMode(GL_MODELVIEW);
    glLoadMatrixf(glm::value_ptr(d_matrix->d_matrix));

    // activate desired blending mode
    d_owner->setupRenderingBlendMode(d_blendMode);

    const int pass_count = d_effect ? d_effect->getPassCount() : 1;
    for (int pass = 0; pass < pass_count; ++pass)
    {
        // set up RenderEffect
        if (d_effect)
            d_effect->performPreRenderFunctions(pass);

        d_renderMaterial->prepareForRendering();

        setupVertexDataPointers();

        // draw the geometry
        glDrawArrays(GL_TRIANGLES, 0, d_vertexCount);
    }

    // clean up RenderEffect
    if (d_effect)
        d_effect->performPostRenderFunctions();
}

//----------------------------------------------------------------------------//
void OpenGLGeometryBuffer::finaliseVertexAttributes()
{
}

//----------------------------------------------------------------------------//
void OpenGLGeometryBuffer::setupVertexDataPointers() const
{
    //Update the fixed function vertex pointers to our vertex data depending on the defined attributes
    int dataOffset = 0;
    GLsizei stride = getVertexAttributeElementCount() * sizeof(GL_FLOAT);

    const size_t attribute_count = d_vertexAttributes.size();
    for (size_t i = 0; i < attribute_count; ++i)
    {
        switch(d_vertexAttributes.at(i))
        {
        case VAT_POSITION0:
            {
                glVertexPointer(3, GL_FLOAT, stride,
                    &d_vertexData[dataOffset]);
                dataOffset += 3;
            }
            break;
        case VAT_COLOUR0:
            {
                glColorPointer(4, GL_FLOAT, stride,
                    &d_vertexData[dataOffset]);
                dataOffset += 4;
            }
            break;
        case VAT_TEXCOORD0:
            {
                glTexCoordPointer(2, GL_FLOAT, stride,
                    &d_vertexData[dataOffset]);
                dataOffset += 2;
            }
            break;
        default:
            break;
        }
    }

    if(attribute_count == 2)
        glDisable(GL_TEXTURE);
    else
        glEnable(GL_TEXTURE);
}

//----------------------------------------------------------------------------//

} // End of  CEGUI namespace section

<commit_msg>MOD: Removed unnecessary code<commit_after>/***********************************************************************
    filename:   CEGUIOpenGLGeometryBuffer.cpp
    created:    Thu Jan 8 2009
    authors:    Paul D Turner <paul@cegui.org.uk>
                Lukas E Meindl
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2013 Paul D Turner & The CEGUI Development Team
 *
 *   Permission is hereby granted, free of charge, to any person obtaining
 *   a copy of this software and associated documentation files (the
 *   "Software"), to deal in the Software without restriction, including
 *   without limitation the rights to use, copy, modify, merge, publish,
 *   distribute, sublicense, and/or sell copies of the Software, and to
 *   permit persons to whom the Software is furnished to do so, subject to
 *   the following conditions:
 *
 *   The above copyright notice and this permission notice shall be
 *   included in all copies or substantial portions of the Software.
 *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *   OTHER DEALINGS IN THE SOFTWARE.
 ***************************************************************************/
#include <GL/glew.h>
#include "CEGUI/RendererModules/OpenGL/GLGeometryBuffer.h"
#include "CEGUI/RendererModules/OpenGL/GLRenderer.h"
#include "CEGUI/RenderEffect.h"
#include "CEGUI/Vertex.h"
#include "CEGUI/RendererModules/OpenGL/GlmPimpl.h"
#include "glm/gtc/type_ptr.hpp"

// Start of CEGUI namespace section
namespace CEGUI
{
//----------------------------------------------------------------------------//
OpenGLGeometryBuffer::OpenGLGeometryBuffer(OpenGLRenderer& owner, CEGUI::RefCounted<RenderMaterial> renderMaterial) :
    OpenGLGeometryBufferBase(owner, renderMaterial)
{
}

//----------------------------------------------------------------------------//
void OpenGLGeometryBuffer::draw() const
{
    if(d_vertexData.empty())
        return;

    CEGUI::Rectf viewPort = d_owner->getActiveViewPort();

    if (d_clippingActive)
    {
        glScissor(static_cast<GLint>(d_clipRect.left()),
            static_cast<GLint>(viewPort.getHeight() - d_clipRect.bottom()),
            static_cast<GLint>(d_clipRect.getWidth()),
            static_cast<GLint>(d_clipRect.getHeight()));

        glEnable(GL_SCISSOR_TEST);
    }
    else
        glDisable(GL_SCISSOR_TEST);

    // apply the transformations we need to use.
    if (!d_matrixValid)
        updateMatrix();

    glMatrixMode(GL_MODELVIEW);
    glLoadMatrixf(glm::value_ptr(d_matrix->d_matrix));

    // activate desired blending mode
    d_owner->setupRenderingBlendMode(d_blendMode);

    const int pass_count = d_effect ? d_effect->getPassCount() : 1;
    for (int pass = 0; pass < pass_count; ++pass)
    {
        // set up RenderEffect
        if (d_effect)
            d_effect->performPreRenderFunctions(pass);

        d_renderMaterial->prepareForRendering();

        setupVertexDataPointers();

        // draw the geometry
        glDrawArrays(GL_TRIANGLES, 0, d_vertexCount);
    }

    // clean up RenderEffect
    if (d_effect)
        d_effect->performPostRenderFunctions();
}

//----------------------------------------------------------------------------//
void OpenGLGeometryBuffer::finaliseVertexAttributes()
{
}

//----------------------------------------------------------------------------//
void OpenGLGeometryBuffer::setupVertexDataPointers() const
{
    //Update the fixed function vertex pointers to our vertex data depending on the defined attributes
    int dataOffset = 0;
    GLsizei stride = getVertexAttributeElementCount() * sizeof(GL_FLOAT);

    const size_t attribute_count = d_vertexAttributes.size();
    for (size_t i = 0; i < attribute_count; ++i)
    {
        switch(d_vertexAttributes.at(i))
        {
        case VAT_POSITION0:
            {
                glVertexPointer(3, GL_FLOAT, stride,
                    &d_vertexData[dataOffset]);
                dataOffset += 3;
            }
            break;
        case VAT_COLOUR0:
            {
                glColorPointer(4, GL_FLOAT, stride,
                    &d_vertexData[dataOffset]);
                dataOffset += 4;
            }
            break;
        case VAT_TEXCOORD0:
            {
                glTexCoordPointer(2, GL_FLOAT, stride,
                    &d_vertexData[dataOffset]);
                dataOffset += 2;
            }
            break;
        default:
            break;
        }
    }
}

//----------------------------------------------------------------------------//

} // End of  CEGUI namespace section

<|endoftext|>


<commit_before>#include <node.h>
#include <node_buffer.h>
#include <nan.h>

#include <stdlib.h>
#include <math.h>

extern "C" {
#include "base91.h"
}

using namespace node;
using namespace v8;

NAN_METHOD(B91Encode) {
  NanScope();
  struct basE91 b91;
  Local<String> result;

  if (args.Length() < 1)
    return NanThrowTypeError("Missing data source (string or Buffer)");

  if (args[0]->IsString()) {
    String::Utf8Value data(args[0]);
    size_t datalen = data.length();
    if (datalen > 0) {
      char* obuf = (char*)malloc(floor(1.25 * datalen));
      basE91_init(&b91);
      int ototal = 0;
      char* ibuf = *data;
      ototal += basE91_encode(&b91, ibuf, datalen, obuf);
      ototal += basE91_encode_end(&b91, obuf + ototal);
      result = NanNew<String>((const char*)obuf, ototal);
      free(obuf);
    } else
      result = NanNew<String>();
  } else if (Buffer::HasInstance(args[0])) {
#if NODE_MAJOR_VERSION == 0 && NODE_MINOR_VERSION < 10
    Local<Object> buf = args[0]->ToObject();
#else
    Local<Value> buf = args[0];
#endif
    char* data = Buffer::Data(buf);
    size_t datalen = Buffer::Length(buf);

    if (datalen > 0) {
      char* obuf = (char*)malloc(floor(1.25 * datalen));
      basE91_init(&b91);
      int ototal = 0;
      ototal += basE91_encode(&b91, data, datalen, obuf);
      ototal += basE91_encode_end(&b91, obuf + ototal);
      result = NanNew<String>((const char*)obuf, ototal);
      free(obuf);
    } else
      result = NanNew<String>();
  } else
    return NanThrowTypeError("Data source not string or Buffer");

  NanReturnValue(result);
}

NAN_METHOD(B91Decode) {
  NanScope();
  struct basE91 b91;
  Buffer *result = NULL;

  if (args.Length() < 1)
    return NanThrowTypeError("Missing string data source");

  if (args[0]->IsString()) {
    String::Utf8Value data(args[0]);
    size_t datalen = data.length();
    if (datalen > 0) {
      char* obuf = (char*)malloc(datalen);
      basE91_init(&b91);
      size_t ototal = 0;
      ototal += basE91_decode(&b91, *data, datalen, obuf);
      ototal += basE91_decode_end(&b91, obuf + ototal);
      result = Buffer::New((const char*)obuf, ototal);
      free(obuf);
    }
  } else
    return NanThrowTypeError("Data source not string");

  if (result != NULL)
    NanReturnValue(result->handle_);
  else
    NanReturnValue(NanNull());
}

extern "C" {
  void init(Handle<Object> target) {
    NanScope();
    target->Set(NanNew<String>("encode"),
                NanNew<FunctionTemplate>(B91Encode)->GetFunction());
    target->Set(NanNew<String>("decode"),
                NanNew<FunctionTemplate>(B91Decode)->GetFunction());
  }

  NODE_MODULE(base91encdec, init);
}
<commit_msg>binding: fix Buffer usage<commit_after>#include <node.h>
#include <node_buffer.h>
#include <nan.h>

#include <stdlib.h>
#include <math.h>

extern "C" {
#include "base91.h"
}

using namespace v8;

static NAN_METHOD(B91Encode) {
  NanScope();
  struct basE91 b91;
  Local<String> result;

  if (args.Length() < 1)
    return NanThrowTypeError("Missing data source (string or Buffer)");

  if (args[0]->IsString()) {
    String::Utf8Value data(args[0]);
    size_t datalen = data.length();
    if (datalen > 0) {
      char* obuf = (char*)malloc(floor(1.25 * datalen));
      basE91_init(&b91);
      int ototal = 0;
      char* ibuf = *data;
      ototal += basE91_encode(&b91, ibuf, datalen, obuf);
      ototal += basE91_encode_end(&b91, obuf + ototal);
      result = NanNew<String>((const char*)obuf, ototal);
      free(obuf);
    } else
      result = NanNew<String>();
  } else if (node::Buffer::HasInstance(args[0])) {
#if NODE_MAJOR_VERSION == 0 && NODE_MINOR_VERSION < 10
    Local<Object> buf = args[0]->ToObject();
#else
    Local<Value> buf = args[0];
#endif
    char* data = node::Buffer::Data(buf);
    size_t datalen = node::Buffer::Length(buf);

    if (datalen > 0) {
      char* obuf = (char*)malloc(floor(1.25 * datalen));
      basE91_init(&b91);
      int ototal = 0;
      ototal += basE91_encode(&b91, data, datalen, obuf);
      ototal += basE91_encode_end(&b91, obuf + ototal);
      result = NanNew<String>((const char*)obuf, ototal);
      free(obuf);
    } else
      result = NanNew<String>();
  } else
    return NanThrowTypeError("Data source not string or Buffer");

  NanReturnValue(result);
}

static NAN_METHOD(B91Decode) {
  NanScope();

  if (args.Length() < 1)
    return NanThrowTypeError("Missing string data source");

  if (args[0]->IsString()) {
    String::Utf8Value data(args[0]);
    size_t datalen = data.length();
    struct basE91 b91;
    if (datalen > 0) {
      char* obuf = (char*)malloc(datalen);
      basE91_init(&b91);
      size_t ototal = 0;
      ototal += basE91_decode(&b91, *data, datalen, obuf);
      ototal += basE91_decode_end(&b91, obuf + ototal);
      NanReturnValue(NanBufferUse(obuf, ototal));
    } else
      NanReturnValue(NanNull());
  }

  NanThrowTypeError("Data source not string");
}

extern "C" {
  void init(Handle<Object> target) {
    NanScope();
    target->Set(NanNew<String>("encode"),
                NanNew<FunctionTemplate>(B91Encode)->GetFunction());
    target->Set(NanNew<String>("decode"),
                NanNew<FunctionTemplate>(B91Decode)->GetFunction());
  }

  NODE_MODULE(base91encdec, init);
}
<|endoftext|>


<commit_before>#pragma once
/*
	_ExtInt is for only clang-12 or before
	clang-14 does not support it.
	so use a generated ll by clang-12.
	If gcc and clang supports _BitInt then replace them.
	cpp ->(clang -emit-llvm)-> bc ->(llvm-dis) -> ll
*/

#include <mcl/config.hpp>
#include <assert.h>
#ifdef _MSC_VER
#include <intrin.h>
#endif
#include "bitint_proto.hpp"

namespace mcl { namespace bint {

inline uint64_t make64(uint32_t H, uint32_t L)
{
	return ((uint64_t)H << 32) | L;
}

inline void split64(uint32_t *H, uint32_t *L, uint64_t x)
{
	*H = uint32_t(x >> 32);
	*L = uint32_t(x);
}

// return the real size of x
// return 1 if x[n] == 0
inline size_t getRealSize(const Unit *x, size_t n)
{
	while (n > 0) {
		if (x[n - 1]) break;
		n--;
	}
	return n > 0 ? n : 1;
}

/*
	[H:L] <= x * y
	@return L
*/
inline uint32_t mulUnit1(uint32_t *pH, uint32_t x, uint32_t y)
{
	uint64_t t = uint64_t(x) * y;
	uint32_t L;
	split64(pH, &L, t);
	return L;
}

/*
	q = [H:L] / y
	r = [H:L] % y
	return q
*/
inline uint32_t divUnit1(uint32_t *pr, uint32_t H, uint32_t L, uint32_t y)
{
	assert(y != 0);
	uint64_t t = make64(H, L);
	uint32_t q = uint32_t(t / y);
	*pr = uint32_t(t % y);
	return q;
}

#if MCL_SIZEOF_UNIT == 8
inline uint64_t mulUnit1(uint64_t *pH, uint64_t x, uint64_t y)
{
#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && !defined(__clang__)
	return _umul128(x, y, pH);
#else
	typedef __attribute__((mode(TI))) unsigned int uint128;
	uint128 t = uint128(x) * y;
	*pH = uint64_t(t >> 64);
	return uint64_t(t);
#endif
}

inline uint64_t divUnit1(uint64_t *pr, uint64_t H, uint64_t L, uint64_t y)
{
	assert(y != 0);
#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && !defined(__clang__)
	return _udiv128(H, L, y, pr);
#else
	typedef __attribute__((mode(TI))) unsigned int uint128;
	uint128 t = (uint128(H) << 64) | L;
	uint64_t q = uint64_t(t / y);
	*pr = uint64_t(t % y);
	return q;
#endif
}

#endif // MCL_SIZEOF_UNIT == 8

template<size_t N>
struct BitInt {
	static const size_t bitSize = sizeof(Unit) * 8 * N;
	typedef unsigned _ExtInt(bitSize) Type;
	Type v;
	Unit getTopUnit() const
	{
		return static_cast<Unit>(v >> (bitSize - sizeof(Unit) * 8));
	}
	Unit getMSB() const
	{
		return getTopUnit() >> (sizeof(Unit) * 8 - 1);
	}
	static const BitInt<N>& load(const void *x)
	{
		return *(const BitInt<N>*)x;
	}
	void save(void *x) const
	{
		*(BitInt<N>*)(x) = *this;
	}
	template<size_t M>
	BitInt<M> cvt() const
	{
		BitInt<M> ret;
		ret.v = static_cast<typename BitInt<M>::Type>(this->v);
		return ret;
	}
};

// true if x[N] == y[N]
template<size_t N>
bool cmpEqT(const Unit *px, const Unit *py)
{
	const auto& x = BitInt<N>::load(px);
	const auto& y = BitInt<N>::load(py);
	return x.v == y.v;
}

// true if x[N] >= y[N]
template<size_t N>
bool cmpGeT(const Unit *px, const Unit *py)
{
	const auto& x = BitInt<N>::load(px);
	const auto& y = BitInt<N>::load(py);
	return x.v >= y.v;
}

// true if x[N] > y[N]
template<size_t N>
bool cmpGtT(const Unit *px, const Unit *py)
{
	const auto& x = BitInt<N>::load(px);
	const auto& y = BitInt<N>::load(py);
	return x.v > y.v;
}

// true if x[N] <= y[N]
template<size_t N>
bool cmpLeT(const Unit *px, const Unit *py)
{
	return !cmpGtT<N>(px, py);
}

// true if x[N] < y[N]
template<size_t N>
bool cmpLtT(const Unit *px, const Unit *py)
{
	return !cmpGeT<N>(px, py);
}

// z[N] = x[N] + y[N] and return CF(0 or 1)
#if 0
template<size_t N>
Unit addT(Unit *pz, const Unit *px, const Unit *py)
{
	auto x = BitInt<N>::load(px).template cvt<N+1>();
	auto y = BitInt<N>::load(py).template cvt<N+1>();
	BitInt<N+1> z;
	z.v = x.v + y.v;
	z.template cvt<N>().save(pz);
	return z.getTopUnit();
}

// z[N] = x[N] - y[N] and return CF(0 or 1)
template<size_t N>
Unit subT(Unit *pz, const Unit *px, const Unit *py)
{
	auto x = BitInt<N>::load(px).template cvt<N+1>();
	auto y = BitInt<N>::load(py).template cvt<N+1>();
	BitInt<N+1> z;
	z.v = x.v - y.v;
	z.template cvt<N>().save(pz);
	return z.getMSB();
}
#endif

// [ret:z[N]] = x[N] * y
template<size_t N>
Unit mulUnitT(Unit *pz, const Unit *px, Unit y)
{
	auto x = BitInt<N>::load(px).template cvt<N+1>();
	BitInt<1> y1;
	BitInt<N+1> z;
	y1.v = y;
	z.v = x.v * y1.template cvt<N+1>().v;
	z.template cvt<N>().save(pz);
	return z.getTopUnit();
}

// [ret:z[N]] = z[N] + x[N] * y
template<size_t N>
Unit mulUnitAddT(Unit *pz, const Unit *px, Unit y)
{
	auto x = BitInt<N>::load(px).template cvt<N+1>();
	auto z = BitInt<N>::load(pz).template cvt<N+1>();
	BitInt<1> y1;
	y1.v = y;
	z.v += x.v * y1.template cvt<N+1>().v;
	z.template cvt<N>().save(pz);
	return z.getTopUnit();
}

// z[2N] = x[N] * y[N]
template<size_t N>
void mulT(Unit *pz, const Unit *px, const Unit *py)
{
	pz[N] = mulUnitT<N>(pz, px, py[0]);
	for (size_t i = 1; i < N; i++) {
		pz[N + i] = mulUnitAddT<N>(&pz[i], px, py[i]);
	}
}

// [ret:z[N]] = x[N] << y
template<size_t N>
Unit shlT(Unit *pz, const Unit *px, Unit y)
{
	assert(0 < y && y < sizeof(Unit) * 8);
	auto x = BitInt<N>::load(px).template cvt<N+1>();
	BitInt<N+1> z;
	z.v = x.v << y;
	z.template cvt<N>().save(pz);
	return z.getTopUnit();
}

// z[N] = x[N] >> y
template<size_t N>
void shrT(Unit *pz, const Unit *px, Unit y)
{
	assert(0 < y && y < sizeof(Unit) * 8);
	auto x = BitInt<N>::load(px);
	x.v >>= y;
	x.template cvt<N>().save(pz);
}

// z[n] = x[n] + y
inline Unit addUnit(Unit *z, const Unit *x, size_t n, Unit y)
{
	assert(n > 0);
	Unit t = x[0] + y;
	z[0] = t;
	size_t i = 0;
	if (t >= y) goto EXIT_0;
	i = 1;
	for (; i < n; i++) {
		t = x[i] + 1;
		z[i] = t;
		if (t != 0) goto EXIT_0;
	}
	return 1;
EXIT_0:
	i++;
	for (; i < n; i++) {
		z[i] = x[i];
	}
	return 0;
}
// x[n] += y
inline Unit addUnit(Unit *x, size_t n, Unit y)
{
	assert(n > 0);
	Unit t = x[0] + y;
	x[0] = t;
	size_t i = 0;
	if (t >= y) return 0;
	i = 1;
	for (; i < n; i++) {
		t = x[i] + 1;
		x[i] = t;
		if (t != 0) return 0;
	}
	return 1;
}

// z[n] = x[n] - y
inline Unit subUnit(Unit *z, const Unit *x, size_t n, Unit y)
{
	assert(n > 0);
	Unit c = x[0] < y ? 1 : 0;
	z[0] = x[0] - y;
	for (size_t i = 1; i < n; i++) {
		if (x[i] < c) {
			z[i] = Unit(-1);
		} else {
			z[i] = x[i] - c;
			c = 0;
		}
	}
	return c;
}

/*
	q[] = x[] / y
	@retval r = x[] % y
	accept q == x
*/
inline Unit divUnit(Unit *q, const Unit *x, size_t n, Unit y)
{
	assert(n > 0);
	Unit r = 0;
	for (int i = (int)n - 1; i >= 0; i--) {
		q[i] = divUnit1(&r, r, x[i], y);
	}
	return r;
}
/*
	q[] = x[] / y
	@retval r = x[] % y
*/
inline Unit modUnit(const Unit *x, size_t n, Unit y)
{
	assert(n > 0);
	Unit r = 0;
	for (int i = (int)n - 1; i >= 0; i--) {
		divUnit1(&r, r, x[i], y);
	}
	return r;
}

// x[n] = 0
inline void clear(Unit *x, size_t n)
{
	for (size_t i = 0; i < n; i++) x[i] = 0;
}

template<size_t N>
struct FuncT {
	static inline Unit add(Unit *z, const Unit *x, const Unit *y)
	{
		return addT<N>(z, x, y);
	}
	static inline Unit sub(Unit *z, const Unit *x, const Unit *y)
	{
		return subT<N>(z, x, y);
	}
	static inline Unit mulUnit(Unit *z, const Unit *x, Unit y)
	{
		return mulUnitT<N>(z, x, y);
	}
	static inline bool cmpGe(const Unit *x, const Unit *y)
	{
		return cmpGeT<N>(x, y);
	}
};
/*
	y must be sizeof(Unit) * 8 * N bit
	x[xn] = x[xn] % y[N]
	q[qn] = x[xn] / y[N] if q != NULL
	return new xn
*/
template<typename Func, size_t N>
size_t divFullBitT(Unit *q, size_t qn, Unit *x, size_t xn, const Unit *y)
{
	assert(xn > 0);
	assert((y[N - 1] >> (sizeof(Unit) * 8 - 1)) != 0);
	assert(q != x && q != y && x != y);
	if (q) clear(q, qn);
	Unit *t = (Unit*)CYBOZU_ALLOCA(sizeof(Unit) * N + 1);
	while (xn > N) {
		if (x[xn - 1] == 0) {
			xn--;
			continue;
		}
		size_t d = xn - N;
		if (Func::cmpGe(x + d, y)) {
			Func::sub(x + d, x + d, y);
			if (q) addUnit(q + d, qn - d, 1);
		} else {
			Unit xTop = x[xn - 1];
			if (xTop == 1) {
				Unit ret = Func::sub(x + d - 1, x + d - 1, y);
				x[xn-1] -= ret;
			} else {
				Unit ret = Func::mulUnit(t, y, xTop);
				ret += Func::sub(x + d - 1, x + d - 1, t);
				x[xn-1] -= ret;
			}
			if (q) addUnit(q + d - 1, qn - d + 1, xTop);
		}
	}
	if (Func::cmpGe(x, y)) {
		Func::sub(x, x, y);
		if (q) addUnit(q, qn, 1);
	}
	xn = getRealSize(x, xn);
	return xn;
}

} } // mcl::bint

<commit_msg>fix typo<commit_after>#pragma once
/*
	_ExtInt is for only clang-12 or before
	clang-14 does not support it.
	so use a generated ll by clang-12.
	If gcc and clang supports _BitInt then replace them.
	cpp ->(clang -emit-llvm)-> bc ->(llvm-dis) -> ll
*/

#include <mcl/config.hpp>
#include <assert.h>
#ifdef _MSC_VER
#include <intrin.h>
#endif
#include "bitint_proto.hpp"

namespace mcl { namespace bint {

inline uint64_t make64(uint32_t H, uint32_t L)
{
	return ((uint64_t)H << 32) | L;
}

inline void split64(uint32_t *H, uint32_t *L, uint64_t x)
{
	*H = uint32_t(x >> 32);
	*L = uint32_t(x);
}

// return the real size of x
// return 1 if x[n] == 0
inline size_t getRealSize(const Unit *x, size_t n)
{
	while (n > 0) {
		if (x[n - 1]) break;
		n--;
	}
	return n > 0 ? n : 1;
}

/*
	[H:L] <= x * y
	@return L
*/
inline uint32_t mulUnit1(uint32_t *pH, uint32_t x, uint32_t y)
{
	uint64_t t = uint64_t(x) * y;
	uint32_t L;
	split64(pH, &L, t);
	return L;
}

/*
	q = [H:L] / y
	r = [H:L] % y
	return q
*/
inline uint32_t divUnit1(uint32_t *pr, uint32_t H, uint32_t L, uint32_t y)
{
	assert(y != 0);
	uint64_t t = make64(H, L);
	uint32_t q = uint32_t(t / y);
	*pr = uint32_t(t % y);
	return q;
}

#if MCL_SIZEOF_UNIT == 8
inline uint64_t mulUnit1(uint64_t *pH, uint64_t x, uint64_t y)
{
#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && !defined(__clang__)
	return _umul128(x, y, pH);
#else
	typedef __attribute__((mode(TI))) unsigned int uint128;
	uint128 t = uint128(x) * y;
	*pH = uint64_t(t >> 64);
	return uint64_t(t);
#endif
}

inline uint64_t divUnit1(uint64_t *pr, uint64_t H, uint64_t L, uint64_t y)
{
	assert(y != 0);
#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && !defined(__clang__)
	return _udiv128(H, L, y, pr);
#else
	typedef __attribute__((mode(TI))) unsigned int uint128;
	uint128 t = (uint128(H) << 64) | L;
	uint64_t q = uint64_t(t / y);
	*pr = uint64_t(t % y);
	return q;
#endif
}

#endif // MCL_SIZEOF_UNIT == 8

template<size_t N>
struct BitInt {
	static const size_t bitSize = sizeof(Unit) * 8 * N;
	typedef unsigned _ExtInt(bitSize) Type;
	Type v;
	Unit getTopUnit() const
	{
		return static_cast<Unit>(v >> (bitSize - sizeof(Unit) * 8));
	}
	Unit getMSB() const
	{
		return getTopUnit() >> (sizeof(Unit) * 8 - 1);
	}
	static const BitInt<N>& load(const void *x)
	{
		return *(const BitInt<N>*)x;
	}
	void save(void *x) const
	{
		*(BitInt<N>*)(x) = *this;
	}
	template<size_t M>
	BitInt<M> cvt() const
	{
		BitInt<M> ret;
		ret.v = static_cast<typename BitInt<M>::Type>(this->v);
		return ret;
	}
};

// true if x[N] == y[N]
template<size_t N>
bool cmpEqT(const Unit *px, const Unit *py)
{
	const auto& x = BitInt<N>::load(px);
	const auto& y = BitInt<N>::load(py);
	return x.v == y.v;
}

// true if x[N] >= y[N]
template<size_t N>
bool cmpGeT(const Unit *px, const Unit *py)
{
	const auto& x = BitInt<N>::load(px);
	const auto& y = BitInt<N>::load(py);
	return x.v >= y.v;
}

// true if x[N] > y[N]
template<size_t N>
bool cmpGtT(const Unit *px, const Unit *py)
{
	const auto& x = BitInt<N>::load(px);
	const auto& y = BitInt<N>::load(py);
	return x.v > y.v;
}

// true if x[N] <= y[N]
template<size_t N>
bool cmpLeT(const Unit *px, const Unit *py)
{
	return !cmpGtT<N>(px, py);
}

// true if x[N] < y[N]
template<size_t N>
bool cmpLtT(const Unit *px, const Unit *py)
{
	return !cmpGeT<N>(px, py);
}

// z[N] = x[N] + y[N] and return CF(0 or 1)
#if 0
template<size_t N>
Unit addT(Unit *pz, const Unit *px, const Unit *py)
{
	auto x = BitInt<N>::load(px).template cvt<N+1>();
	auto y = BitInt<N>::load(py).template cvt<N+1>();
	BitInt<N+1> z;
	z.v = x.v + y.v;
	z.template cvt<N>().save(pz);
	return z.getTopUnit();
}

// z[N] = x[N] - y[N] and return CF(0 or 1)
template<size_t N>
Unit subT(Unit *pz, const Unit *px, const Unit *py)
{
	auto x = BitInt<N>::load(px).template cvt<N+1>();
	auto y = BitInt<N>::load(py).template cvt<N+1>();
	BitInt<N+1> z;
	z.v = x.v - y.v;
	z.template cvt<N>().save(pz);
	return z.getMSB();
}
#endif

// [ret:z[N]] = x[N] * y
template<size_t N>
Unit mulUnitT(Unit *pz, const Unit *px, Unit y)
{
	auto x = BitInt<N>::load(px).template cvt<N+1>();
	BitInt<1> y1;
	BitInt<N+1> z;
	y1.v = y;
	z.v = x.v * y1.template cvt<N+1>().v;
	z.template cvt<N>().save(pz);
	return z.getTopUnit();
}

// [ret:z[N]] = z[N] + x[N] * y
template<size_t N>
Unit mulUnitAddT(Unit *pz, const Unit *px, Unit y)
{
	auto x = BitInt<N>::load(px).template cvt<N+1>();
	auto z = BitInt<N>::load(pz).template cvt<N+1>();
	BitInt<1> y1;
	y1.v = y;
	z.v += x.v * y1.template cvt<N+1>().v;
	z.template cvt<N>().save(pz);
	return z.getTopUnit();
}

// z[2N] = x[N] * y[N]
template<size_t N>
void mulT(Unit *pz, const Unit *px, const Unit *py)
{
	pz[N] = mulUnitT<N>(pz, px, py[0]);
	for (size_t i = 1; i < N; i++) {
		pz[N + i] = mulUnitAddT<N>(&pz[i], px, py[i]);
	}
}

// [ret:z[N]] = x[N] << y
template<size_t N>
Unit shlT(Unit *pz, const Unit *px, Unit y)
{
	assert(0 < y && y < sizeof(Unit) * 8);
	auto x = BitInt<N>::load(px).template cvt<N+1>();
	BitInt<N+1> z;
	z.v = x.v << y;
	z.template cvt<N>().save(pz);
	return z.getTopUnit();
}

// z[N] = x[N] >> y
template<size_t N>
void shrT(Unit *pz, const Unit *px, Unit y)
{
	assert(0 < y && y < sizeof(Unit) * 8);
	auto x = BitInt<N>::load(px);
	x.v >>= y;
	x.template cvt<N>().save(pz);
}

// z[n] = x[n] + y
inline Unit addUnit(Unit *z, const Unit *x, size_t n, Unit y)
{
	assert(n > 0);
	Unit t = x[0] + y;
	z[0] = t;
	size_t i = 0;
	if (t >= y) goto EXIT_0;
	i = 1;
	for (; i < n; i++) {
		t = x[i] + 1;
		z[i] = t;
		if (t != 0) goto EXIT_0;
	}
	return 1;
EXIT_0:
	i++;
	for (; i < n; i++) {
		z[i] = x[i];
	}
	return 0;
}
// x[n] += y
inline Unit addUnit(Unit *x, size_t n, Unit y)
{
	assert(n > 0);
	Unit t = x[0] + y;
	x[0] = t;
	size_t i = 0;
	if (t >= y) return 0;
	i = 1;
	for (; i < n; i++) {
		t = x[i] + 1;
		x[i] = t;
		if (t != 0) return 0;
	}
	return 1;
}

// z[n] = x[n] - y
inline Unit subUnit(Unit *z, const Unit *x, size_t n, Unit y)
{
	assert(n > 0);
	Unit c = x[0] < y ? 1 : 0;
	z[0] = x[0] - y;
	for (size_t i = 1; i < n; i++) {
		if (x[i] < c) {
			z[i] = Unit(-1);
		} else {
			z[i] = x[i] - c;
			c = 0;
		}
	}
	return c;
}

/*
	q[] = x[] / y
	@retval r = x[] % y
	accept q == x
*/
inline Unit divUnit(Unit *q, const Unit *x, size_t n, Unit y)
{
	assert(n > 0);
	Unit r = 0;
	for (int i = (int)n - 1; i >= 0; i--) {
		q[i] = divUnit1(&r, r, x[i], y);
	}
	return r;
}
/*
	q[] = x[] / y
	@retval r = x[] % y
*/
inline Unit modUnit(const Unit *x, size_t n, Unit y)
{
	assert(n > 0);
	Unit r = 0;
	for (int i = (int)n - 1; i >= 0; i--) {
		divUnit1(&r, r, x[i], y);
	}
	return r;
}

// x[n] = 0
inline void clear(Unit *x, size_t n)
{
	for (size_t i = 0; i < n; i++) x[i] = 0;
}

template<size_t N>
struct FuncT {
	static inline Unit add(Unit *z, const Unit *x, const Unit *y)
	{
		return addT<N>(z, x, y);
	}
	static inline Unit sub(Unit *z, const Unit *x, const Unit *y)
	{
		return subT<N>(z, x, y);
	}
	static inline Unit mulUnit(Unit *z, const Unit *x, Unit y)
	{
		return mulUnitT<N>(z, x, y);
	}
	static inline bool cmpGe(const Unit *x, const Unit *y)
	{
		return cmpGeT<N>(x, y);
	}
};
/*
	y must be sizeof(Unit) * 8 * N bit
	x[xn] = x[xn] % y[N]
	q[qn] = x[xn] / y[N] if q != NULL
	return new xn
*/
template<typename Func, size_t N>
size_t divFullBitT(Unit *q, size_t qn, Unit *x, size_t xn, const Unit *y)
{
	assert(xn > 0);
	assert((y[N - 1] >> (sizeof(Unit) * 8 - 1)) != 0);
	assert(q != x && q != y && x != y);
	if (q) clear(q, qn);
	Unit *t = (Unit*)CYBOZU_ALLOCA(sizeof(Unit) * N);
	while (xn > N) {
		if (x[xn - 1] == 0) {
			xn--;
			continue;
		}
		size_t d = xn - N;
		if (Func::cmpGe(x + d, y)) {
			Func::sub(x + d, x + d, y);
			if (q) addUnit(q + d, qn - d, 1);
		} else {
			Unit xTop = x[xn - 1];
			if (xTop == 1) {
				Unit ret = Func::sub(x + d - 1, x + d - 1, y);
				x[xn-1] -= ret;
			} else {
				Unit ret = Func::mulUnit(t, y, xTop);
				ret += Func::sub(x + d - 1, x + d - 1, t);
				x[xn-1] -= ret;
			}
			if (q) addUnit(q + d - 1, qn - d + 1, xTop);
		}
	}
	if (Func::cmpGe(x, y)) {
		Func::sub(x, x, y);
		if (q) addUnit(q, qn, 1);
	}
	xn = getRealSize(x, xn);
	return xn;
}

} } // mcl::bint

<|endoftext|>


<commit_before>#include <sstream>
#include <istream>
#include <iostream>
#include <algorithm>

#include "builtin.hh"
#include "zs_error.hh"
#include "number.hh"
#include "procedure.hh"
#include "lisp_ptr.hh"
#include "eval.hh"
#include "builtin_util.hh"
#include "reader.hh"
#include "printer.hh"
#include "vm.hh"
#include "port.hh"

#include "builtin_boolean.hh"
#include "builtin_char.hh"
#include "builtin_cons.hh"
#include "builtin_equal.hh"
#include "builtin_extra.hh"
#include "builtin_numeric.hh"
#include "builtin_port.hh"
#include "builtin_procedure.hh"
#include "builtin_string.hh"
#include "builtin_symbol.hh"
#include "builtin_syntax.hh"
#include "builtin_vector.hh"

using namespace std;
using namespace Procedure;

namespace {

static const char null_env_symname[] = "null-env-value";
static const char r5rs_env_symname[] = "r5rs-env-value";
static const char interaction_env_symname[] = "interaction-env-value";

static
Lisp_ptr env_pick_2(const char* name){
  ZsArgs args{1};
  auto num = args[0].get<Number*>();
  if(!num){
    throw builtin_type_check_failed(name, Ptr_tag::number, args[0]);
  }

  if(num->type() != Number::Type::integer){
    throw zs_error("native func: %s: passed number is not exact integer\n", name);
  }

  auto ver = num->get<Number::integer_type>();
  if(ver != 5l){
    throw zs_error("native func: %s: passed number is not 5 (supplied %ld)\n",
                        name, ver);
  }

  return vm.find(intern(vm.symtable(), name));
}

Lisp_ptr env_r5rs(){
  return env_pick_2(r5rs_env_symname);
}

Lisp_ptr env_null(){
  return env_pick_2(null_env_symname);
}

Lisp_ptr env_interactive(){
  ZsArgs args{0};
  return vm.find(intern(vm.symtable(), interaction_env_symname));
}

Lisp_ptr eval_func(){
  ZsArgs args{2};
  auto env = args[1].get<Env*>();
  if(!env){
    throw builtin_type_check_failed("eval", Ptr_tag::env, args[1]);
  }

  auto oldenv = vm.frame();
  vm.set_frame(env);
  vm.return_value = {oldenv, vm_op_leave_frame, args[0]};
  return {};
}

Lisp_ptr load_func(){
  ZsArgs args{1};
  auto str = args[0].get<String*>();
  if(!str){
    throw builtin_type_check_failed("load", Ptr_tag::string, args[0]);
  }

  stringstream f(*str, ios_base::in);
  if(!f){
    throw zs_error("load error: failed at opening file\n");
  }

  load(&f);
  return vm_op_nop;
}

} //namespace

static const BuiltinFunc builtin_syntax_funcs[] = {
#include "builtin_equal.defs.hh"
#include "builtin_syntax.defs.hh"
};

static const BuiltinFunc builtin_funcs[] = {
  {"eval", {
      eval_func,
      {2, 2, Passing::eval, Returning::code, MoveReturnValue::f}}},

  {"scheme-report-environment", {
      env_r5rs,
      {1}}},
  {"null-environment", {
      env_null,
      {1}}},
  {"interaction-environment", {
      env_interactive,
      {0}}},

  {"load", {
      load_func,
      {1}}},

#include "builtin_boolean.defs.hh"
#include "builtin_char.defs.hh"
#include "builtin_cons.defs.hh"
#include "builtin_numeric.defs.hh"
#include "builtin_port.defs.hh"
#include "builtin_procedure.defs.hh"
#include "builtin_string.defs.hh"
#include "builtin_symbol.defs.hh"
#include "builtin_vector.defs.hh"
};

static const char* builtin_strs[] = {
#include "builtin_cons.strs.hh"
#include "builtin_procedure.strs.hh"
#include "builtin_port.strs.hh"
};

static const BuiltinFunc builtin_extra_funcs[] = {
#include "builtin_extra.defs.hh"
};

static const char* builtin_extra_strs[] = {
#include "builtin_extra.strs.hh"
};

void install_builtin(){
  static constexpr auto install_builtin_native = [](const BuiltinFunc& bf){
    vm.local_set(intern(vm.symtable(), bf.name), {&bf.func});
  };
  static constexpr auto install_builtin_string = [](const char* s){
    stringstream ss({s}, ios_base::in);
    load(&ss);
  };

  // null-environment
  for_each(std::begin(builtin_syntax_funcs), std::end(builtin_syntax_funcs),
           install_builtin_native);
  vm.local_set(intern(vm.symtable(), null_env_symname), vm.frame());

  // r5rs-environment
  vm.set_frame(vm.frame()->push());
  for_each(std::begin(builtin_funcs), std::end(builtin_funcs),
           install_builtin_native);
  for_each(std::begin(builtin_strs), std::end(builtin_strs),
           install_builtin_string);
  vm.local_set(intern(vm.symtable(), CURRENT_INPUT_PORT_SYMNAME), &std::cin);
  vm.local_set(intern(vm.symtable(), CURRENT_OUTPUT_PORT_SYMNAME), &std::cout);
  vm.local_set(intern(vm.symtable(), r5rs_env_symname), vm.frame());

  // interaction-environment
  vm.set_frame(vm.frame()->push());
  for_each(std::begin(builtin_extra_funcs), std::end(builtin_extra_funcs),
           install_builtin_native);
  for_each(std::begin(builtin_extra_strs), std::end(builtin_extra_strs),
           install_builtin_string);
  vm.local_set(intern(vm.symtable(), interaction_env_symname), vm.frame());
}

void load(InputPort* p){
  while(1){
    auto form = read(*p);
    if(!form){
      if(!*p){
        // cerr << "load error: failed at reading a form. abandoned.\n";
      }
      break;
    }

    vm.code.push_back(form);
    eval();
    if(!vm.return_value[0]){
      cerr << "load error: failed at evaluating a form. skipped.\n";
      cerr << "\tform: \n";
      print(cerr, form);
      continue;
    }
  }
}
<commit_msg>redefine load<commit_after>#include <sstream>
#include <istream>
#include <iostream>
#include <algorithm>

#include "builtin.hh"
#include "zs_error.hh"
#include "number.hh"
#include "procedure.hh"
#include "lisp_ptr.hh"
#include "eval.hh"
#include "builtin_util.hh"
#include "reader.hh"
#include "printer.hh"
#include "vm.hh"
#include "port.hh"

#include "builtin_boolean.hh"
#include "builtin_char.hh"
#include "builtin_cons.hh"
#include "builtin_equal.hh"
#include "builtin_extra.hh"
#include "builtin_numeric.hh"
#include "builtin_port.hh"
#include "builtin_procedure.hh"
#include "builtin_string.hh"
#include "builtin_symbol.hh"
#include "builtin_syntax.hh"
#include "builtin_vector.hh"

using namespace std;
using namespace Procedure;

namespace {

static const char null_env_symname[] = "null-env-value";
static const char r5rs_env_symname[] = "r5rs-env-value";
static const char interaction_env_symname[] = "interaction-env-value";

static
Lisp_ptr env_pick_2(const char* name){
  ZsArgs args{1};
  auto num = args[0].get<Number*>();
  if(!num){
    throw builtin_type_check_failed(name, Ptr_tag::number, args[0]);
  }

  if(num->type() != Number::Type::integer){
    throw zs_error("native func: %s: passed number is not exact integer\n", name);
  }

  auto ver = num->get<Number::integer_type>();
  if(ver != 5l){
    throw zs_error("native func: %s: passed number is not 5 (supplied %ld)\n",
                        name, ver);
  }

  return vm.find(intern(vm.symtable(), name));
}

Lisp_ptr env_r5rs(){
  return env_pick_2(r5rs_env_symname);
}

Lisp_ptr env_null(){
  return env_pick_2(null_env_symname);
}

Lisp_ptr env_interactive(){
  ZsArgs args{0};
  return vm.find(intern(vm.symtable(), interaction_env_symname));
}

Lisp_ptr eval_func(){
  ZsArgs args{2};
  auto env = args[1].get<Env*>();
  if(!env){
    throw builtin_type_check_failed("eval", Ptr_tag::env, args[1]);
  }

  auto oldenv = vm.frame();
  vm.set_frame(env);
  vm.return_value = {oldenv, vm_op_leave_frame, args[0]};
  return {};
}

Lisp_ptr load_func(){
  ZsArgs args{1};
  auto str = args[0].get<String*>();
  if(!str){
    throw builtin_type_check_failed("load", Ptr_tag::string, args[0]);
  }

  stringstream f(*str, ios_base::in);
  if(!f){
    throw zs_error("load error: failed at opening file\n");
  }

  load(&f);
  return Lisp_ptr{true};
}

} //namespace

static const BuiltinFunc builtin_syntax_funcs[] = {
#include "builtin_equal.defs.hh"
#include "builtin_syntax.defs.hh"
};

static const BuiltinFunc builtin_funcs[] = {
  {"eval", {
      eval_func,
      {2, 2, Passing::eval, Returning::code, MoveReturnValue::f}}},

  {"scheme-report-environment", {
      env_r5rs,
      {1}}},
  {"null-environment", {
      env_null,
      {1}}},
  {"interaction-environment", {
      env_interactive,
      {0}}},

  {"load", {
      load_func,
      {1}}},

#include "builtin_boolean.defs.hh"
#include "builtin_char.defs.hh"
#include "builtin_cons.defs.hh"
#include "builtin_numeric.defs.hh"
#include "builtin_port.defs.hh"
#include "builtin_procedure.defs.hh"
#include "builtin_string.defs.hh"
#include "builtin_symbol.defs.hh"
#include "builtin_vector.defs.hh"
};

static const char* builtin_strs[] = {
#include "builtin_cons.strs.hh"
#include "builtin_procedure.strs.hh"
#include "builtin_port.strs.hh"
};

static const BuiltinFunc builtin_extra_funcs[] = {
#include "builtin_extra.defs.hh"
};

static const char* builtin_extra_strs[] = {
#include "builtin_extra.strs.hh"
};

void install_builtin(){
  static constexpr auto install_builtin_native = [](const BuiltinFunc& bf){
    vm.local_set(intern(vm.symtable(), bf.name), {&bf.func});
  };
  static constexpr auto install_builtin_string = [](const char* s){
    stringstream ss({s}, ios_base::in);
    load(&ss);
  };

  // null-environment
  for_each(std::begin(builtin_syntax_funcs), std::end(builtin_syntax_funcs),
           install_builtin_native);
  vm.local_set(intern(vm.symtable(), null_env_symname), vm.frame());

  // r5rs-environment
  vm.set_frame(vm.frame()->push());
  for_each(std::begin(builtin_funcs), std::end(builtin_funcs),
           install_builtin_native);
  for_each(std::begin(builtin_strs), std::end(builtin_strs),
           install_builtin_string);
  vm.local_set(intern(vm.symtable(), CURRENT_INPUT_PORT_SYMNAME), &std::cin);
  vm.local_set(intern(vm.symtable(), CURRENT_OUTPUT_PORT_SYMNAME), &std::cout);
  vm.local_set(intern(vm.symtable(), r5rs_env_symname), vm.frame());

  // interaction-environment
  vm.set_frame(vm.frame()->push());
  for_each(std::begin(builtin_extra_funcs), std::end(builtin_extra_funcs),
           install_builtin_native);
  for_each(std::begin(builtin_extra_strs), std::end(builtin_extra_strs),
           install_builtin_string);
  vm.local_set(intern(vm.symtable(), interaction_env_symname), vm.frame());
}

void load(InputPort* p){
  while(1){
    auto form = read(*p);
    if(!form){
      if(!*p){
        // cerr << "load error: failed at reading a form. abandoned.\n";
      }
      break;
    }

    vm.code.push_back(form);
    eval();
    if(!vm.return_value[0]){
      cerr << "load error: failed at evaluating a form. skipped.\n";
      cerr << "\tform: \n";
      print(cerr, form);
      continue;
    }
  }
}
<|endoftext|>


<commit_before>/*
 * This file is part of the kreenshot-editor project.
 *
 * Copyright (C) 2014 by Gregor Mi <codestruct@posteo.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 or the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
 */
#include "kreengraphicsscene.h"
#include "toolmanager.h"
#include "kreengraphicsitems.h"

namespace kreen {
namespace core {

KreenGraphicsScene::KreenGraphicsScene()
{
    _creatingItem = nullptr;
}

void KreenGraphicsScene::setToolManager(ToolManagerPtr toolManager)
{
    _toolManager = toolManager;
}

void KreenGraphicsScene::renderFinalImageOnly(bool finalOnly)
{
    foreach (QGraphicsItem* grItem, items()) {

        auto kreenGrItem = dynamic_cast<KreenQGraphicsItemBase*>(grItem);
        if (kreenGrItem && kreenGrItem->item()->typeId.startsWith("op-")) { // hide image operations like crop or rip out
            grItem->setVisible(!finalOnly);
        }

        // TODO: also hide the selection rect
    }
}

void KreenGraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent* event)
{
    qDebug() << "MyQGraphicsScene::mousePressEvent";
    Q_ASSERT(_toolManager != nullptr);

    _creatingItemStartPoint = event->scenePos().toPoint();

    if (!_toolManager->isImageOperationActive()) {
        ToolEnum tool = _toolManager->chosenTool();

        KreenItemPtr item;

        if (tool == Select) {
            // do nothing
        }
        else if (tool == DrawRect) {
            item = KreenItem::create("rect");
            _creatingItem = _toolManager->createGraphicsItemFromKreenItem(item, this);
            this->addItem(_creatingItem);
        }
        else if (tool == DrawEllipse) {
            item = KreenItem::create("ellipse");
            _creatingItem = _toolManager->createGraphicsItemFromKreenItem(item, this);
            this->addItem(_creatingItem);
        }
        else if (tool == DrawLine) {
            item = KreenItem::create("line");
            _creatingItem = _toolManager->createGraphicsItemFromKreenItem(item, this);
            this->addItem(_creatingItem);
        }
        else if (tool == OperationCrop) {
            item = KreenItem::create("op-crop");
            _creatingItem = _toolManager->createGraphicsItemFromKreenItem(item, this);
            this->addItem(_creatingItem);
        }
        else {
            qDebug() << "Unknown tool: " << tool;
            Q_ASSERT(false);
        }

        if (item && isItemForPointToSceneRestriction(item)) {
            restrictPointToScene(&_creatingItemStartPoint);
        }
    }

    QGraphicsScene::mousePressEvent(event);
}

void KreenGraphicsScene::mouseMoveEvent(QGraphicsSceneMouseEvent* event)
{
    if (_creatingItem != nullptr) {

        //qDebug() << "mouseMoveEvent";
        QPoint scenePos = event->scenePos().toPoint();

        //qDebug() << scenePos;
        auto grItemBase = dynamic_cast<KreenQGraphicsItemBase*>(_creatingItem);

        if (isItemForPointToSceneRestriction(grItemBase->item())) {
            restrictPointToScene(&scenePos);
        }

        grItemBase->updateVisualGeometryFromPoints(_creatingItemStartPoint, scenePos);
    }

    QGraphicsScene::mouseMoveEvent(event);
}

bool KreenGraphicsScene::isItemForPointToSceneRestriction(KreenItemPtr item)
{
    return item->typeId == "op-crop"; // TODO: op-ripout
}

void KreenGraphicsScene::restrictPointToScene(QPoint* pt)
{
    if (pt->x() < 0) {
        pt->setX(0);
    }

    if (pt->y() < 0) {
        pt->setY(0);
    }

    if (pt->x() > this->width()) {
        pt->setX(this->width());
    }

    if (pt->y() > this->height()) {
        pt->setY(this->height());
    }
}

void KreenGraphicsScene::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
{
    qDebug() << "MyQGraphicsScene::mouseReleaseEvent";

    if (_creatingItem != nullptr) {
        this->removeItem(_creatingItem);

        auto grItemBase = dynamic_cast<KreenQGraphicsItemBase*>(_creatingItem);
        grItemBase->updateModelFromVisualGeometry();

        _creatingItem = nullptr;
        if (!grItemBase->item()->rect().isNull()) {
            qDebug() << "emit itemCreated";
            emit itemCreated(grItemBase->item());
            qDebug() << "QGraphicsScene::mouseReleaseEvent(event)";
            QGraphicsScene::mouseReleaseEvent(event);
            return;
        }
        else {
            qDebug() << "rect is null, discard";
        }
    }

    QGraphicsScene::mouseReleaseEvent(event);

    qDebug() << "emit MyQGraphicsScene::mouseReleased";
    emit mouseReleased(); // used to update from model to have instant visual feedback if something is wrong with model/view mappine
}

}
}

<commit_msg>debug<commit_after>/*
 * This file is part of the kreenshot-editor project.
 *
 * Copyright (C) 2014 by Gregor Mi <codestruct@posteo.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 or the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
 */
#include "kreengraphicsscene.h"
#include "toolmanager.h"
#include "kreengraphicsitems.h"

namespace kreen {
namespace core {

KreenGraphicsScene::KreenGraphicsScene()
{
    _creatingItem = nullptr;
}

void KreenGraphicsScene::setToolManager(ToolManagerPtr toolManager)
{
    _toolManager = toolManager;
}

void KreenGraphicsScene::renderFinalImageOnly(bool finalOnly)
{
    foreach (QGraphicsItem* grItem, items()) {

        auto kreenGrItem = dynamic_cast<KreenQGraphicsItemBase*>(grItem);
        if (kreenGrItem && kreenGrItem->item()->typeId.startsWith("op-")) { // hide image operations like crop or rip out
            grItem->setVisible(!finalOnly);
        }

        // TODO: also hide the selection rect
    }
}

void KreenGraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent* event)
{
    qDebug() << "MyQGraphicsScene::mousePressEvent";
    Q_ASSERT(_toolManager != nullptr);

    _creatingItemStartPoint = event->scenePos().toPoint();

    if (!_toolManager->isImageOperationActive()) {
        ToolEnum tool = _toolManager->chosenTool();

        KreenItemPtr item;

        if (tool == Select) {
            // do nothing
        }
        else if (tool == DrawRect) {
            item = KreenItem::create("rect");
            _creatingItem = _toolManager->createGraphicsItemFromKreenItem(item, this);
            this->addItem(_creatingItem);
        }
        else if (tool == DrawEllipse) {
            item = KreenItem::create("ellipse");
            _creatingItem = _toolManager->createGraphicsItemFromKreenItem(item, this);
            this->addItem(_creatingItem);
        }
        else if (tool == DrawLine) {
            item = KreenItem::create("line");
            _creatingItem = _toolManager->createGraphicsItemFromKreenItem(item, this);
            this->addItem(_creatingItem);
        }
        else if (tool == OperationCrop) {
            item = KreenItem::create("op-crop");
            _creatingItem = _toolManager->createGraphicsItemFromKreenItem(item, this);
            this->addItem(_creatingItem);
        }
        else {
            qDebug() << "Unknown tool: " << tool;
            Q_ASSERT(false);
        }

        if (item && isItemForPointToSceneRestriction(item)) {
            restrictPointToScene(&_creatingItemStartPoint);
        }
    }

    QGraphicsScene::mousePressEvent(event);
}

void KreenGraphicsScene::mouseMoveEvent(QGraphicsSceneMouseEvent* event)
{
    if (_creatingItem != nullptr) {

        //qDebug() << "mouseMoveEvent";
        QPoint scenePos = event->scenePos().toPoint();

        //qDebug() << scenePos;
        auto grItemBase = dynamic_cast<KreenQGraphicsItemBase*>(_creatingItem);

        if (isItemForPointToSceneRestriction(grItemBase->item())) {
            restrictPointToScene(&scenePos);
        }

        grItemBase->updateVisualGeometryFromPoints(_creatingItemStartPoint, scenePos);
    }

    QGraphicsScene::mouseMoveEvent(event);
}

bool KreenGraphicsScene::isItemForPointToSceneRestriction(KreenItemPtr item)
{
    return item->typeId == "op-crop"; // TODO: op-ripout
}

void KreenGraphicsScene::restrictPointToScene(QPoint* pt)
{
    if (pt->x() < 0) {
        pt->setX(0);
    }

    if (pt->y() < 0) {
        pt->setY(0);
    }

    if (pt->x() > this->width()) {
        pt->setX(this->width());
    }

    if (pt->y() > this->height()) {
        pt->setY(this->height());
    }
}

void KreenGraphicsScene::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
{
    qDebug() << "MyQGraphicsScene::mouseReleaseEvent enter";

    if (_creatingItem != nullptr) {
        this->removeItem(_creatingItem);

        auto grItemBase = dynamic_cast<KreenQGraphicsItemBase*>(_creatingItem);
        grItemBase->updateModelFromVisualGeometry();

        _creatingItem = nullptr;
        if (!grItemBase->item()->rect().isNull()) {
            qDebug() << "emit itemCreated";
            emit itemCreated(grItemBase->item());
            qDebug() << "QGraphicsScene::mouseReleaseEvent(event) call";
            QGraphicsScene::mouseReleaseEvent(event);
            return;
        }
        else {
            qDebug() << "rect is null, discard";
        }
    }

    QGraphicsScene::mouseReleaseEvent(event);

    qDebug() << "emit MyQGraphicsScene::mouseReleased";
    emit mouseReleased(); // used to update from model to have instant visual feedback if something is wrong with model/view mappine
}

}
}

<|endoftext|>