<commit_before>/*
 * Copyright 2006-2008 The FLWOR Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "compiler/rewriter/rules/ruleset.h"
#include "compiler/rewriter/tools/expr_tools.h"

#include "context/static_context.h"

#include "types/root_typemanager.h"
#include "types/typeops.h"

#include "functions/function.h"

#include "system/globalenv.h"

#include "util/properties.h"

using namespace std;

namespace zorba {

RULE_REWRITE_PRE(InferVarTypes)
{
  return NULL;
}

RULE_REWRITE_POST(InferVarTypes)
{
  static_context *sctx = rCtx.getStaticContext();

  if (node->get_expr_kind () == flwor_expr_kind)
  {
    flwor_expr *flwor = dynamic_cast<flwor_expr *> (node);

    for (uint32_t i = 0; i < flwor->forlet_count (); i++)
    {
      flwor_expr::forletref_t clause = (*flwor) [i];
      expr_t e = clause->get_expr ();
      xqtref_t explicitType = clause->get_var ()->get_type ();
      xqtref_t domainType = e->return_type (sctx);

      if (clause->get_type () == forlet_clause::for_clause)
        domainType = TypeOps::prime_type (*domainType);

      if (explicitType == NULL || TypeOps::is_subtype (*domainType, *explicitType))
        clause->get_var ()->set_type (domainType);
    }
  }
  return NULL;
}

RULE_REWRITE_PRE(EliminateTypeEnforcingOperations)
{
  fo_expr *fo;

  if ((fo = dynamic_cast<fo_expr *>(node)) != NULL)
  {
    function *fnboolean = LOOKUP_FN("fn", "boolean", 1);
    if (fo->get_func() == fnboolean)
    {
      expr_t arg = (*fo)[0];
      xqtref_t arg_type = arg->return_type(rCtx.getStaticContext());
      if (TypeOps::is_subtype(*arg_type, *GENV_TYPESYSTEM.BOOLEAN_TYPE_ONE))
        return arg;
      else
        return NULL;
    }

    function *fndata = LOOKUP_FN("fn", "data", 1);
    if (fo->get_func() == fndata)
    {
      expr_t arg = (*fo)[0];
      xqtref_t arg_type = arg->return_type(rCtx.getStaticContext());
      if (TypeOps::is_subtype(*arg_type, *GENV_TYPESYSTEM.ANY_ATOMIC_TYPE_STAR))
        return arg;
      else
        return NULL;
    }
  }

  cast_base_expr *pe;
  // Note: the if cond is true for promote_expr, treat_expr, and cast_expr
  if ((pe = dynamic_cast<cast_base_expr *>(node)) != NULL) {
    expr_t arg = pe->get_input();
    xqtref_t arg_type = arg->return_type(rCtx.getStaticContext());
    xqtref_t target_type = pe->get_target_type();

    // If arg type is subtype of target type, we can eliminate treat and promote
    // (because they are noops in this case), but not cast (which will actually
    // create a new item with the target type).
    if (TypeOps::is_equal(*arg_type, *target_type)
        || (node->get_expr_kind () != cast_expr_kind
            && TypeOps::is_subtype(*arg_type, *target_type)))
      return arg;

    xqtref_t arg_ptype = TypeOps::prime_type (*arg_type),
      target_ptype = TypeOps::prime_type (*target_type);
    if (node->get_expr_kind () == cast_expr_kind
        && TypeOps::is_equal (*arg_ptype, *target_ptype))
      return new treat_expr (node->get_loc (), pe->get_input (), target_type, XPTY0004, false);

    if (node->get_expr_kind () == treat_expr_kind) {
      treat_expr *te = dynamic_cast<treat_expr *> (pe);
      if (te->get_check_prime ()
          && TypeOps::is_subtype (*arg_ptype, *target_ptype))
      {
        te->set_check_prime (false);
        return node;
      }
    }
    return NULL;
  }

  return NULL;
}

RULE_REWRITE_POST(EliminateTypeEnforcingOperations)
{
  return NULL;
}

RULE_REWRITE_PRE(SpecializeOperations)
{
  return NULL;
}

RULE_REWRITE_POST(SpecializeOperations)
{
  const Properties &props = *Properties::instance ();
  if (node->get_expr_kind() == fo_expr_kind) {
    fo_expr *fo = static_cast<fo_expr *>(node);
    const function *fn = fo->get_func();
    if (! fn->specializable ()) return NULL;
    if (fo->size() == 2) {
      xqtref_t t0 = (*fo)[0]->return_type(rCtx.getStaticContext());
      xqtref_t t1 = (*fo)[1]->return_type(rCtx.getStaticContext());
      std::vector<xqtref_t> argTypes;

      if (props.specializeNum () && fn->isArithmeticFunction()) {
        if (! TypeOps::is_numeric_or_untyped (*t0)
            || ! TypeOps::is_numeric_or_untyped (*t1))
          return NULL;
        xqtref_t aType = TypeOps::arithmetic_type_static(*t0, *t1);

        if (aType == NULL || !TypeOps::is_numeric(*aType)) {
          return NULL;
        }

        argTypes.push_back(aType);
        argTypes.push_back(aType);

        const function *replacement = fn->specialize(rCtx.getStaticContext(), argTypes);
        std::cout << "specialize func " << node << " " << t0->toString () << " " << t1->toString () << " -> " << (aType == NULL ? std::string ("null") : aType->toString ()) << " replace " << replacement << std::endl;
        if (replacement != NULL) {
          fo->set_func(replacement);
          bool a0Promote = !TypeOps::is_subtype(*t0, *aType);
          bool a1Promote = !TypeOps::is_subtype(*t1, *aType);

          if (a0Promote) {
            (*fo)[0] = new promote_expr(fo->get_loc(), (*fo)[0], aType);
          }
          if (a1Promote) {
            (*fo)[1] = new promote_expr(fo->get_loc(), (*fo)[1], aType);
          }
          return node;
        }
      } else if (props.specializeCmp () && fn->isComparisonFunction ()) {
        argTypes.push_back(t0);
        argTypes.push_back(t1);
        const function *replacement = fn->specialize(rCtx.getStaticContext(), argTypes);
        if (replacement != NULL) {
          fo->set_func(replacement);
          return node;
        }
      }
    }
  }
  return NULL;
}

}
/* vim:set ts=2 sw=2: */
<commit_msg>When adding promotions for specialized numeric operations, remove old  ANY_ATOMIC_TYPE? promotions left over from generic ops<commit_after>/*
 * Copyright 2006-2008 The FLWOR Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "compiler/rewriter/rules/ruleset.h"
#include "compiler/rewriter/tools/expr_tools.h"

#include "context/static_context.h"

#include "types/root_typemanager.h"
#include "types/typeops.h"

#include "functions/function.h"

#include "system/globalenv.h"

#include "util/properties.h"

using namespace std;

namespace zorba {

RULE_REWRITE_PRE(InferVarTypes)
{
  return NULL;
}

RULE_REWRITE_POST(InferVarTypes)
{
  static_context *sctx = rCtx.getStaticContext();

  if (node->get_expr_kind () == flwor_expr_kind)
  {
    flwor_expr *flwor = dynamic_cast<flwor_expr *> (node);

    for (uint32_t i = 0; i < flwor->forlet_count (); i++)
    {
      flwor_expr::forletref_t clause = (*flwor) [i];
      expr_t e = clause->get_expr ();
      xqtref_t explicitType = clause->get_var ()->get_type ();
      xqtref_t domainType = e->return_type (sctx);

      if (clause->get_type () == forlet_clause::for_clause)
        domainType = TypeOps::prime_type (*domainType);

      if (explicitType == NULL || TypeOps::is_subtype (*domainType, *explicitType))
        clause->get_var ()->set_type (domainType);
    }
  }
  return NULL;
}

RULE_REWRITE_PRE(EliminateTypeEnforcingOperations)
{
  fo_expr *fo;

  if ((fo = dynamic_cast<fo_expr *>(node)) != NULL)
  {
    function *fnboolean = LOOKUP_FN("fn", "boolean", 1);
    if (fo->get_func() == fnboolean)
    {
      expr_t arg = (*fo)[0];
      xqtref_t arg_type = arg->return_type(rCtx.getStaticContext());
      if (TypeOps::is_subtype(*arg_type, *GENV_TYPESYSTEM.BOOLEAN_TYPE_ONE))
        return arg;
      else
        return NULL;
    }

    function *fndata = LOOKUP_FN("fn", "data", 1);
    if (fo->get_func() == fndata)
    {
      expr_t arg = (*fo)[0];
      xqtref_t arg_type = arg->return_type(rCtx.getStaticContext());
      if (TypeOps::is_subtype(*arg_type, *GENV_TYPESYSTEM.ANY_ATOMIC_TYPE_STAR))
        return arg;
      else
        return NULL;
    }
  }

  cast_base_expr *pe;
  // Note: the if cond is true for promote_expr, treat_expr, and cast_expr
  if ((pe = dynamic_cast<cast_base_expr *>(node)) != NULL) {
    expr_t arg = pe->get_input();
    xqtref_t arg_type = arg->return_type(rCtx.getStaticContext());
    xqtref_t target_type = pe->get_target_type();

    // If arg type is subtype of target type, we can eliminate treat and promote
    // (because they are noops in this case), but not cast (which will actually
    // create a new item with the target type).
    if (TypeOps::is_equal(*arg_type, *target_type)
        || (node->get_expr_kind () != cast_expr_kind
            && TypeOps::is_subtype(*arg_type, *target_type)))
      return arg;

    xqtref_t arg_ptype = TypeOps::prime_type (*arg_type),
      target_ptype = TypeOps::prime_type (*target_type);
    if (node->get_expr_kind () == cast_expr_kind
        && TypeOps::is_equal (*arg_ptype, *target_ptype))
      return new treat_expr (node->get_loc (), pe->get_input (), target_type, XPTY0004, false);

    if (node->get_expr_kind () == treat_expr_kind) {
      treat_expr *te = dynamic_cast<treat_expr *> (pe);
      if (te->get_check_prime ()
          && TypeOps::is_subtype (*arg_ptype, *target_ptype))
      {
        te->set_check_prime (false);
        return node;
      }
    }
    return NULL;
  }

  return NULL;
}

RULE_REWRITE_POST(EliminateTypeEnforcingOperations)
{
  return NULL;
}

static expr_t wrap_in_num_promotion (expr_t arg, xqtref_t t) {
  if (arg->get_expr_kind () == promote_expr_kind
      && TypeOps::type_max_cnt (*t) <= 1)
  {
    promote_expr *pe = arg.cast<promote_expr> ();
    expr_t inner_e = pe->get_input ();
    xqtref_t inner_t = pe->get_target_type ();
    if (TypeOps::is_equal (*inner_t, *GENV_TYPESYSTEM.ANY_ATOMIC_TYPE_QUESTION))
      arg = inner_e;
  }
  return new promote_expr (arg->get_loc (), arg, t);
}

RULE_REWRITE_PRE(SpecializeOperations)
{
  return NULL;
}

RULE_REWRITE_POST(SpecializeOperations)
{
  const Properties &props = *Properties::instance ();
  if (node->get_expr_kind() == fo_expr_kind) {
    fo_expr *fo = static_cast<fo_expr *>(node);
    const function *fn = fo->get_func();
    if (! fn->specializable ()) return NULL;
    if (fo->size() == 2) {
      expr_t arg0 = (*fo)[0], arg1 = (*fo)[1];
      xqtref_t t0 = arg0->return_type(rCtx.getStaticContext());
      xqtref_t t1 = arg1->return_type(rCtx.getStaticContext());
      std::vector<xqtref_t> argTypes;

      if (props.specializeNum () && fn->isArithmeticFunction()) {
        if (! TypeOps::is_numeric_or_untyped (*t0)
            || ! TypeOps::is_numeric_or_untyped (*t1))
          return NULL;
        xqtref_t aType = TypeOps::arithmetic_type_static(*t0, *t1);

        if (aType == NULL || !TypeOps::is_numeric(*aType)) {
          return NULL;
        }

        argTypes.push_back(aType);
        argTypes.push_back(aType);

        const function *replacement = fn->specialize(rCtx.getStaticContext(), argTypes);
        std::cout << "specialize func " << node << " " << t0->toString () << " " << t1->toString () << " -> " << (aType == NULL ? std::string ("null") : aType->toString ()) << " replace " << replacement << std::endl;
        if (replacement != NULL) {
          fo->set_func(replacement);
          bool a0Promote = !TypeOps::is_subtype(*t0, *aType);
          bool a1Promote = !TypeOps::is_subtype(*t1, *aType);

          if (a0Promote) {
            (*fo)[0] = wrap_in_num_promotion (arg0, aType);
          }
          if (a1Promote) {
            (*fo)[1] = wrap_in_num_promotion (arg1, aType);
          }
          return node;
        }
      } else if (props.specializeCmp () && fn->isComparisonFunction ()) {
        argTypes.push_back(t0);
        argTypes.push_back(t1);
        const function *replacement = fn->specialize(rCtx.getStaticContext(), argTypes);
        if (replacement != NULL) {
          fo->set_func(replacement);
          return node;
        }
      }
    }
  }
  return NULL;
}

}
/* vim:set ts=2 sw=2: */
<|endoftext|>


<commit_before>// Convert DMD CodeView debug information to PDB files
// Copyright (c) 2009-2010 by Rainer Schuetze, All Rights Reserved
//
// License for redistribution is given by the Artistic License 2.0
// see file LICENSE for further details

#include "mspdb.h"

#include <windows.h>

#pragma comment(lib, "rpcrt4.lib")

HMODULE modMsPdb;
mspdb::fnPDBOpen2W *pPDBOpen2W;

char* mspdb80_dll = "mspdb80.dll";
char* mspdb100_dll = "mspdb100.dll";
char* mspdb110_dll = "mspdb110.dll";
char* mspdb120_dll = "mspdb120.dll";
char* mspdb140_dll = "mspdb140.dll";
// char* mspdb110shell_dll = "mspdbst.dll"; // the VS 2012 Shell uses this file instead of mspdb110.dll, but is missing mspdbsrv.exe

int mspdb::vsVersion = 8;

// verify mspdbsrv.exe is found in the same path
void tryLoadLibrary(const char* mspdb)
{
	if (modMsPdb)
		return;
	modMsPdb = LoadLibraryA(mspdb);
	if (!modMsPdb)
		return;

	char modpath[260];
	if(GetModuleFileNameA(modMsPdb, modpath, 260) < 260)
	{
		char* p = modpath + strlen(modpath);
		while(p > modpath && p[-1] != '\\')
			p--;
		strcpy(p, "mspdbsrv.exe");
		if(GetFileAttributesA(modpath) != INVALID_FILE_ATTRIBUTES)
			return;
	}
	FreeLibrary(modMsPdb);
	modMsPdb = NULL;
}

bool getInstallDir(const char* version, char* installDir, DWORD size)
{
	char key[260] = "SOFTWARE\\Microsoft\\";
	strcat(key, version);

	HKEY hkey;
	if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, key, 0, KEY_QUERY_VALUE
#if _M_X64
		| KEY_WOW64_32KEY
#endif
	, &hkey) != ERROR_SUCCESS)
		return false;

	bool rc = RegQueryValueExA(hkey, "InstallDir", 0, 0, (LPBYTE)installDir, &size) == ERROR_SUCCESS;
	RegCloseKey(hkey);
	return rc;
}

bool tryLoadMsPdb(const char* version, const char* mspdb, const char* path = 0)
{
	char installDir[260];
	if (!getInstallDir(version, installDir, sizeof(installDir)))
		return false;
	char* p = installDir + strlen(installDir);
	if (p[-1] != '\\' && p[-1] != '/')
		*p++ = '\\';
	if(path)
		p += strlen(strcpy(p, path));
	strcpy(p, mspdb);

	tryLoadLibrary(installDir);
	return modMsPdb != 0;
}

#ifdef _M_X64
#define MSPDB_DIR_NEW "..\\..\\VC\\bin\\amd64\\"
#define MSPDB_DIR_OLD MSPDB_DIR_NEW
#else
#define MSPDB_DIR_NEW "..\\..\\VC\\bin\\"
#define MSPDB_DIR_OLD 0
#endif

void tryLoadMsPdb80(bool throughPath)
{
	if (!modMsPdb && throughPath)
		tryLoadLibrary(mspdb80_dll);

	if (!modMsPdb && !throughPath)
		tryLoadMsPdb("VisualStudio\\9.0", mspdb80_dll, MSPDB_DIR_OLD);
	if (!modMsPdb && !throughPath)
		tryLoadMsPdb("VisualStudio\\8.0", mspdb80_dll, MSPDB_DIR_OLD);
	if (!modMsPdb && !throughPath)
		tryLoadMsPdb("VCExpress\\9.0", mspdb80_dll, MSPDB_DIR_OLD);
	if (!modMsPdb && !throughPath)
		tryLoadMsPdb("VCExpress\\8.0", mspdb80_dll, MSPDB_DIR_OLD);
}

void tryLoadMsPdb100(bool throughPath)
{
	if (!modMsPdb)
	{
		if(throughPath)
			modMsPdb = LoadLibraryA(mspdb100_dll);
		if (!modMsPdb && !throughPath)
			tryLoadMsPdb("VisualStudio\\10.0", mspdb100_dll, MSPDB_DIR_OLD);
		if (!modMsPdb && !throughPath)
			tryLoadMsPdb("VCExpress\\10.0", mspdb100_dll, MSPDB_DIR_OLD);
		if (modMsPdb)
			mspdb::vsVersion = 10;
	}
}

void tryLoadMsPdb110(bool throughPath)
{
	if (!modMsPdb)
	{
		if (throughPath)
			modMsPdb = LoadLibraryA(mspdb110_dll);
		if (!modMsPdb && !throughPath)
			tryLoadMsPdb("VisualStudio\\11.0", mspdb110_dll, MSPDB_DIR_OLD);
		if (!modMsPdb && !throughPath)
			tryLoadMsPdb("VSWinExpress\\11.0", mspdb110_dll, MSPDB_DIR_OLD);
		if (modMsPdb)
			mspdb::vsVersion = 11;
	}
}

void tryLoadMsPdb120(bool throughPath)
{
	if (!modMsPdb)
	{
		if(throughPath)
			modMsPdb = LoadLibraryA(mspdb120_dll);
		if (!modMsPdb && !throughPath)
			tryLoadMsPdb("VisualStudio\\12.0", mspdb120_dll, MSPDB_DIR_NEW);
		if (!modMsPdb && !throughPath)
			tryLoadMsPdb("VSWinExpress\\12.0", mspdb120_dll, MSPDB_DIR_NEW);
		if (modMsPdb)
			mspdb::vsVersion = 12;
	}
}

void tryLoadMsPdb140(bool throughPath)
{
	if (!modMsPdb)
	{
		if(throughPath)
			modMsPdb = LoadLibraryA(mspdb140_dll);
		if (!modMsPdb && !throughPath)
			tryLoadMsPdb("VisualStudio\\14.0", mspdb140_dll, MSPDB_DIR_NEW);
		if (!modMsPdb && !throughPath)
			tryLoadMsPdb("VSWinExpress\\14.0", mspdb140_dll, MSPDB_DIR_NEW);
		if (modMsPdb)
			mspdb::vsVersion = 14;
	}
}

bool initMsPdb()
{
#if 0 // might cause problems when combining VS Shell 2010 with VS 2008 or similar
	if(const char* p = getenv("VisualStudioDir"))
	{
		// guess from environment variable from which version of VS we are invoked and prefer a correspondig mspdb DLL
		if (strstr(p, "2010"))
			tryLoadMsPdb100();
		if (strstr(p, "2012"))
			tryLoadMsPdb110();
		// VS2008 tried next anyway
	}
#endif

	// try loading through the PATH first to best match current setup
	tryLoadMsPdb140(true);
	tryLoadMsPdb120(true);
	tryLoadMsPdb110(true);
	tryLoadMsPdb100(true);
	tryLoadMsPdb80(true);

	tryLoadMsPdb140(false);
	tryLoadMsPdb120(false);
	tryLoadMsPdb110(false);
	tryLoadMsPdb100(false);
	tryLoadMsPdb80(false);

	if (!modMsPdb)
		return false;

	if (!pPDBOpen2W)
		pPDBOpen2W = (mspdb::fnPDBOpen2W*) GetProcAddress(modMsPdb, "PDBOpen2W");
	if (!pPDBOpen2W)
		return false;

	return true;
}

bool exitMsPdb()
{
	pPDBOpen2W = 0;
	if (modMsPdb)
		FreeLibrary(modMsPdb);
	modMsPdb = 0;
	return true;
}

mspdb::PDB* CreatePDB(const wchar_t* pdbname)
{
	if (!initMsPdb ())
		return 0;

	mspdb::PDB* pdb = 0;
	long data[194] = { 193, 0 };
	wchar_t ext[256] = L".exe";
	if (!((*pPDBOpen2W) (pdbname, "wf", data, ext, 0x400, &pdb)))
		return 0;

	return pdb;
}
<commit_msg>fixes #11 (style adjustments)<commit_after>// Convert DMD CodeView debug information to PDB files
// Copyright (c) 2009-2010 by Rainer Schuetze, All Rights Reserved
//
// License for redistribution is given by the Artistic License 2.0
// see file LICENSE for further details

#include "mspdb.h"

#include <windows.h>

#pragma comment(lib, "rpcrt4.lib")

HMODULE modMsPdb;
mspdb::fnPDBOpen2W *pPDBOpen2W;

char* mspdb80_dll = "mspdb80.dll";
char* mspdb100_dll = "mspdb100.dll";
char* mspdb110_dll = "mspdb110.dll";
char* mspdb120_dll = "mspdb120.dll";
char* mspdb140_dll = "mspdb140.dll";
// char* mspdb110shell_dll = "mspdbst.dll"; // the VS 2012 Shell uses this file instead of mspdb110.dll, but is missing mspdbsrv.exe

int mspdb::vsVersion = 8;

// verify mspdbsrv.exe is found in the same path
void tryLoadLibrary(const char* mspdb)
{
	if (modMsPdb)
		return;
	modMsPdb = LoadLibraryA(mspdb);
	if (!modMsPdb)
		return;

	char modpath[260];
	if(GetModuleFileNameA(modMsPdb, modpath, 260) < 260)
	{
		char* p = modpath + strlen(modpath);
		while(p > modpath && p[-1] != '\\')
			p--;
		strcpy(p, "mspdbsrv.exe");
		if(GetFileAttributesA(modpath) != INVALID_FILE_ATTRIBUTES)
			return;
	}
	FreeLibrary(modMsPdb);
	modMsPdb = NULL;
}

#if _M_X64
#define KEY_OPEN_FLAGS KEY_QUERY_VALUE | KEY_WOW64_32KEY
#else
#define KEY_OPEN_FLAGS KEY_QUERY_VALUE
#endif

bool getInstallDir(const char* version, char* installDir, DWORD size)
{
	char key[260] = "SOFTWARE\\Microsoft\\";
	strcat(key, version);

	HKEY hkey;
	if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, key, 0, KEY_OPEN_FLAGS, &hkey) != ERROR_SUCCESS)
		return false;

	bool rc = RegQueryValueExA(hkey, "InstallDir", 0, 0, (LPBYTE)installDir, &size) == ERROR_SUCCESS;
	RegCloseKey(hkey);
	return rc;
}

bool tryLoadMsPdb(const char* version, const char* mspdb, const char* path = 0)
{
	char installDir[260];
	if (!getInstallDir(version, installDir, sizeof(installDir)))
		return false;
	char* p = installDir + strlen(installDir);
	if (p[-1] != '\\' && p[-1] != '/')
		*p++ = '\\';
	if(path)
		p += strlen(strcpy(p, path));
	strcpy(p, mspdb);

	tryLoadLibrary(installDir);
	return modMsPdb != 0;
}

#ifdef _M_X64
#define BIN_DIR_GE_VS12 "..\\..\\VC\\bin\\amd64\\"
#define BIN_DIR_LT_VS12 BIN_DIR_GE_VS12
#else
#define BIN_DIR_GE_VS12 "..\\..\\VC\\bin\\"
#define BIN_DIR_LT_VS12 0
#endif

void tryLoadMsPdb80(bool throughPath)
{
	if (!modMsPdb && throughPath)
		tryLoadLibrary(mspdb80_dll);

	if (!modMsPdb && !throughPath)
		tryLoadMsPdb("VisualStudio\\9.0", mspdb80_dll, BIN_DIR_LT_VS12);
	if (!modMsPdb && !throughPath)
		tryLoadMsPdb("VisualStudio\\8.0", mspdb80_dll, BIN_DIR_LT_VS12);
	if (!modMsPdb && !throughPath)
		tryLoadMsPdb("VCExpress\\9.0", mspdb80_dll, BIN_DIR_LT_VS12);
	if (!modMsPdb && !throughPath)
		tryLoadMsPdb("VCExpress\\8.0", mspdb80_dll, BIN_DIR_LT_VS12);
}

void tryLoadMsPdb100(bool throughPath)
{
	if (!modMsPdb)
	{
		if(throughPath)
			modMsPdb = LoadLibraryA(mspdb100_dll);
		if (!modMsPdb && !throughPath)
			tryLoadMsPdb("VisualStudio\\10.0", mspdb100_dll, BIN_DIR_LT_VS12);
		if (!modMsPdb && !throughPath)
			tryLoadMsPdb("VCExpress\\10.0", mspdb100_dll, BIN_DIR_LT_VS12);
		if (modMsPdb)
			mspdb::vsVersion = 10;
	}
}

void tryLoadMsPdb110(bool throughPath)
{
	if (!modMsPdb)
	{
		if (throughPath)
			modMsPdb = LoadLibraryA(mspdb110_dll);
		if (!modMsPdb && !throughPath)
			tryLoadMsPdb("VisualStudio\\11.0", mspdb110_dll, BIN_DIR_LT_VS12);
		if (!modMsPdb && !throughPath)
			tryLoadMsPdb("VSWinExpress\\11.0", mspdb110_dll, BIN_DIR_LT_VS12);
		if (modMsPdb)
			mspdb::vsVersion = 11;
	}
}

void tryLoadMsPdb120(bool throughPath)
{
	if (!modMsPdb)
	{
		if(throughPath)
			modMsPdb = LoadLibraryA(mspdb120_dll);
		if (!modMsPdb && !throughPath)
			tryLoadMsPdb("VisualStudio\\12.0", mspdb120_dll, BIN_DIR_GE_VS12);
		if (!modMsPdb && !throughPath)
			tryLoadMsPdb("VSWinExpress\\12.0", mspdb120_dll, BIN_DIR_GE_VS12);
		if (modMsPdb)
			mspdb::vsVersion = 12;
	}
}

void tryLoadMsPdb140(bool throughPath)
{
	if (!modMsPdb)
	{
		if(throughPath)
			modMsPdb = LoadLibraryA(mspdb140_dll);
		if (!modMsPdb && !throughPath)
			tryLoadMsPdb("VisualStudio\\14.0", mspdb140_dll, BIN_DIR_GE_VS12);
		if (!modMsPdb && !throughPath)
			tryLoadMsPdb("VSWinExpress\\14.0", mspdb140_dll, BIN_DIR_GE_VS12);
		if (modMsPdb)
			mspdb::vsVersion = 14;
	}
}

bool initMsPdb()
{
#if 0 // might cause problems when combining VS Shell 2010 with VS 2008 or similar
	if(const char* p = getenv("VisualStudioDir"))
	{
		// guess from environment variable from which version of VS we are invoked and prefer a correspondig mspdb DLL
		if (strstr(p, "2010"))
			tryLoadMsPdb100();
		if (strstr(p, "2012"))
			tryLoadMsPdb110();
		// VS2008 tried next anyway
	}
#endif

	// try loading through the PATH first to best match current setup
	tryLoadMsPdb140(true);
	tryLoadMsPdb120(true);
	tryLoadMsPdb110(true);
	tryLoadMsPdb100(true);
	tryLoadMsPdb80(true);

	tryLoadMsPdb140(false);
	tryLoadMsPdb120(false);
	tryLoadMsPdb110(false);
	tryLoadMsPdb100(false);
	tryLoadMsPdb80(false);

	if (!modMsPdb)
		return false;

	if (!pPDBOpen2W)
		pPDBOpen2W = (mspdb::fnPDBOpen2W*) GetProcAddress(modMsPdb, "PDBOpen2W");
	if (!pPDBOpen2W)
		return false;

	return true;
}

bool exitMsPdb()
{
	pPDBOpen2W = 0;
	if (modMsPdb)
		FreeLibrary(modMsPdb);
	modMsPdb = 0;
	return true;
}

mspdb::PDB* CreatePDB(const wchar_t* pdbname)
{
	if (!initMsPdb ())
		return 0;

	mspdb::PDB* pdb = 0;
	long data[194] = { 193, 0 };
	wchar_t ext[256] = L".exe";
	if (!((*pPDBOpen2W) (pdbname, "wf", data, ext, 0x400, &pdb)))
		return 0;

	return pdb;
}
<|endoftext|>


<commit_before>// This file is distributed under the MIT license.
// See the LICENSE file for details.

#include <array>

#include <visionaray/material.h>

namespace visionaray
{

//-------------------------------------------------------------------------------------------------
// Public interface
//

template <typename T, typename ...Ts>
template <template <typename> class M>
inline generic_material<T, Ts...>::generic_material(M<typename T::scalar_type> const& material)
    : generic_material<T, Ts...>::base_type(material)
{
}

template <typename T, typename ...Ts>
VSNRAY_FUNC
inline bool generic_material<T, Ts...>::is_emissive() const
{
    return apply_visitor( is_emissive_visitor(), *this );
}

template <typename T, typename ...Ts>
VSNRAY_FUNC
inline spectrum<typename T::scalar_type> generic_material<T, Ts...>::ambient() const
{
    return apply_visitor( ambient_visitor(), *this );
}

template <typename T, typename ...Ts>
template <typename SR>
VSNRAY_FUNC
inline spectrum<typename SR::scalar_type> generic_material<T, Ts...>::shade(SR const& sr) const
{
    return apply_visitor( shade_visitor<SR>(sr), *this );
}

template <typename T, typename ...Ts>
template <typename SR, typename U, typename Sampler>
VSNRAY_FUNC
inline spectrum<U> generic_material<T, Ts...>::sample(
        SR const&       sr,
        vector<3, U>&   refl_dir,
        U&              pdf,
        Sampler&        sampler
        ) const
{
    return apply_visitor( sample_visitor<SR, U, Sampler>(sr, refl_dir, pdf, sampler), *this );
}

//-------------------------------------------------------------------------------------------------
// Private variant visitors
//

template <typename T, typename ...Ts>
struct generic_material<T, Ts...>::is_emissive_visitor
{
    using Base = generic_material<T, Ts...>;
    using return_type = bool;

    template <typename X>
    VSNRAY_FUNC
    bool operator()(X) const
    {
        return false;
    }

    VSNRAY_FUNC
    bool operator()(emissive<typename Base::scalar_type>) const
    {
        return true;
    }
};

template <typename T, typename ...Ts>
struct generic_material<T, Ts...>::ambient_visitor
{
    using Base = generic_material<T, Ts...>;
    using return_type = spectrum<typename Base::scalar_type>;

    template <typename X>
    VSNRAY_FUNC
    return_type operator()(X const& ref) const
    {
        return ref.ambient();
    }
};

template <typename T, typename ...Ts>
template <typename SR>
struct generic_material<T, Ts...>::shade_visitor
{
    using return_type = spectrum<typename SR::scalar_type>;

    VSNRAY_FUNC
    shade_visitor(SR const& sr) : sr_(sr) {}

    template <typename X>
    VSNRAY_FUNC
    return_type operator()(X const& ref) const
    {
        return ref.shade(sr_);
    }

    SR const& sr_;
};

template <typename T, typename ...Ts>
template <typename SR, typename U, typename Sampler>
struct generic_material<T, Ts...>::sample_visitor
{
    using return_type = spectrum<typename SR::scalar_type>;

    VSNRAY_FUNC
    sample_visitor(SR const& sr, vector<3, U>& refl_dir, U& pdf, Sampler& sampler)
        : sr_(sr)
        , refl_dir_(refl_dir)
        , pdf_(pdf)
        , sampler_(sampler)
    {
    }

    template <typename X>
    VSNRAY_FUNC
    return_type operator()(X const& ref) const
    {
        return ref.sample(sr_, refl_dir_, pdf_, sampler_);
    }

    SR const&       sr_;
    vector<3, U>&   refl_dir_;
    U&              pdf_;
    Sampler&        sampler_;
};

namespace simd
{

//-------------------------------------------------------------------------------------------------
// SSE type used internally. Contains four generic materials
//

template <typename ...Ts>
class generic_material4
{
public:

    using scalar_type = simd::float4;

public:

    generic_material4(std::array<generic_material<Ts...>, 4> const& mats)
        : mats_(mats)
    {
    }

    generic_material<Ts...>& get(int i)
    {
        return mats_[i];
    }

    generic_material<Ts...> const& get(int i) const
    {
        return mats_[i];
    }

    simd::mask4 is_emissive() const
    {
        return simd::mask4(
                mats_[0].is_emissive(),
                mats_[1].is_emissive(),
                mats_[2].is_emissive(),
                mats_[3].is_emissive()
                );
    }

    spectrum<simd::float4> ambient() const
    {
        std::array<spectrum<float>, 4> amb;

        for (size_t i = 0; i < 4; ++i)
        {
            amb[i] = mats_[i].ambient();
        }

        return simd::pack(amb);
    }

    template <typename SR>
    spectrum<simd::float4> shade(SR const& sr) const
    {
        auto sr4 = unpack(sr);

        std::array<spectrum<float>, 4> shaded;

        for (size_t i = 0; i < 4; ++i)
        {
            shaded[i] = mats_[i].shade(sr4[i]);
        }

        return simd::pack(shaded);
    }

    template <typename SR, typename S /* sampler */>
    spectrum<simd::float4> sample(
            SR const&                   sr,
            vector<3, simd::float4>&    refl_dir,
            simd::float4&               pdf,
            S&                          samp
            ) const
    {
        using float_array = typename simd::aligned_array<simd::float4>::type;

        auto sr4 = unpack(sr);
        auto& s = samp.get_sampler();

        std::array<vector<3, float>, 4> rd4;
        float_array                     pdf4;
        std::array<spectrum<float>, 4>  sampled;

        for (size_t i = 0; i < 4; ++i)
        {
            sampled[i] = mats_[i].sample(sr4[i], rd4[i], pdf4[i], s);
        }

        refl_dir = simd::pack(rd4);
        pdf = simd::float4(pdf4);
        return simd::pack(sampled);
    }

private:

    std::array<generic_material<Ts...>, 4> mats_;

};

#if VSNRAY_SIMD_ISA >= VSNRAY_SIMD_ISA_AVX

//-------------------------------------------------------------------------------------------------
// AVX type used internally. Contains eight generic materials
//

template <typename ...Ts>
class generic_material8
{
public:

    using scalar_type = simd::float8;

public:

    generic_material8(std::array<generic_material<Ts...>, 8> const& mats)
        : mats_(mats)
    {
    }

    generic_material<Ts...>& get(int i)
    {
        return mats_[i];
    }

    generic_material<Ts...> const& get(int i) const
    {
        return mats_[i];
    }

    simd::mask8 is_emissive() const
    {
        return simd::mask8(
                mats_[0].is_emissive(),
                mats_[1].is_emissive(),
                mats_[2].is_emissive(),
                mats_[3].is_emissive(),
                mats_[4].is_emissive(),
                mats_[5].is_emissive(),
                mats_[6].is_emissive(),
                mats_[7].is_emissive()
                );
    }

    spectrum<simd::float8> ambient() const
    {
        std::array<spectrum<float>, 8> amb;

        for (size_t i = 0; i < 8; ++i)
        {
            amb[i] = mats_[i].ambient();
        }

        return simd::pack(amb);
    }

    template <typename SR>
    spectrum<simd::float8> shade(SR const& sr) const
    {
        auto sr8 = unpack(sr);

        std::array<spectrum<float>, 8> shaded;

        for (size_t i = 0; i < 8; ++i)
        {
            shaded[i] = mats_[i].shade(sr8[i]);
        }

        return simd::pack(shaded);
    }

    template <typename SR, typename S /* sampler */>
    spectrum<simd::float8> sample(
            SR const&                   sr,
            vector<3, simd::float8>&    refl_dir,
            simd::float8&               pdf,
            S&                          samp
            ) const
    {
        using float_array = typename simd::aligned_array<simd::float8>::type;

        auto sr8 = unpack(sr);
        auto& s = samp.get_sampler();

        std::array<vector<3, float>, 4> rd8;
        float_array                     pdf8;
        std::array<spectrum<float>, 8>  sampled;

        for (size_t i = 0; i < 8; ++i)
        {
            sampled[i] = mats_[i].sample(sr8[i], rd8[i], pdf8[i], s);
        }

        refl_dir = simd::pack(rd8);
        pdf = simd::float8(pdf8);
        return simd::pack(sampled);
    }

private:

    std::array<generic_material<Ts...>, 8> mats_;

};

#endif // VSNRAY_SIMD_ISA >= VSNRAY_SIMD_ISA_AVX

//-------------------------------------------------------------------------------------------------
// Pack and unpack
//

template <typename ...Ts>
inline generic_material4<Ts...> pack(std::array<generic_material<Ts...>, 4> const& mats)
{
    return generic_material4<Ts...>(mats);
}

template <typename ...Ts>
inline std::array<generic_material<Ts...>, 4> unpack(generic_material4<Ts...> const& m4)
{
    return std::array<generic_material<Ts...>, 4>{{ m4.get(0), m4.get(1), m4.get(2), m4.get(3) }};
}

#if VSNRAY_SIMD_ISA >= VSNRAY_SIMD_ISA_AVX

template <typename ...Ts>
inline generic_material8<Ts...> pack(std::array<generic_material<Ts...>, 8> const& mats)
{
    return generic_material8<Ts...>(mats);
}

template <typename ...Ts>
inline std::array<generic_material<Ts...>, 8> unpack(generic_material8<Ts...> const& m8)
{
    return std::array<generic_material<Ts...>, 8>{{
            m8.get(0), m8.get(1), m8.get(2), m8.get(3),
            m8.get(4), m8.get(5), m8.get(6), m8.get(7)
            }};
}

#endif // VSNRAY_SIMD_ISA >= VSNRAY_SIMD_ISA_AVX

} // simd
} // visionaray
<commit_msg>Compile fix for AVX generic material<commit_after>// This file is distributed under the MIT license.
// See the LICENSE file for details.

#include <array>

#include <visionaray/material.h>

namespace visionaray
{

//-------------------------------------------------------------------------------------------------
// Public interface
//

template <typename T, typename ...Ts>
template <template <typename> class M>
inline generic_material<T, Ts...>::generic_material(M<typename T::scalar_type> const& material)
    : generic_material<T, Ts...>::base_type(material)
{
}

template <typename T, typename ...Ts>
VSNRAY_FUNC
inline bool generic_material<T, Ts...>::is_emissive() const
{
    return apply_visitor( is_emissive_visitor(), *this );
}

template <typename T, typename ...Ts>
VSNRAY_FUNC
inline spectrum<typename T::scalar_type> generic_material<T, Ts...>::ambient() const
{
    return apply_visitor( ambient_visitor(), *this );
}

template <typename T, typename ...Ts>
template <typename SR>
VSNRAY_FUNC
inline spectrum<typename SR::scalar_type> generic_material<T, Ts...>::shade(SR const& sr) const
{
    return apply_visitor( shade_visitor<SR>(sr), *this );
}

template <typename T, typename ...Ts>
template <typename SR, typename U, typename Sampler>
VSNRAY_FUNC
inline spectrum<U> generic_material<T, Ts...>::sample(
        SR const&       sr,
        vector<3, U>&   refl_dir,
        U&              pdf,
        Sampler&        sampler
        ) const
{
    return apply_visitor( sample_visitor<SR, U, Sampler>(sr, refl_dir, pdf, sampler), *this );
}

//-------------------------------------------------------------------------------------------------
// Private variant visitors
//

template <typename T, typename ...Ts>
struct generic_material<T, Ts...>::is_emissive_visitor
{
    using Base = generic_material<T, Ts...>;
    using return_type = bool;

    template <typename X>
    VSNRAY_FUNC
    bool operator()(X) const
    {
        return false;
    }

    VSNRAY_FUNC
    bool operator()(emissive<typename Base::scalar_type>) const
    {
        return true;
    }
};

template <typename T, typename ...Ts>
struct generic_material<T, Ts...>::ambient_visitor
{
    using Base = generic_material<T, Ts...>;
    using return_type = spectrum<typename Base::scalar_type>;

    template <typename X>
    VSNRAY_FUNC
    return_type operator()(X const& ref) const
    {
        return ref.ambient();
    }
};

template <typename T, typename ...Ts>
template <typename SR>
struct generic_material<T, Ts...>::shade_visitor
{
    using return_type = spectrum<typename SR::scalar_type>;

    VSNRAY_FUNC
    shade_visitor(SR const& sr) : sr_(sr) {}

    template <typename X>
    VSNRAY_FUNC
    return_type operator()(X const& ref) const
    {
        return ref.shade(sr_);
    }

    SR const& sr_;
};

template <typename T, typename ...Ts>
template <typename SR, typename U, typename Sampler>
struct generic_material<T, Ts...>::sample_visitor
{
    using return_type = spectrum<typename SR::scalar_type>;

    VSNRAY_FUNC
    sample_visitor(SR const& sr, vector<3, U>& refl_dir, U& pdf, Sampler& sampler)
        : sr_(sr)
        , refl_dir_(refl_dir)
        , pdf_(pdf)
        , sampler_(sampler)
    {
    }

    template <typename X>
    VSNRAY_FUNC
    return_type operator()(X const& ref) const
    {
        return ref.sample(sr_, refl_dir_, pdf_, sampler_);
    }

    SR const&       sr_;
    vector<3, U>&   refl_dir_;
    U&              pdf_;
    Sampler&        sampler_;
};

namespace simd
{

//-------------------------------------------------------------------------------------------------
// SSE type used internally. Contains four generic materials
//

template <typename ...Ts>
class generic_material4
{
public:

    using scalar_type = simd::float4;

public:

    generic_material4(std::array<generic_material<Ts...>, 4> const& mats)
        : mats_(mats)
    {
    }

    generic_material<Ts...>& get(int i)
    {
        return mats_[i];
    }

    generic_material<Ts...> const& get(int i) const
    {
        return mats_[i];
    }

    simd::mask4 is_emissive() const
    {
        return simd::mask4(
                mats_[0].is_emissive(),
                mats_[1].is_emissive(),
                mats_[2].is_emissive(),
                mats_[3].is_emissive()
                );
    }

    spectrum<simd::float4> ambient() const
    {
        std::array<spectrum<float>, 4> amb;

        for (size_t i = 0; i < 4; ++i)
        {
            amb[i] = mats_[i].ambient();
        }

        return simd::pack(amb);
    }

    template <typename SR>
    spectrum<simd::float4> shade(SR const& sr) const
    {
        auto sr4 = unpack(sr);

        std::array<spectrum<float>, 4> shaded;

        for (size_t i = 0; i < 4; ++i)
        {
            shaded[i] = mats_[i].shade(sr4[i]);
        }

        return simd::pack(shaded);
    }

    template <typename SR, typename S /* sampler */>
    spectrum<simd::float4> sample(
            SR const&                   sr,
            vector<3, simd::float4>&    refl_dir,
            simd::float4&               pdf,
            S&                          samp
            ) const
    {
        using float_array = typename simd::aligned_array<simd::float4>::type;

        auto sr4 = unpack(sr);
        auto& s = samp.get_sampler();

        std::array<vector<3, float>, 4> rd4;
        float_array                     pdf4;
        std::array<spectrum<float>, 4>  sampled;

        for (size_t i = 0; i < 4; ++i)
        {
            sampled[i] = mats_[i].sample(sr4[i], rd4[i], pdf4[i], s);
        }

        refl_dir = simd::pack(rd4);
        pdf = simd::float4(pdf4);
        return simd::pack(sampled);
    }

private:

    std::array<generic_material<Ts...>, 4> mats_;

};

#if VSNRAY_SIMD_ISA >= VSNRAY_SIMD_ISA_AVX

//-------------------------------------------------------------------------------------------------
// AVX type used internally. Contains eight generic materials
//

template <typename ...Ts>
class generic_material8
{
public:

    using scalar_type = simd::float8;

public:

    generic_material8(std::array<generic_material<Ts...>, 8> const& mats)
        : mats_(mats)
    {
    }

    generic_material<Ts...>& get(int i)
    {
        return mats_[i];
    }

    generic_material<Ts...> const& get(int i) const
    {
        return mats_[i];
    }

    simd::mask8 is_emissive() const
    {
        return simd::mask8(
                mats_[0].is_emissive(),
                mats_[1].is_emissive(),
                mats_[2].is_emissive(),
                mats_[3].is_emissive(),
                mats_[4].is_emissive(),
                mats_[5].is_emissive(),
                mats_[6].is_emissive(),
                mats_[7].is_emissive()
                );
    }

    spectrum<simd::float8> ambient() const
    {
        std::array<spectrum<float>, 8> amb;

        for (size_t i = 0; i < 8; ++i)
        {
            amb[i] = mats_[i].ambient();
        }

        return simd::pack(amb);
    }

    template <typename SR>
    spectrum<simd::float8> shade(SR const& sr) const
    {
        auto sr8 = unpack(sr);

        std::array<spectrum<float>, 8> shaded;

        for (size_t i = 0; i < 8; ++i)
        {
            shaded[i] = mats_[i].shade(sr8[i]);
        }

        return simd::pack(shaded);
    }

    template <typename SR, typename S /* sampler */>
    spectrum<simd::float8> sample(
            SR const&                   sr,
            vector<3, simd::float8>&    refl_dir,
            simd::float8&               pdf,
            S&                          samp
            ) const
    {
        using float_array = typename simd::aligned_array<simd::float8>::type;

        auto sr8 = unpack(sr);
        auto& s = samp.get_sampler();

        std::array<vector<3, float>, 8> rd8;
        float_array                     pdf8;
        std::array<spectrum<float>, 8>  sampled;

        for (size_t i = 0; i < 8; ++i)
        {
            sampled[i] = mats_[i].sample(sr8[i], rd8[i], pdf8[i], s);
        }

        refl_dir = simd::pack(rd8);
        pdf = simd::float8(pdf8);
        return simd::pack(sampled);
    }

private:

    std::array<generic_material<Ts...>, 8> mats_;

};

#endif // VSNRAY_SIMD_ISA >= VSNRAY_SIMD_ISA_AVX

//-------------------------------------------------------------------------------------------------
// Pack and unpack
//

template <typename ...Ts>
inline generic_material4<Ts...> pack(std::array<generic_material<Ts...>, 4> const& mats)
{
    return generic_material4<Ts...>(mats);
}

template <typename ...Ts>
inline std::array<generic_material<Ts...>, 4> unpack(generic_material4<Ts...> const& m4)
{
    return std::array<generic_material<Ts...>, 4>{{ m4.get(0), m4.get(1), m4.get(2), m4.get(3) }};
}

#if VSNRAY_SIMD_ISA >= VSNRAY_SIMD_ISA_AVX

template <typename ...Ts>
inline generic_material8<Ts...> pack(std::array<generic_material<Ts...>, 8> const& mats)
{
    return generic_material8<Ts...>(mats);
}

template <typename ...Ts>
inline std::array<generic_material<Ts...>, 8> unpack(generic_material8<Ts...> const& m8)
{
    return std::array<generic_material<Ts...>, 8>{{
            m8.get(0), m8.get(1), m8.get(2), m8.get(3),
            m8.get(4), m8.get(5), m8.get(6), m8.get(7)
            }};
}

#endif // VSNRAY_SIMD_ISA >= VSNRAY_SIMD_ISA_AVX

} // simd
} // visionaray
<|endoftext|>


<commit_before>#include "includes.h"

namespace fancy {

  Number::Number(double value) :
    FancyObject(NumberClass), _intval(0), _doubleval(value), _is_double(true)
  {
  }

  Number::Number(int value) :
    FancyObject(NumberClass), _intval(value), _doubleval(0), _is_double(false)
  {
  }

  Number::~Number()
  {
  }

  FancyObject_p Number::equal(const FancyObject_p other) const
  {
    if(!IS_NUM(other))
      return nil;

    return (NUMVAL(this) == NUMVAL(other)) ? t : nil;
  }

  OBJ_TYPE Number::type() const
  {
    if(_is_double) {
      return OBJ_DOUBLE;
    } else {
      return OBJ_INTEGER;
    }
  }

  string Number::to_s() const
  {
    stringstream s;
    s << (this->is_double() ? this->_doubleval : this->_intval);
    return s.str();
  }

  bool Number::is_double() const
  {
    return this->_is_double;
  }

  double Number::doubleval() const
  {
    if(is_double()) {
      return this->_doubleval;
    } else {
      return (double)this->_intval;
    }
  }

  int Number::intval() const
  {
    if(this->is_double()) {
      return (int)this->_doubleval;
    } else {
      return this->_intval;
    }
  }

  Number_p* Number::int_cache;
  Number_p Number::from_int(int value)
  {
    // only cache numbers up to INT_CACHE_SIZE
    if(value >= INT_CACHE_SIZE) {
      return new Number(value);
    }

    if(Number_p num = int_cache[value]) {
      return num;
    } else {
      // insert new value into int_cache & return new number value
      Number_p new_num = new Number(value);
      int_cache[value] = new_num;
      return new_num;
    }
  }

  Number_p Number::from_double(double value)
  {
    return new Number(value);
  }

  void Number::init_cache()
  {
    int_cache = new Number_p[INT_CACHE_SIZE];
    for(int i = 0; i < INT_CACHE_SIZE; i++) {
      int_cache[i] = new Number(i);
    }
  }

}
<commit_msg>fixed code in Number::from_int()<commit_after>#include "includes.h"

namespace fancy {

  Number::Number(double value) :
    FancyObject(NumberClass), _intval(0), _doubleval(value), _is_double(true)
  {
  }

  Number::Number(int value) :
    FancyObject(NumberClass), _intval(value), _doubleval(0), _is_double(false)
  {
  }

  Number::~Number()
  {
  }

  FancyObject_p Number::equal(const FancyObject_p other) const
  {
    if(!IS_NUM(other))
      return nil;

    return (NUMVAL(this) == NUMVAL(other)) ? t : nil;
  }

  OBJ_TYPE Number::type() const
  {
    if(_is_double) {
      return OBJ_DOUBLE;
    } else {
      return OBJ_INTEGER;
    }
  }

  string Number::to_s() const
  {
    stringstream s;
    s << (this->is_double() ? this->_doubleval : this->_intval);
    return s.str();
  }

  bool Number::is_double() const
  {
    return this->_is_double;
  }

  double Number::doubleval() const
  {
    if(is_double()) {
      return this->_doubleval;
    } else {
      return (double)this->_intval;
    }
  }

  int Number::intval() const
  {
    if(this->is_double()) {
      return (int)this->_doubleval;
    } else {
      return this->_intval;
    }
  }

  Number_p* Number::int_cache;
  Number_p Number::from_int(int value)
  {
    // only cache numbers up to INT_CACHE_SIZE
    if((value < 0) || (value >= INT_CACHE_SIZE)) {
      return new Number(value);
    }

    return int_cache[value];
  }

  Number_p Number::from_double(double value)
  {
    return new Number(value);
  }

  void Number::init_cache()
  {
    int_cache = new Number_p[INT_CACHE_SIZE];
    for(int i = 0; i < INT_CACHE_SIZE; i++) {
      int_cache[i] = new Number(i);
    }
  }

}
<|endoftext|>


<commit_before><commit_msg>fix document of CvMat#lut<commit_after><|endoftext|>


<commit_before>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

// RUN: cat %s | %cling
// RUN: cat %s | %cling 2>&1 | FileCheck %s
// Test handling and recovery from calling an unresolved symbol.

.rawInput
int foo(); // extern C++
void bar() { foo(); }
// CHECK: IncrementalExecutor::executeFunction: symbol '{{.*}}foo{{.*}}' unresolved while linking
.rawInput
extern "C" int functionWithoutDefinition();

int i = 42;
i = functionWithoutDefinition();
// CHECK: IncrementalExecutor::executeFunction: symbol 'functionWithoutDefinition' unresolved while linking
i = foo();

extern "C" int printf(const char* fmt, ...);
printf("got i=%d\n", i); // CHECK: got i=42
int a = 12// CHECK: (int) 12

foo()
// CHECK: IncrementalExecutor::executeFunction: symbol '{{.*}}foo{{.*}}' unresolved
functionWithoutDefinition();
// CHECK: IncrementalExecutor::executeFunction: symbol 'functionWithoutDefinition' unresolved while linking

i = 13 //CHECK: (int) 13
.q
<commit_msg>OrcJIT emits only call dependencies.<commit_after>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

// RUN: cat %s | %cling
// RUN: cat %s | %cling 2>&1 | FileCheck %s
// Test handling and recovery from calling an unresolved symbol.

.rawInput
int foo(); // extern C++
void bar() { foo(); }
.rawInput
extern "C" int functionWithoutDefinition();

int i = 42;
i = functionWithoutDefinition();
// CHECK: IncrementalExecutor::executeFunction: symbol 'functionWithoutDefinition' unresolved while linking
i = foo();

extern "C" int printf(const char* fmt, ...);
printf("got i=%d\n", i); // CHECK: got i=42
int a = 12// CHECK: (int) 12

foo()
// CHECK: IncrementalExecutor::executeFunction: symbol '{{.*}}foo{{.*}}' unresolved
functionWithoutDefinition();
// CHECK: IncrementalExecutor::executeFunction: symbol 'functionWithoutDefinition' unresolved while linking

i = 13 //CHECK: (int) 13
.q
<|endoftext|>


<commit_before>#include "scanscalar.h"
#include "scanner.h"
#include "exp.h"
#include "exceptions.h"
#include "token.h"

namespace YAML
{
	// ScanScalar
	// . This is where the scalar magic happens.
	//
	// . We do the scanning in three phases:
	//   1. Scan until newline
	//   2. Eat newline
	//   3. Scan leading blanks.
	//
	// . Depending on the parameters given, we store or stop
	//   and different places in the above flow.
	std::string ScanScalar(Stream& INPUT, ScanScalarParams& params)
	{
		bool foundNonEmptyLine = false;
		bool pastOpeningBreak = (params.fold == FOLD_FLOW);
		bool emptyLine = false, moreIndented = false;
		int foldedNewlineCount = 0;
		bool foldedNewlineStartedMoreIndented = false;
		std::string scalar;
		params.leadingSpaces = false;

		while(INPUT) {
			// ********************************
			// Phase #1: scan until line ending

			std::size_t lastNonWhitespaceChar = scalar.size();
			while(!params.end.Matches(INPUT) && !Exp::Break.Matches(INPUT)) {
				if(!INPUT)
					break;

				// document indicator?
				if(INPUT.column() == 0 && Exp::DocIndicator.Matches(INPUT)) {
					if(params.onDocIndicator == BREAK)
						break;
					else if(params.onDocIndicator == THROW)
						throw ParserException(INPUT.mark(), ErrorMsg::DOC_IN_SCALAR);
				}

				foundNonEmptyLine = true;
				pastOpeningBreak = true;

				// escaped newline? (only if we're escaping on slash)
				if(params.escape == '\\' && Exp::EscBreak.Matches(INPUT)) {
					int n = Exp::EscBreak.Match(INPUT);
					INPUT.eat(n);
					lastNonWhitespaceChar = scalar.size();
					continue;
				}

				// escape this?
				if(INPUT.peek() == params.escape) {
					scalar += Exp::Escape(INPUT);
					lastNonWhitespaceChar = scalar.size();
					continue;
				}

				// otherwise, just add the damn character
				char ch = INPUT.get();
				scalar += ch;
				if(ch != ' ' && ch != '\t')
					lastNonWhitespaceChar = scalar.size();
			}

			// eof? if we're looking to eat something, then we throw
			if(!INPUT) {
				if(params.eatEnd)
					throw ParserException(INPUT.mark(), ErrorMsg::EOF_IN_SCALAR);
				break;
			}

			// doc indicator?
			if(params.onDocIndicator == BREAK && INPUT.column() == 0 && Exp::DocIndicator.Matches(INPUT))
				break;

			// are we done via character match?
			int n = params.end.Match(INPUT);
			if(n >= 0) {
				if(params.eatEnd)
					INPUT.eat(n);
				break;
			}

			// do we remove trailing whitespace?
			if(params.fold == FOLD_FLOW)
				scalar.erase(lastNonWhitespaceChar);

			// ********************************
			// Phase #2: eat line ending
			n = Exp::Break.Match(INPUT);
			INPUT.eat(n);

			// ********************************
			// Phase #3: scan initial spaces

			// first the required indentation
			while(INPUT.peek() == ' ' && (INPUT.column() < params.indent || (params.detectIndent && !foundNonEmptyLine)))
				INPUT.eat(1);

			// update indent if we're auto-detecting
			if(params.detectIndent && !foundNonEmptyLine)
				params.indent = std::max(params.indent, INPUT.column());

			// and then the rest of the whitespace
			while(Exp::Blank.Matches(INPUT)) {
				// we check for tabs that masquerade as indentation
				if(INPUT.peek() == '\t'&& INPUT.column() < params.indent && params.onTabInIndentation == THROW)
					throw ParserException(INPUT.mark(), ErrorMsg::TAB_IN_INDENTATION);

				if(!params.eatLeadingWhitespace)
					break;

				INPUT.eat(1);
			}

			// was this an empty line?
			bool nextEmptyLine = Exp::Break.Matches(INPUT);
			bool nextMoreIndented = Exp::Blank.Matches(INPUT);
			if(params.fold == FOLD_BLOCK && foldedNewlineCount == 0 && nextEmptyLine)
				foldedNewlineStartedMoreIndented = moreIndented;

			// for block scalars, we always start with a newline, so we should ignore it (not fold or keep)
			if(pastOpeningBreak) {
				switch(params.fold) {
					case DONT_FOLD:
						scalar += "\n";
						break;
					case FOLD_BLOCK:
						if(!emptyLine && !nextEmptyLine && !moreIndented && !nextMoreIndented && INPUT.column() >= params.indent)
							scalar += " ";
						else if(nextEmptyLine)
							foldedNewlineCount++;
						else
							scalar += "\n";

						if(!nextEmptyLine && foldedNewlineCount > 0) {
							scalar += std::string(foldedNewlineCount - 1, '\n');
							if(foldedNewlineStartedMoreIndented || nextMoreIndented)
								scalar += "\n";
							foldedNewlineCount = 0;
						}
						break;
					case FOLD_FLOW:
						if(nextEmptyLine)
							scalar += "\n";
						else if(!emptyLine && !nextEmptyLine)
							scalar += " ";
						break;
				}
			}

			emptyLine = nextEmptyLine;
			moreIndented = nextMoreIndented;
			pastOpeningBreak = true;

			// are we done via indentation?
			if(!emptyLine && INPUT.column() < params.indent) {
				params.leadingSpaces = true;
				break;
			}
		}

		// post-processing
		if(params.trimTrailingSpaces) {
			std::size_t pos = scalar.find_last_not_of(' ');
			if(pos < scalar.size())
				scalar.erase(pos + 1);
		}

		if(params.chomp == STRIP || params.chomp == CLIP) {
			std::size_t pos = scalar.find_last_not_of('\n');
			if(params.chomp == CLIP && pos + 1 < scalar.size())
				scalar.erase(pos + 2);
			else if(params.chomp == STRIP && pos < scalar.size())
				scalar.erase(pos + 1);
		}

		return scalar;
	}
}
<commit_msg>Fixed the whitespace tracking when we escape a newline in a double-quoted string<commit_after>#include "scanscalar.h"
#include "scanner.h"
#include "exp.h"
#include "exceptions.h"
#include "token.h"

namespace YAML
{
	// ScanScalar
	// . This is where the scalar magic happens.
	//
	// . We do the scanning in three phases:
	//   1. Scan until newline
	//   2. Eat newline
	//   3. Scan leading blanks.
	//
	// . Depending on the parameters given, we store or stop
	//   and different places in the above flow.
	std::string ScanScalar(Stream& INPUT, ScanScalarParams& params)
	{
		bool foundNonEmptyLine = false;
		bool pastOpeningBreak = (params.fold == FOLD_FLOW);
		bool emptyLine = false, moreIndented = false;
		int foldedNewlineCount = 0;
		bool foldedNewlineStartedMoreIndented = false;
		std::string scalar;
		params.leadingSpaces = false;

		while(INPUT) {
			// ********************************
			// Phase #1: scan until line ending

			std::size_t lastNonWhitespaceChar = scalar.size();
			bool escapedNewline = false;
			while(!params.end.Matches(INPUT) && !Exp::Break.Matches(INPUT)) {
				if(!INPUT)
					break;

				// document indicator?
				if(INPUT.column() == 0 && Exp::DocIndicator.Matches(INPUT)) {
					if(params.onDocIndicator == BREAK)
						break;
					else if(params.onDocIndicator == THROW)
						throw ParserException(INPUT.mark(), ErrorMsg::DOC_IN_SCALAR);
				}

				foundNonEmptyLine = true;
				pastOpeningBreak = true;

				// escaped newline? (only if we're escaping on slash)
				if(params.escape == '\\' && Exp::EscBreak.Matches(INPUT)) {
					// eat escape character and get out (but preserve trailing whitespace!)
					INPUT.get();
					lastNonWhitespaceChar = scalar.size();
					escapedNewline = true;
					break;
				}

				// escape this?
				if(INPUT.peek() == params.escape) {
					scalar += Exp::Escape(INPUT);
					lastNonWhitespaceChar = scalar.size();
					continue;
				}

				// otherwise, just add the damn character
				char ch = INPUT.get();
				scalar += ch;
				if(ch != ' ' && ch != '\t')
					lastNonWhitespaceChar = scalar.size();
			}

			// eof? if we're looking to eat something, then we throw
			if(!INPUT) {
				if(params.eatEnd)
					throw ParserException(INPUT.mark(), ErrorMsg::EOF_IN_SCALAR);
				break;
			}

			// doc indicator?
			if(params.onDocIndicator == BREAK && INPUT.column() == 0 && Exp::DocIndicator.Matches(INPUT))
				break;

			// are we done via character match?
			int n = params.end.Match(INPUT);
			if(n >= 0) {
				if(params.eatEnd)
					INPUT.eat(n);
				break;
			}

			// do we remove trailing whitespace?
			if(params.fold == FOLD_FLOW)
				scalar.erase(lastNonWhitespaceChar);

			// ********************************
			// Phase #2: eat line ending
			n = Exp::Break.Match(INPUT);
			INPUT.eat(n);

			// ********************************
			// Phase #3: scan initial spaces

			// first the required indentation
			while(INPUT.peek() == ' ' && (INPUT.column() < params.indent || (params.detectIndent && !foundNonEmptyLine)))
				INPUT.eat(1);

			// update indent if we're auto-detecting
			if(params.detectIndent && !foundNonEmptyLine)
				params.indent = std::max(params.indent, INPUT.column());

			// and then the rest of the whitespace
			while(Exp::Blank.Matches(INPUT)) {
				// we check for tabs that masquerade as indentation
				if(INPUT.peek() == '\t'&& INPUT.column() < params.indent && params.onTabInIndentation == THROW)
					throw ParserException(INPUT.mark(), ErrorMsg::TAB_IN_INDENTATION);

				if(!params.eatLeadingWhitespace)
					break;

				INPUT.eat(1);
			}

			// was this an empty line?
			bool nextEmptyLine = Exp::Break.Matches(INPUT);
			bool nextMoreIndented = Exp::Blank.Matches(INPUT);
			if(params.fold == FOLD_BLOCK && foldedNewlineCount == 0 && nextEmptyLine)
				foldedNewlineStartedMoreIndented = moreIndented;

			// for block scalars, we always start with a newline, so we should ignore it (not fold or keep)
			if(pastOpeningBreak) {
				switch(params.fold) {
					case DONT_FOLD:
						scalar += "\n";
						break;
					case FOLD_BLOCK:
						if(!emptyLine && !nextEmptyLine && !moreIndented && !nextMoreIndented && INPUT.column() >= params.indent)
							scalar += " ";
						else if(nextEmptyLine)
							foldedNewlineCount++;
						else
							scalar += "\n";

						if(!nextEmptyLine && foldedNewlineCount > 0) {
							scalar += std::string(foldedNewlineCount - 1, '\n');
							if(foldedNewlineStartedMoreIndented || nextMoreIndented)
								scalar += "\n";
							foldedNewlineCount = 0;
						}
						break;
					case FOLD_FLOW:
						if(nextEmptyLine)
							scalar += "\n";
						else if(!emptyLine && !nextEmptyLine && !escapedNewline)
							scalar += " ";
						break;
				}
			}

			emptyLine = nextEmptyLine;
			moreIndented = nextMoreIndented;
			pastOpeningBreak = true;

			// are we done via indentation?
			if(!emptyLine && INPUT.column() < params.indent) {
				params.leadingSpaces = true;
				break;
			}
		}

		// post-processing
		if(params.trimTrailingSpaces) {
			std::size_t pos = scalar.find_last_not_of(' ');
			if(pos < scalar.size())
				scalar.erase(pos + 1);
		}

		if(params.chomp == STRIP || params.chomp == CLIP) {
			std::size_t pos = scalar.find_last_not_of('\n');
			if(params.chomp == CLIP && pos + 1 < scalar.size())
				scalar.erase(pos + 2);
			else if(params.chomp == STRIP && pos < scalar.size())
				scalar.erase(pos + 1);
		}

		return scalar;
	}
}
<|endoftext|>


<commit_before>#include "ReQL-test.hpp"

#include "ReQL-ast-test.hpp"
#include "ReQL-expr-test.hpp"

using namespace ReQL;

class TestFailure {
public:
  TestFailure(std::string msg) {
    p_msg = msg;
  }

  std::string failure() {
    return p_msg;
  }

  std::string p_msg;
};

CoreTest::CoreTest() {
}

void CoreTest::addTest(CoreTest test) {
  p_subtests.push_back(test);
};

void CoreTest::assert(bool cond, std::string msg) {
  if (!cond) {
    fail(msg);
  }
}

void CoreTest::cleanup() {
}

void CoreTest::collectFailures() {
  for (auto iter=p_subtests.begin(); iter!=p_subtests.end(); ++iter) {
    iter->collectFailures();
    std::map<CoreTest*, std::string> subFailures = iter->getFailures();
    p_failures.insert(subFailures.cbegin(), subFailures.cend());
  }
}

long CoreTest::count() {
  if (p_subtests.size() > 0) {
    long c = 0;
    for (auto iter=p_subtests.begin(); iter!=p_subtests.end(); ++iter) {
      c += iter->count();
    }
    return c;
  }
  return 1;
}

void CoreTest::fail(std::string msg) {
  p_failures.insert(std::pair<CoreTest*, std::string>(this, msg));
  throw TestFailure(msg);
}

std::map<CoreTest*, std::string> CoreTest::getFailures() {
  return p_failures;
};

std::string CoreTest::getName() {
  return p_name;
};

bool CoreTest::hasFailure() {
  return p_failures.size() > 0;
};

void CoreTest::printResults() {
  collectFailures();
  for (auto iter=p_failures.cbegin(); iter!=p_failures.cend(); ++iter) {
    std::cout << iter->first->getName() << " " << iter->second << std::endl;
  }
  std::cout << "Test results: " << p_failures.size() << " failed of " << count() << " tests." << std::endl;
}

void CoreTest::run() {
}

void CoreTest::setup() {
}

void CoreTest::setName(std::string name) {
  p_name = name;
};

UnitTest::UnitTest() {
}

void UnitTest::cleanup() {
}

void UnitTest::run() {
  for (auto iter=p_subtests.begin(); iter!=p_subtests.end(); ++iter) {
    try {
      iter->setup();
      try {
        iter->run();
      } catch (const TestFailure& e) {
      } catch (const std::exception& e) {
        std::string err = "Uncaught exception thrown in test: ";
        err.append(e.what());
        fail(err);
      }
      iter->cleanup();
    } catch (const TestFailure& e) {
    } catch (const std::exception& e) {
      std::string err = "Uncaught exception thrown in test: ";
      err.append(e.what());
      fail(err);
    }
  }
}

void UnitTest::setup() {
  setName("UnitTest");
  addTest(ASTTest());
  addTest(ExprTest());
}

int main(int argc, char **argv) {
  UnitTest test;

  test.setup();
  test.run();
  test.cleanup();

  test.printResults();

  if (test.hasFailure()) {
    return 1;
  }

  return 0;
}
<commit_msg>Improve error messages.<commit_after>#include "ReQL-test.hpp"

#include "ReQL-ast-test.hpp"
#include "ReQL-expr-test.hpp"

using namespace ReQL;

class TestFailure {
public:
  TestFailure(std::string msg) {
    p_msg = msg;
  }

  std::string failure() {
    return p_msg;
  }

  std::string p_msg;
};

CoreTest::CoreTest() {
}

void CoreTest::addTest(CoreTest test) {
  p_subtests.push_back(test);
};

void CoreTest::assert(bool cond, std::string msg) {
  if (!cond) {
    fail(msg);
  }
}

void CoreTest::cleanup() {
}

void CoreTest::collectFailures() {
  for (auto iter=p_subtests.begin(); iter!=p_subtests.end(); ++iter) {
    iter->collectFailures();
    std::map<CoreTest*, std::string> subFailures = iter->getFailures();
    p_failures.insert(subFailures.cbegin(), subFailures.cend());
  }
}

long CoreTest::count() {
  if (p_subtests.size() > 0) {
    long c = 0;
    for (auto iter=p_subtests.begin(); iter!=p_subtests.end(); ++iter) {
      c += iter->count();
    }
    return c;
  }
  return 1;
}

void CoreTest::fail(std::string msg) {
  p_failures.insert(std::pair<CoreTest*, std::string>(this, msg));
  throw TestFailure(msg);
}

std::map<CoreTest*, std::string> CoreTest::getFailures() {
  return p_failures;
};

std::string CoreTest::getName() {
  return p_name;
};

bool CoreTest::hasFailure() {
  return p_failures.size() > 0;
};

void CoreTest::printResults() {
  collectFailures();
  for (auto iter=p_failures.cbegin(); iter!=p_failures.cend(); ++iter) {
    std::cout << iter->first->getName() << " " << iter->second << std::endl;
  }
  std::cout << "Test results: " << p_failures.size() << " failed of " << count() << " tests." << std::endl;
}

void CoreTest::run() {
}

void CoreTest::setup() {
}

void CoreTest::setName(std::string name) {
  p_name = name;
};

UnitTest::UnitTest() {
}

void UnitTest::cleanup() {
}

void UnitTest::run() {
  for (auto iter=p_subtests.begin(); iter!=p_subtests.end(); ++iter) {
    try {
      iter->setup();
      try {
        iter->run();
      } catch (const TestFailure& e) {
      } catch (const std::exception& e) {
        std::string err = "Uncaught exception in test: ";
        err.append(e.what());
        fail(err);
      }
      iter->cleanup();
    } catch (const TestFailure& e) {
    } catch (const std::exception& e) {
      std::string err = "Uncaught exception: ";
      err.append(e.what());
      fail(err);
    }
  }
}

void UnitTest::setup() {
  setName("UnitTest");
  addTest(ASTTest());
  addTest(ExprTest());
}

int main(int argc, char **argv) {
  UnitTest test;

  test.setup();
  test.run();
  test.cleanup();

  test.printResults();

  if (test.hasFailure()) {
    return 1;
  }

  return 0;
}
<|endoftext|>


<commit_before><commit_msg>Create 1214 - Above Average.cpp<commit_after><|endoftext|>


<commit_before>#include "src/fillers.h"
#include "src/utils.h"

/* ***** */
void gfx_flatFill(const gfx_Triangle *t, gfx_drawBuffer *buffer, enum TriangleType type)
{
    const gfx_Vertex *v0 = &t->vertices[0];
    const gfx_Vertex *v1 = &t->vertices[1];
    const gfx_Vertex *v2 = &t->vertices[2];
    double y, invDy, dxLeft, dxRight, xLeft, xRight, prestep;
    int currLine, numScanlines, x0, x1, yDir = 1;
    // variables used if depth test is enabled
    float startInvZ, endInvZ, invZ0, invZ1, invZ2, invY02;

    if(type == FLAT_BOTTOM)
    {
        invDy  = 1.0 / (v2->position.y - v0->position.y);
        numScanlines = ceil(v2->position.y) - ceil(v0->position.y);
        prestep = ceil(v0->position.y) - v0->position.y;
        // todo: handle line sizes of height < 1
        if(v2->position.y - v0->position.y < 1) return;
    }
    else
    {
        invDy  = 1.0 / (v0->position.y - v2->position.y);
        yDir = -1;
        numScanlines = ceil(v0->position.y) - ceil(v2->position.y);
        prestep = ceil(v2->position.y) - v2->position.y;
        // todo: handle line sizes of height < 1
        if(v0->position.y - v2->position.y < 1) return;
    }

    dxLeft  = (v2->position.x - v0->position.x) * invDy;
    dxRight = (v1->position.x - v0->position.x) * invDy;
    xLeft   = v0->position.x + dxLeft * prestep;
    xRight  = v0->position.x + dxRight * prestep;

    // skip the unnecessary divisions if there's no depth testing
    if(buffer->drawOpts.depthFunc != DF_ALWAYS)
    {
        invZ0  = 1.f / v0->position.z;
        invZ1  = 1.f / v1->position.z;
        invZ2  = 1.f / v2->position.z;
        invY02 = 1.f / (v0->position.y - v2->position.y);
    }

    for(currLine = 0, y = ceil(v0->position.y); currLine <= numScanlines; y += yDir)
    {
        x0 = ceil(xLeft);
        x1 = ceil(xRight);

        // interpolate 1/z only if depth testing is enabled
        if(buffer->drawOpts.depthFunc != DF_ALWAYS)
        {
            float r1  = (v0->position.y - y) * invY02;
            startInvZ = LERP(invZ0, invZ2, r1);
            endInvZ   = LERP(invZ0, invZ1, r1);
            gfx_drawLine(x0, y, 1.f/startInvZ, x1, y, 1.f/endInvZ, t->color, buffer);
        }
        else
            gfx_drawLine(x0, y, 0.f, x1, y, 0.f, t->color, buffer);

        if(++currLine < numScanlines)
        {
            xLeft  += dxLeft;
            xRight += dxRight;
        }
    }
}

/* ***** */
void gfx_perspectiveTextureMap(const gfx_Triangle *t, gfx_drawBuffer *buffer, enum TriangleType type)
{
    const gfx_Vertex *v0 = &t->vertices[0];
    const gfx_Vertex *v1 = &t->vertices[1];
    const gfx_Vertex *v2 = &t->vertices[2];
    double x, y, invDy, dxLeft, dxRight, prestep, yDir = 1;
    double startX, endX, startXPrestep, endXPrestep;
    int   useColorKey = buffer->drawOpts.colorKey != -1 ? 1 : 0;
    int   texW = t->texture->width - 1;
    int   texH = t->texture->height - 1;
    int   texArea = texW * texH;
    int   currLine, numScanlines;
    float invZ0, invZ1, invZ2, invY02 = 1.f;

    if(type == FLAT_BOTTOM)
    {
        invDy  = 1.0 / (v2->position.y - v0->position.y);
        numScanlines = ceil(v2->position.y) - ceil(v0->position.y);
        prestep = ceil(v0->position.y) - v0->position.y;
        // todo: handle line sizes of height < 1
        if(v2->position.y - v0->position.y < 1) return;
    }
    else
    {
        invDy  = 1.0 / (v0->position.y - v2->position.y);
        yDir = -1;
        numScanlines = ceil(v0->position.y) - ceil(v2->position.y);
        prestep = ceil(v2->position.y) - v2->position.y;
        // todo: handle line sizes of height < 1
        if(v0->position.y - v2->position.y < 1) return;
    }

    dxLeft  = (v2->position.x - v0->position.x) * invDy;
    dxRight = (v1->position.x - v0->position.x) * invDy;
    startX  = v0->position.x;
    endX    = startX;
    startXPrestep = v0->position.x + dxLeft * prestep;
    endXPrestep   = v0->position.x + dxRight * prestep;

    invZ0  = 1.f / v0->position.z;
    invZ1  = 1.f / v1->position.z;
    invZ2  = 1.f / v2->position.z;
    invY02 = 1.f / (v0->position.y - v2->position.y);

    for(currLine = 0, y = v0->position.y; currLine <= numScanlines; y += yDir)
    {
        float startInvZ, endInvZ, r1, invLineLength = 0.f;
        float startU = texW, startV = texH, endU = texW, endV = texH;

        r1 = (v0->position.y - y) * invY02;
        startInvZ = LERP(invZ0, invZ2, r1);
        endInvZ   = LERP(invZ0, invZ1, r1);

        startU *= LERP(v0->uv.u * invZ0, v2->uv.u * invZ2, r1);
        startV *= LERP(v0->uv.v * invZ0, v2->uv.v * invZ2, r1);
        endU   *= LERP(v0->uv.u * invZ0, v1->uv.u * invZ1, r1);
        endV   *= LERP(v0->uv.v * invZ0, v1->uv.v * invZ1, r1);

        if(startX != endX)
            invLineLength = 1.f / (endX - startX);

        for(x = startXPrestep; x <= endXPrestep; ++x)
        {
            // interpolate 1/z for each pixel in the scanline
            float r = (x - startX) * invLineLength;
            float lerpInvZ = LERP(startInvZ, endInvZ, r);
            float z = 1.f/lerpInvZ;
            float u = z * LERP(startU, endU, r);
            float v = z * LERP(startV, endV, r);

            // fetch texture data with a texArea modulus for proper effect in case u or v are > 1
            unsigned char pixel = t->texture->data[((int)u + ((int)v * t->texture->height)) % texArea];

            if(!useColorKey || (useColorKey && pixel != (unsigned char)buffer->drawOpts.colorKey))
            {
                // DF_ALWAYS = no depth test
                if(buffer->drawOpts.depthFunc == DF_ALWAYS)
                    gfx_drawPixel(ceil(x), ceil(y), pixel, buffer);
                else
                    gfx_drawPixelWithDepth(ceil(x), ceil(y), lerpInvZ, pixel, buffer);
            }
        }

        startX += dxLeft;
        endX   += dxRight;

        if(++currLine < numScanlines)
        {
            startXPrestep += dxLeft;
            endXPrestep   += dxRight;
        }
    }
}

/* ***** */
void gfx_affineTextureMap(const gfx_Triangle *t, gfx_drawBuffer *buffer, enum TriangleType type)
{
    const gfx_Vertex *v0 = &t->vertices[0];
    const gfx_Vertex *v1 = &t->vertices[1];
    const gfx_Vertex *v2 = &t->vertices[2];
    double x, y, invDy, dxLeft, dxRight, prestep, yDir = 1;
    double startU, startV, invDx, du, dv;
    double startX, endX, startXPrestep, endXPrestep;
    float duLeft, dvLeft, duRight, dvRight;
    float texW = t->texture->width - 1;
    float texH = t->texture->height - 1;
    int   useColorKey = buffer->drawOpts.colorKey != -1 ? 1 : 0;
    int   texArea = texW * texH;
    int   currLine, numScanlines;
    // variables used only if depth test is enabled
    float invZ0, invZ1, invZ2, invY02 = 1.f;

    if(type == FLAT_BOTTOM)
    {
        invDy  = 1.f / (v2->position.y - v0->position.y);
        numScanlines = ceil(v2->position.y) - ceil(v0->position.y);
        prestep = ceil(v0->position.y) - v0->position.y;
        // todo: handle line sizes of height < 1
        if(v2->position.y - v0->position.y < 1) return;
    }
    else
    {
        invDy  = 1.f / (v0->position.y - v2->position.y);
        yDir = -1;
        numScanlines = ceil(v0->position.y) - ceil(v2->position.y);
        prestep = ceil(v2->position.y) - v2->position.y;
        // todo: handle line sizes of height < 1
        if(v0->position.y - v2->position.y < 1) return;
    }

    dxLeft  = (v2->position.x - v0->position.x) * invDy;
    dxRight = (v1->position.x - v0->position.x) * invDy;

    duLeft  = texW * (v2->uv.u - v0->uv.u) * invDy;
    dvLeft  = texH * (v2->uv.v - v0->uv.v) * invDy;
    duRight = texW * (v1->uv.u - v0->uv.u) * invDy;
    dvRight = texH * (v1->uv.v - v0->uv.v) * invDy;

    startU = texW * v0->uv.u + duLeft * prestep;
    startV = texH * v0->uv.v + dvLeft * prestep;
    // With triangles the texture gradients (u,v slopes over the triangle surface)
    // are guaranteed to be constant, so we need to calculate du and dv only once.
    invDx = 1.f / (dxRight - dxLeft);
    du = (duRight - duLeft) * invDx;
    dv = (dvRight - dvLeft) * invDx;
    startX = v0->position.x;
    endX   = startX;
    startXPrestep = v0->position.x + dxLeft * prestep;
    endXPrestep   = v0->position.x + dxRight * prestep;

    // skip the unnecessary divisions if there's no depth testing
    if(buffer->drawOpts.depthFunc != DF_ALWAYS)
    {
        invZ0  = 1.f / v0->position.z;
        invZ1  = 1.f / v1->position.z;
        invZ2  = 1.f / v2->position.z;
        invY02 = 1.f / (v0->position.y - v2->position.y);
    }

    for(currLine = 0, y = v0->position.y; currLine <= numScanlines; y += yDir)
    {
        float u = startU;
        float v = startV;
        // variables used only if depth test is enabled
        float startInvZ, endInvZ, invLineLength = 0.f;

        // interpolate 1/z only if depth testing is enabled
        if(buffer->drawOpts.depthFunc != DF_ALWAYS)
        {
            float r1  = (v0->position.y - y) * invY02;
            startInvZ = LERP(invZ0, invZ2, r1);
            endInvZ   = LERP(invZ0, invZ1, r1);

            if(startX != endX)
                invLineLength = 1.f / (endX - startX);
        }

        for(x = startXPrestep; x <= endXPrestep; ++x)
        {
            // fetch texture data with a texArea modulus for proper effect in case u or v are > 1
            unsigned char pixel = t->texture->data[((int)u + ((int)v * t->texture->height)) % texArea];

            if(!useColorKey || (useColorKey && pixel != (unsigned char)buffer->drawOpts.colorKey))
            {
                // DF_ALWAYS = no depth test
                if(buffer->drawOpts.depthFunc == DF_ALWAYS)
                    gfx_drawPixel(ceil(x), ceil(y), pixel, buffer);
                else
                {
                    float r = (x - startX) * invLineLength;
                    float lerpInvZ = LERP(startInvZ, endInvZ, r);
                    gfx_drawPixelWithDepth(ceil(x), ceil(y), lerpInvZ, pixel, buffer);
                }
            }
            u += du;
            v += dv;
        }

        startX += dxLeft;
        endX   += dxRight;

        if(++currLine < numScanlines)
        {
            startXPrestep += dxLeft;
            endXPrestep   += dxRight;
            startU += duLeft;
            startV += dvLeft;
        }
    }
}
<commit_msg>fixed glitches when attemtping to render a zero-length scanline<commit_after>#include "src/fillers.h"
#include "src/utils.h"

/* ***** */
void gfx_flatFill(const gfx_Triangle *t, gfx_drawBuffer *buffer, enum TriangleType type)
{
    const gfx_Vertex *v0 = &t->vertices[0];
    const gfx_Vertex *v1 = &t->vertices[1];
    const gfx_Vertex *v2 = &t->vertices[2];
    double y, invDy, dxLeft, dxRight, xLeft, xRight, prestep;
    int currLine, numScanlines, x0, x1, yDir = 1;
    // variables used if depth test is enabled
    float startInvZ, endInvZ, invZ0, invZ1, invZ2, invY02;

    if(type == FLAT_BOTTOM)
    {
        invDy  = 1.0 / (v2->position.y - v0->position.y);
        numScanlines = ceil(v2->position.y) - ceil(v0->position.y);
        prestep = ceil(v0->position.y) - v0->position.y;
        // todo: handle line sizes of height < 1
        if(v2->position.y - v0->position.y < 1) return;
    }
    else
    {
        invDy  = 1.0 / (v0->position.y - v2->position.y);
        yDir = -1;
        numScanlines = ceil(v0->position.y) - ceil(v2->position.y);
        prestep = ceil(v2->position.y) - v2->position.y;
        // todo: handle line sizes of height < 1
        if(v0->position.y - v2->position.y < 1) return;
    }

    dxLeft  = (v2->position.x - v0->position.x) * invDy;
    dxRight = (v1->position.x - v0->position.x) * invDy;
    xLeft   = v0->position.x + dxLeft * prestep;
    xRight  = v0->position.x + dxRight * prestep;

    // skip the unnecessary divisions if there's no depth testing
    if(buffer->drawOpts.depthFunc != DF_ALWAYS)
    {
        invZ0  = 1.f / v0->position.z;
        invZ1  = 1.f / v1->position.z;
        invZ2  = 1.f / v2->position.z;
        invY02 = 1.f / (v0->position.y - v2->position.y);
    }

    for(currLine = 0, y = ceil(v0->position.y); currLine <= numScanlines; y += yDir)
    {
        x0 = ceil(xLeft);
        x1 = ceil(xRight);

        // interpolate 1/z only if depth testing is enabled
        if(buffer->drawOpts.depthFunc != DF_ALWAYS)
        {
            float r1  = (v0->position.y - y) * invY02;
            startInvZ = LERP(invZ0, invZ2, r1);
            endInvZ   = LERP(invZ0, invZ1, r1);
            gfx_drawLine(x0, y, 1.f/startInvZ, x1, y, 1.f/endInvZ, t->color, buffer);
        }
        else
            gfx_drawLine(x0, y, 0.f, x1, y, 0.f, t->color, buffer);

        if(++currLine < numScanlines)
        {
            xLeft  += dxLeft;
            xRight += dxRight;
        }
    }
}

/* ***** */
void gfx_perspectiveTextureMap(const gfx_Triangle *t, gfx_drawBuffer *buffer, enum TriangleType type)
{
    const gfx_Vertex *v0 = &t->vertices[0];
    const gfx_Vertex *v1 = &t->vertices[1];
    const gfx_Vertex *v2 = &t->vertices[2];
    double x, y, invDy, dxLeft, dxRight, prestep, yDir = 1;
    double startX, endX, startXPrestep, endXPrestep, lineLength;
    int   useColorKey = buffer->drawOpts.colorKey != -1 ? 1 : 0;
    int   texW = t->texture->width - 1;
    int   texH = t->texture->height - 1;
    int   texArea = texW * texH;
    int   currLine, numScanlines;
    float invZ0, invZ1, invZ2, invY02 = 1.f;

    if(type == FLAT_BOTTOM)
    {
        invDy  = 1.0 / (v2->position.y - v0->position.y);
        numScanlines = ceil(v2->position.y) - ceil(v0->position.y);
        prestep = ceil(v0->position.y) - v0->position.y;
        // todo: handle line sizes of height < 1
        if(v2->position.y - v0->position.y < 1) return;
    }
    else
    {
        invDy  = 1.0 / (v0->position.y - v2->position.y);
        yDir = -1;
        numScanlines = ceil(v0->position.y) - ceil(v2->position.y);
        prestep = ceil(v2->position.y) - v2->position.y;
        // todo: handle line sizes of height < 1
        if(v0->position.y - v2->position.y < 1) return;
    }

    dxLeft  = (v2->position.x - v0->position.x) * invDy;
    dxRight = (v1->position.x - v0->position.x) * invDy;
    startX  = v0->position.x;
    endX    = startX;
    startXPrestep = v0->position.x + dxLeft * prestep;
    endXPrestep   = v0->position.x + dxRight * prestep;

    invZ0  = 1.f / v0->position.z;
    invZ1  = 1.f / v1->position.z;
    invZ2  = 1.f / v2->position.z;
    invY02 = 1.f / (v0->position.y - v2->position.y);

    for(currLine = 0, y = v0->position.y; currLine <= numScanlines; y += yDir)
    {
        float startInvZ, endInvZ, r1, invLineLength;
        float startU = texW, startV = texH, endU = texW, endV = texH;
        lineLength = endX - startX;

        r1 = (v0->position.y - y) * invY02;
        startInvZ = LERP(invZ0, invZ2, r1);
        endInvZ   = LERP(invZ0, invZ1, r1);

        startU *= LERP(v0->uv.u * invZ0, v2->uv.u * invZ2, r1);
        startV *= LERP(v0->uv.v * invZ0, v2->uv.v * invZ2, r1);
        endU   *= LERP(v0->uv.u * invZ0, v1->uv.u * invZ1, r1);
        endV   *= LERP(v0->uv.v * invZ0, v1->uv.v * invZ1, r1);

        // skip zero-length lines
        if(lineLength)
        {
            invLineLength = 1.f / lineLength;

            for(x = startXPrestep; x <= endXPrestep; ++x)
            {
                // interpolate 1/z for each pixel in the scanline
                float r = (x - startX) * invLineLength;
                float lerpInvZ = LERP(startInvZ, endInvZ, r);
                float z = 1.f/lerpInvZ;
                float u = z * LERP(startU, endU, r);
                float v = z * LERP(startV, endV, r);

                // fetch texture data with a texArea modulus for proper effect in case u or v are > 1
                unsigned char pixel = t->texture->data[((int)u + ((int)v * t->texture->height)) % texArea];

                if(!useColorKey || (useColorKey && pixel != (unsigned char)buffer->drawOpts.colorKey))
                {
                    // DF_ALWAYS = no depth test
                    if(buffer->drawOpts.depthFunc == DF_ALWAYS)
                        gfx_drawPixel(ceil(x), ceil(y), pixel, buffer);
                    else
                        gfx_drawPixelWithDepth(ceil(x), ceil(y), lerpInvZ, pixel, buffer);
                }
            }
        }

        startX += dxLeft;
        endX   += dxRight;

        if(++currLine < numScanlines)
        {
            startXPrestep += dxLeft;
            endXPrestep   += dxRight;
        }
    }
}

/* ***** */
void gfx_affineTextureMap(const gfx_Triangle *t, gfx_drawBuffer *buffer, enum TriangleType type)
{
    const gfx_Vertex *v0 = &t->vertices[0];
    const gfx_Vertex *v1 = &t->vertices[1];
    const gfx_Vertex *v2 = &t->vertices[2];
    double x, y, invDy, dxLeft, dxRight, prestep, yDir = 1;
    double startU, startV, invDx, du, dv, lineLength;
    double startX, endX, startXPrestep, endXPrestep;
    float duLeft, dvLeft, duRight, dvRight;
    float texW = t->texture->width - 1;
    float texH = t->texture->height - 1;
    int   useColorKey = buffer->drawOpts.colorKey != -1 ? 1 : 0;
    int   texArea = texW * texH;
    int   currLine, numScanlines;
    // variables used only if depth test is enabled
    float invZ0, invZ1, invZ2, invY02 = 1.f;

    if(type == FLAT_BOTTOM)
    {
        invDy  = 1.f / (v2->position.y - v0->position.y);
        numScanlines = ceil(v2->position.y) - ceil(v0->position.y);
        prestep = ceil(v0->position.y) - v0->position.y;
        // todo: handle line sizes of height < 1
        if(v2->position.y - v0->position.y < 1) return;
    }
    else
    {
        invDy  = 1.f / (v0->position.y - v2->position.y);
        yDir = -1;
        numScanlines = ceil(v0->position.y) - ceil(v2->position.y);
        prestep = ceil(v2->position.y) - v2->position.y;
        // todo: handle line sizes of height < 1
        if(v0->position.y - v2->position.y < 1) return;
    }

    dxLeft  = (v2->position.x - v0->position.x) * invDy;
    dxRight = (v1->position.x - v0->position.x) * invDy;

    duLeft  = texW * (v2->uv.u - v0->uv.u) * invDy;
    dvLeft  = texH * (v2->uv.v - v0->uv.v) * invDy;
    duRight = texW * (v1->uv.u - v0->uv.u) * invDy;
    dvRight = texH * (v1->uv.v - v0->uv.v) * invDy;

    startU = texW * v0->uv.u + duLeft * prestep;
    startV = texH * v0->uv.v + dvLeft * prestep;
    // With triangles the texture gradients (u,v slopes over the triangle surface)
    // are guaranteed to be constant, so we need to calculate du and dv only once.
    invDx = 1.f / (dxRight - dxLeft);
    du = (duRight - duLeft) * invDx;
    dv = (dvRight - dvLeft) * invDx;
    startX = v0->position.x;
    endX   = startX;
    startXPrestep = v0->position.x + dxLeft * prestep;
    endXPrestep   = v0->position.x + dxRight * prestep;

    // skip the unnecessary divisions if there's no depth testing
    if(buffer->drawOpts.depthFunc != DF_ALWAYS)
    {
        invZ0  = 1.f / v0->position.z;
        invZ1  = 1.f / v1->position.z;
        invZ2  = 1.f / v2->position.z;
        invY02 = 1.f / (v0->position.y - v2->position.y);
    }

    for(currLine = 0, y = v0->position.y; currLine <= numScanlines; y += yDir)
    {
        float u = startU;
        float v = startV;
        // variables used only if depth test is enabled
        float startInvZ, endInvZ, invLineLength;
        lineLength = endX - startX;

        // interpolate 1/z only if depth testing is enabled
        if(buffer->drawOpts.depthFunc != DF_ALWAYS)
        {
            float r1  = (v0->position.y - y) * invY02;
            startInvZ = LERP(invZ0, invZ2, r1);
            endInvZ   = LERP(invZ0, invZ1, r1);

            if(lineLength)
                invLineLength = 1.f / lineLength;
        }

        // skip zero-length lines
        if(lineLength)
        {
            for(x = startXPrestep; x <= endXPrestep; ++x)
            {
                // fetch texture data with a texArea modulus for proper effect in case u or v are > 1
                unsigned char pixel = t->texture->data[((int)u + ((int)v * t->texture->height)) % texArea];

                if(!useColorKey || (useColorKey && pixel != (unsigned char)buffer->drawOpts.colorKey))
                {
                    // DF_ALWAYS = no depth test
                    if(buffer->drawOpts.depthFunc == DF_ALWAYS)
                        gfx_drawPixel(ceil(x), ceil(y), pixel, buffer);
                    else
                    {
                        float r = (x - startX) * invLineLength;
                        float lerpInvZ = LERP(startInvZ, endInvZ, r);
                        gfx_drawPixelWithDepth(ceil(x), ceil(y), lerpInvZ, pixel, buffer);
                    }
                }
                u += du;
                v += dv;
            }
        }

        startX += dxLeft;
        endX   += dxRight;

        if(++currLine < numScanlines)
        {
            startXPrestep += dxLeft;
            endXPrestep   += dxRight;
            startU += duLeft;
            startV += dvLeft;
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef TEST_ARRAY_GENERATOR_HPP_
#define TEST_ARRAY_GENERATOR_HPP_

#include <climits>
#include <random>
#include <string>
#include <type_traits>

/**
 * Helper function to generate a test pattern for boolean type.
 * Alternating true (even index) and false (odd index) pattern.
 * @param C Container (vector, array, etc) to be filled
 * @param size How many elements to fill in. Must size<=container_size
 */
template<
  typename C,
  typename std::enable_if<
    std::is_same<typename C::value_type, bool>::value
  >::type * = nullptr
>
void test_vector_fill(
  C * container, size_t size, bool val1 = true, bool val2 = false)
{
  for (size_t i = 0; i < size; i++) {
    if ((i % 2) == 0) {
      (*container)[i] = val2;
    } else {
      (*container)[i] = val1;
    }
  }
}

/**
 * Helper function to generate a test pattern for integer number types.
 * The template type parameter must be an integer number type.
 * Mininum and maximum values for the type and distributed values in the middle.
 * @param C Container (vector, array, etc) to be filled
 * @param size How many elements to fill in. Must size<=container_size
 * @param min Minimum value in the range to fill.
 * @param max Maximum value in the range to fill.
 */
template<
  typename C,
  typename std::enable_if<
    std::is_integral<typename C::value_type>::value &&
    !std::is_same<typename C::value_type, bool>::value
  >::type * = nullptr
>
void test_vector_fill(
  C * container, size_t size,
  typename C::value_type min, typename C::value_type max)
{
  if (size > 0 && min < max) {
    size_t step = (max - min) / size;
    (*container)[0] = min;
    for (size_t i = 1; i < size - 1; i++) {
      (*container)[i] = min + static_cast<typename C::value_type>(i * step);
    }
    (*container)[size - 1] = max;
  }
}

/**
 * Helper function to generate a test pattern for float number types.
 * Mininum and maximum values for the type and distributed values in the middle.
 * @param C Container (vector, array, etc) to be filled
 * @param size How many elements to fill in. Must size<=container_size
 * @param min Minimum value in the range to fill.
 * @param max Maximum value in the range to fill.
 */
template<
  typename C,
  typename std::enable_if<
    std::is_floating_point<typename C::value_type>::value
  >::type * = nullptr
>
void test_vector_fill(
  C * container, size_t size,
  typename C::value_type min, typename C::value_type max)
{
  if (size > 0 && min < max) {
    typename C::value_type step = (max - min) / static_cast<typename C::value_type>(size);
    (*container)[0] = min;
    for (size_t i = 1; i < size - 1; i++) {
      (*container)[i] = min + static_cast<typename C::value_type>(i * step);
    }
    (*container)[size - 1] = max;
  }
}

/**
 * Helper function to generate a test pattern for string types.
 * Mininum and maximum values for the type and distributed values in the middle.
 * @param C Container (vector, array, etc) to be filled
 * @param size How many elements to fill in. Must size<=container_size
 * @param min Minimum value in the range to fill.
 * @param max Maximum value in the range to fill.
 * @param minlength Minimum length of the generated strings.
 * @param maxlength Maximum length of the generated strings.
 */
template<
  typename C,
  typename std::enable_if<
    std::is_same<typename C::value_type, typename std::string>::value
  >::type * = nullptr
>
void test_vector_fill(
  C * container, size_t size,
  int min, int max,
  int minlength, const int maxlength)
{
  if (size > 0 && min < max && minlength < maxlength) {
    size_t step = (max - min) / size;
    size_t step_length = (maxlength - minlength) / size;
    char * tmpstr = static_cast<char *>(malloc(maxlength + 1));
    std::snprintf(tmpstr, minlength + 1, "%*d", minlength, min);
    (*container)[0] = std::string(tmpstr);
    for (size_t i = 1; i < size - 1; i++) {
      int value = min + static_cast<int>(i * step);
      int length = minlength + static_cast<int>(i * step_length);
      std::snprintf(tmpstr, length + 1, "%*d", length, value);
      (*container)[i] = std::string(tmpstr);
    }
    std::snprintf(tmpstr, maxlength + 1, "%*d", maxlength, max);
    (*container)[size - 1] = std::string(tmpstr);
  }
}

#endif  // TEST_ARRAY_GENERATOR_HPP_
<commit_msg>free tmpstr to fix memory leak (#295)<commit_after>// Copyright 2015 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef TEST_ARRAY_GENERATOR_HPP_
#define TEST_ARRAY_GENERATOR_HPP_

#include <climits>
#include <random>
#include <string>
#include <type_traits>

/**
 * Helper function to generate a test pattern for boolean type.
 * Alternating true (even index) and false (odd index) pattern.
 * @param C Container (vector, array, etc) to be filled
 * @param size How many elements to fill in. Must size<=container_size
 */
template<
  typename C,
  typename std::enable_if<
    std::is_same<typename C::value_type, bool>::value
  >::type * = nullptr
>
void test_vector_fill(
  C * container, size_t size, bool val1 = true, bool val2 = false)
{
  for (size_t i = 0; i < size; i++) {
    if ((i % 2) == 0) {
      (*container)[i] = val2;
    } else {
      (*container)[i] = val1;
    }
  }
}

/**
 * Helper function to generate a test pattern for integer number types.
 * The template type parameter must be an integer number type.
 * Mininum and maximum values for the type and distributed values in the middle.
 * @param C Container (vector, array, etc) to be filled
 * @param size How many elements to fill in. Must size<=container_size
 * @param min Minimum value in the range to fill.
 * @param max Maximum value in the range to fill.
 */
template<
  typename C,
  typename std::enable_if<
    std::is_integral<typename C::value_type>::value &&
    !std::is_same<typename C::value_type, bool>::value
  >::type * = nullptr
>
void test_vector_fill(
  C * container, size_t size,
  typename C::value_type min, typename C::value_type max)
{
  if (size > 0 && min < max) {
    size_t step = (max - min) / size;
    (*container)[0] = min;
    for (size_t i = 1; i < size - 1; i++) {
      (*container)[i] = min + static_cast<typename C::value_type>(i * step);
    }
    (*container)[size - 1] = max;
  }
}

/**
 * Helper function to generate a test pattern for float number types.
 * Mininum and maximum values for the type and distributed values in the middle.
 * @param C Container (vector, array, etc) to be filled
 * @param size How many elements to fill in. Must size<=container_size
 * @param min Minimum value in the range to fill.
 * @param max Maximum value in the range to fill.
 */
template<
  typename C,
  typename std::enable_if<
    std::is_floating_point<typename C::value_type>::value
  >::type * = nullptr
>
void test_vector_fill(
  C * container, size_t size,
  typename C::value_type min, typename C::value_type max)
{
  if (size > 0 && min < max) {
    typename C::value_type step = (max - min) / static_cast<typename C::value_type>(size);
    (*container)[0] = min;
    for (size_t i = 1; i < size - 1; i++) {
      (*container)[i] = min + static_cast<typename C::value_type>(i * step);
    }
    (*container)[size - 1] = max;
  }
}

/**
 * Helper function to generate a test pattern for string types.
 * Mininum and maximum values for the type and distributed values in the middle.
 * @param C Container (vector, array, etc) to be filled
 * @param size How many elements to fill in. Must size<=container_size
 * @param min Minimum value in the range to fill.
 * @param max Maximum value in the range to fill.
 * @param minlength Minimum length of the generated strings.
 * @param maxlength Maximum length of the generated strings.
 */
template<
  typename C,
  typename std::enable_if<
    std::is_same<typename C::value_type, typename std::string>::value
  >::type * = nullptr
>
void test_vector_fill(
  C * container, size_t size,
  int min, int max,
  int minlength, const int maxlength)
{
  if (size > 0 && min < max && minlength < maxlength) {
    size_t step = (max - min) / size;
    size_t step_length = (maxlength - minlength) / size;
    char * tmpstr = static_cast<char *>(malloc(maxlength + 1));
    std::snprintf(tmpstr, minlength + 1, "%*d", minlength, min);
    (*container)[0] = std::string(tmpstr);
    for (size_t i = 1; i < size - 1; i++) {
      int value = min + static_cast<int>(i * step);
      int length = minlength + static_cast<int>(i * step_length);
      std::snprintf(tmpstr, length + 1, "%*d", length, value);
      (*container)[i] = std::string(tmpstr);
    }
    std::snprintf(tmpstr, maxlength + 1, "%*d", maxlength, max);
    (*container)[size - 1] = std::string(tmpstr);
    free(tmpstr);
  }
}

#endif  // TEST_ARRAY_GENERATOR_HPP_
<|endoftext|>