<commit_before>/*
 * Copyright (c) 2015-2019 Dubalu LLC
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#include "cast.h"

#include "database/schema.h"
#include "exception_xapian.h"                     // for CastError
#include "strings.hh"                             // for strings::format

MsgPack
Cast::cast(const MsgPack& obj)
{
	if (obj.size() == 1) {
		const auto str_key = obj.begin()->str();
		switch (get_hash_type(str_key)) {
			case HashType::INTEGER:
				return integer(obj.at(str_key));
			case HashType::POSITIVE:
				return positive(obj.at(str_key));
			case HashType::FLOAT:
				return static_cast<double>(floating(obj.at(str_key)));
			case HashType::BOOLEAN:
				return boolean(obj.at(str_key));
			case HashType::KEYWORD:
			case HashType::TEXT:
			case HashType::STRING:
				return string(obj.at(str_key));
			case HashType::UUID:
				return uuid(obj.at(str_key));
			case HashType::DATE:
			case HashType::DATETIME:
				return datetime(obj.at(str_key));
			case HashType::TIME:
				return time(obj.at(str_key));
			case HashType::TIMEDELTA:
				return timedelta(obj.at(str_key));
			case HashType::EWKT:
				return ewkt(obj.at(str_key));
			case HashType::POINT:
			case HashType::CIRCLE:
			case HashType::CONVEX:
			case HashType::POLYGON:
			case HashType::CHULL:
			case HashType::MULTIPOINT:
			case HashType::MULTICIRCLE:
			case HashType::MULTIPOLYGON:
			case HashType::MULTICHULL:
			case HashType::GEO_COLLECTION:
			case HashType::GEO_INTERSECTION:
				return obj;
			default:
				THROW(CastError, "Unknown cast type {}", str_key);
		}
	}

	THROW(CastError, "Expected map with one element");
}

MsgPack
Cast::cast(FieldType type, const MsgPack& obj)
{
	switch (type) {
		case FieldType::integer:
			return integer(obj);
		case FieldType::positive:
			return positive(obj);
		case FieldType::floating:
			return static_cast<double>(floating(obj));
		case FieldType::boolean:
			return boolean(obj);
		case FieldType::keyword:
		case FieldType::text:
		case FieldType::string:
			return string(obj);
		case FieldType::uuid:
			return uuid(obj);
		case FieldType::date:
		case FieldType::datetime:
			return datetime(obj);
		case FieldType::time:
			return time(obj);
		case FieldType::timedelta:
			return timedelta(obj);
		case FieldType::script:
			if (obj.is_map()) {
				return obj;
			}
			THROW(CastError, "Type {} cannot be cast to script", enum_name(obj.get_type()));
		case FieldType::geo:
			if (obj.is_map() || obj.is_string()) {
				return obj;
			}
			THROW(CastError, "Type {} cannot be cast to geo", enum_name(obj.get_type()));
		case FieldType::empty:
			if (obj.is_string()) {
				{
					// Try like INTEGER.
					int errno_save;
					auto r = strict_stoll(&errno_save, obj.str_view());
					if (errno_save == 0) {
						return MsgPack(r);
					}
				}
				{
					// Try like POSITIVE.
					int errno_save;
					auto r = strict_stoull(&errno_save, obj.str_view());
					if (errno_save == 0) {
						return MsgPack(r);
					}
				}
				{
					// Try like FLOAT
					int errno_save;
					auto r = strict_stod(&errno_save, obj.str_view());
					if (errno_save == 0) {
						return MsgPack(r);
					}
				}
				return obj;
			}
			[[fallthrough]];
		default:
			THROW(CastError, "Type {} cannot be cast", enum_name(obj.get_type()));
	}
}

int64_t
Cast::integer(const MsgPack& obj)
{
	switch (obj.get_type()) {
		case MsgPack::Type::POSITIVE_INTEGER:
			return obj.u64();
		case MsgPack::Type::NEGATIVE_INTEGER:
			return obj.i64();
		case MsgPack::Type::FLOAT:
			return obj.f64();
		case MsgPack::Type::STR: {
			int errno_save;
			auto r = strict_stoll(&errno_save, obj.str_view());
			if (errno_save != 0) {
				THROW(CastError, "Value {} cannot be cast to integer", enum_name(obj.get_type()));
			}
			return r;
		}
		case MsgPack::Type::BOOLEAN:
			return static_cast<int64_t>(obj.boolean());
		default:
			THROW(CastError, "Type {} cannot be cast to integer", enum_name(obj.get_type()));
	}
}

uint64_t
Cast::positive(const MsgPack& obj)
{
	switch (obj.get_type()) {
		case MsgPack::Type::POSITIVE_INTEGER:
			return obj.u64();
		case MsgPack::Type::NEGATIVE_INTEGER:
			return obj.i64();
		case MsgPack::Type::FLOAT:
			return obj.f64();
		case MsgPack::Type::STR: {
			int errno_save;
			auto r = strict_stoull(&errno_save, obj.str_view());
			if (errno_save != 0) {
				THROW(CastError, "Value {} cannot be cast to positive", enum_name(obj.get_type()));
			}
			return r;
		}
		case MsgPack::Type::BOOLEAN:
			return static_cast<uint64_t>(obj.boolean());
		default:
			THROW(CastError, "Type {} cannot be cast to positive", enum_name(obj.get_type()));
	}
}

long double
Cast::floating(const MsgPack& obj)
{
	switch (obj.get_type()) {
		case MsgPack::Type::POSITIVE_INTEGER:
			return obj.u64();
		case MsgPack::Type::NEGATIVE_INTEGER:
			return obj.i64();
		case MsgPack::Type::FLOAT:
			return obj.f64();
		case MsgPack::Type::STR: {
			int errno_save;
			auto r = strict_stod(&errno_save, obj.str_view());
			if (errno_save != 0) {
				THROW(CastError, "Value {} cannot be cast to float", enum_name(obj.get_type()));
			}
			return r;
		}
		case MsgPack::Type::BOOLEAN:
			return static_cast<double>(obj.boolean());
		default:
			THROW(CastError, "Type {} cannot be cast to float", enum_name(obj.get_type()));
	}
}

std::string
Cast::string(const MsgPack& obj)
{
	switch (obj.get_type()) {
		case MsgPack::Type::POSITIVE_INTEGER:
			return strings::format("{}", obj.u64());
		case MsgPack::Type::NEGATIVE_INTEGER:
			return strings::format("{}", obj.i64());
		case MsgPack::Type::FLOAT:
			return strings::format("{}", obj.f64());
		case MsgPack::Type::STR:
			return obj.str();
		case MsgPack::Type::BOOLEAN:
			return obj.boolean() ? "true" : "false";
		default:
			return obj.to_string();
	}
}

bool
Cast::boolean(const MsgPack& obj)
{
	switch (obj.get_type()) {
		case MsgPack::Type::POSITIVE_INTEGER:
			return obj.u64() != 0;
		case MsgPack::Type::NEGATIVE_INTEGER:
			return obj.i64() != 0;
		case MsgPack::Type::FLOAT:
			return obj.f64() != 0;
		case MsgPack::Type::STR: {
			auto value = obj.str_view();
			switch (value.size()) {
				case 0:
					return false;
				case 1:
					switch (value[0]) {
						case '0':
						case 'f':
						case 'F':
							return false;
						// case '1':
						// case 't':
						// case 'T':
						// 	return true;
					}
					break;
				// case 4:
				// 	switch (value[0]) {
				// 		case 't':
				// 		case 'T': {
				// 			auto lower_value = strings::lower(value);
				// 			if (lower_value == "true") {
				// 				return true;
				// 			}
				// 		}
				// 	}
				// 	break;
				case 5:
					switch (value[0]) {
						case 'f':
						case 'F': {
							auto lower_value = strings::lower(value);
							if (lower_value == "false") {
								return false;
							}
						}
					}
					break;
			}
			return true;
		}
		case MsgPack::Type::BOOLEAN:
			return obj.boolean();
		default:
			THROW(CastError, "Type {} cannot be cast to boolean", enum_name(obj.get_type()));
	}
}

std::string
Cast::uuid(const MsgPack& obj)
{
	if (obj.is_string()) {
		return obj.str();
	}
	THROW(CastError, "Type {} cannot be cast to uuid", enum_name(obj.get_type()));
}

MsgPack
Cast::datetime(const MsgPack& obj)
{
	switch (obj.get_type()) {
		case MsgPack::Type::POSITIVE_INTEGER:
		case MsgPack::Type::NEGATIVE_INTEGER:
		case MsgPack::Type::FLOAT:
		case MsgPack::Type::STR:
		case MsgPack::Type::MAP:
			return obj;
		default:
			THROW(CastError, "Type {} cannot be cast to datetime", enum_name(obj.get_type()));
	}
}

MsgPack
Cast::time(const MsgPack& obj)
{
	switch (obj.get_type()) {
		case MsgPack::Type::POSITIVE_INTEGER:
		case MsgPack::Type::NEGATIVE_INTEGER:
		case MsgPack::Type::FLOAT:
		case MsgPack::Type::STR:
			return obj;
		default:
			THROW(CastError, "Type {} cannot be cast to time", enum_name(obj.get_type()));
	}
}

MsgPack
Cast::timedelta(const MsgPack& obj)
{
	switch (obj.get_type()) {
		case MsgPack::Type::POSITIVE_INTEGER:
		case MsgPack::Type::NEGATIVE_INTEGER:
		case MsgPack::Type::FLOAT:
		case MsgPack::Type::STR:
			return obj;
		default:
			THROW(CastError, "Type {} cannot be cast to timedelta", enum_name(obj.get_type()));
	}
}

std::string
Cast::ewkt(const MsgPack& obj)
{
	if (obj.is_string()) {
		return obj.str();
	}
	THROW(CastError, "Type {} cannot be cast to ewkt", enum_name(obj.get_type()));
}

Cast::HashType
Cast::get_hash_type(std::string_view cast_word)
{
	static const auto _ = cast_hash;
	return static_cast<HashType>(_.fhh(cast_word));
}

FieldType
Cast::get_field_type(std::string_view cast_word)
{
	if (cast_word.empty() || cast_word[0] != reserved__) {
		THROW(CastError, "Unknown cast type {}", repr(cast_word));
	}
	switch (get_hash_type(cast_word)) {
		case HashType::INTEGER:           return FieldType::integer;
		case HashType::POSITIVE:          return FieldType::positive;
		case HashType::FLOAT:             return FieldType::floating;
		case HashType::BOOLEAN:           return FieldType::boolean;
		case HashType::KEYWORD:           return FieldType::keyword;
		case HashType::TEXT:              return FieldType::text;
		case HashType::STRING:            return FieldType::string;
		case HashType::UUID:              return FieldType::uuid;
		case HashType::DATETIME:          return FieldType::datetime;
		case HashType::TIME:              return FieldType::time;
		case HashType::TIMEDELTA:         return FieldType::timedelta;
		case HashType::EWKT:              return FieldType::geo;
		case HashType::POINT:             return FieldType::geo;
		case HashType::CIRCLE:            return FieldType::geo;
		case HashType::CONVEX:            return FieldType::geo;
		case HashType::POLYGON:           return FieldType::geo;
		case HashType::CHULL:             return FieldType::geo;
		case HashType::MULTIPOINT:        return FieldType::geo;
		case HashType::MULTICIRCLE:       return FieldType::geo;
		case HashType::MULTIPOLYGON:      return FieldType::geo;
		case HashType::MULTICHULL:        return FieldType::geo;
		case HashType::GEO_COLLECTION:    return FieldType::geo;
		case HashType::GEO_INTERSECTION:  return FieldType::geo;
		case HashType::CHAI:              return FieldType::script;
		default:
			THROW(CastError, "Unknown cast type {}", repr(cast_word));
	}
}
<commit_msg>Cast: Skip comments<commit_after>/*
 * Copyright (c) 2015-2019 Dubalu LLC
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#include "cast.h"

#include "database/schema.h"
#include "exception_xapian.h"                     // for CastError
#include "reserved/reserved.h"                    // for is_comment
#include "strings.hh"                             // for strings::format

MsgPack
Cast::cast(const MsgPack& obj)
{
	auto it = obj.begin();
	auto it_e = obj.end();
	for (; it != it_e; ++it) {
		auto str_key = it->str_view();
		if (is_comment(str_key)) {
			continue;
		}
		switch (get_hash_type(str_key)) {
			case HashType::INTEGER:
				return integer(it.value());
			case HashType::POSITIVE:
				return positive(it.value());
			case HashType::FLOAT:
				return static_cast<double>(floating(it.value()));
			case HashType::BOOLEAN:
				return boolean(it.value());
			case HashType::KEYWORD:
			case HashType::TEXT:
			case HashType::STRING:
				return string(it.value());
			case HashType::UUID:
				return uuid(it.value());
			case HashType::DATE:
			case HashType::DATETIME:
				return datetime(it.value());
			case HashType::TIME:
				return time(it.value());
			case HashType::TIMEDELTA:
				return timedelta(it.value());
			case HashType::EWKT:
				return ewkt(it.value());
			case HashType::POINT:
			case HashType::CIRCLE:
			case HashType::CONVEX:
			case HashType::POLYGON:
			case HashType::CHULL:
			case HashType::MULTIPOINT:
			case HashType::MULTICIRCLE:
			case HashType::MULTIPOLYGON:
			case HashType::MULTICHULL:
			case HashType::GEO_COLLECTION:
			case HashType::GEO_INTERSECTION:
				return obj;
			default:
				THROW(CastError, "Unknown cast type {}", str_key);
		}
	}

	THROW(CastError, "Expected map with one valid cast");
}

MsgPack
Cast::cast(FieldType type, const MsgPack& obj)
{
	switch (type) {
		case FieldType::integer:
			return integer(obj);
		case FieldType::positive:
			return positive(obj);
		case FieldType::floating:
			return static_cast<double>(floating(obj));
		case FieldType::boolean:
			return boolean(obj);
		case FieldType::keyword:
		case FieldType::text:
		case FieldType::string:
			return string(obj);
		case FieldType::uuid:
			return uuid(obj);
		case FieldType::date:
		case FieldType::datetime:
			return datetime(obj);
		case FieldType::time:
			return time(obj);
		case FieldType::timedelta:
			return timedelta(obj);
		case FieldType::script:
			if (obj.is_map()) {
				return obj;
			}
			THROW(CastError, "Type {} cannot be cast to script", enum_name(obj.get_type()));
		case FieldType::geo:
			if (obj.is_map() || obj.is_string()) {
				return obj;
			}
			THROW(CastError, "Type {} cannot be cast to geo", enum_name(obj.get_type()));
		case FieldType::empty:
			if (obj.is_string()) {
				{
					// Try like INTEGER.
					int errno_save;
					auto r = strict_stoll(&errno_save, obj.str_view());
					if (errno_save == 0) {
						return MsgPack(r);
					}
				}
				{
					// Try like POSITIVE.
					int errno_save;
					auto r = strict_stoull(&errno_save, obj.str_view());
					if (errno_save == 0) {
						return MsgPack(r);
					}
				}
				{
					// Try like FLOAT
					int errno_save;
					auto r = strict_stod(&errno_save, obj.str_view());
					if (errno_save == 0) {
						return MsgPack(r);
					}
				}
				return obj;
			}
			[[fallthrough]];
		default:
			THROW(CastError, "Type {} cannot be cast", enum_name(obj.get_type()));
	}
}

int64_t
Cast::integer(const MsgPack& obj)
{
	switch (obj.get_type()) {
		case MsgPack::Type::POSITIVE_INTEGER:
			return obj.u64();
		case MsgPack::Type::NEGATIVE_INTEGER:
			return obj.i64();
		case MsgPack::Type::FLOAT:
			return obj.f64();
		case MsgPack::Type::STR: {
			int errno_save;
			auto r = strict_stoll(&errno_save, obj.str_view());
			if (errno_save != 0) {
				THROW(CastError, "Value {} cannot be cast to integer", enum_name(obj.get_type()));
			}
			return r;
		}
		case MsgPack::Type::BOOLEAN:
			return static_cast<int64_t>(obj.boolean());
		default:
			THROW(CastError, "Type {} cannot be cast to integer", enum_name(obj.get_type()));
	}
}

uint64_t
Cast::positive(const MsgPack& obj)
{
	switch (obj.get_type()) {
		case MsgPack::Type::POSITIVE_INTEGER:
			return obj.u64();
		case MsgPack::Type::NEGATIVE_INTEGER:
			return obj.i64();
		case MsgPack::Type::FLOAT:
			return obj.f64();
		case MsgPack::Type::STR: {
			int errno_save;
			auto r = strict_stoull(&errno_save, obj.str_view());
			if (errno_save != 0) {
				THROW(CastError, "Value {} cannot be cast to positive", enum_name(obj.get_type()));
			}
			return r;
		}
		case MsgPack::Type::BOOLEAN:
			return static_cast<uint64_t>(obj.boolean());
		default:
			THROW(CastError, "Type {} cannot be cast to positive", enum_name(obj.get_type()));
	}
}

long double
Cast::floating(const MsgPack& obj)
{
	switch (obj.get_type()) {
		case MsgPack::Type::POSITIVE_INTEGER:
			return obj.u64();
		case MsgPack::Type::NEGATIVE_INTEGER:
			return obj.i64();
		case MsgPack::Type::FLOAT:
			return obj.f64();
		case MsgPack::Type::STR: {
			int errno_save;
			auto r = strict_stod(&errno_save, obj.str_view());
			if (errno_save != 0) {
				THROW(CastError, "Value {} cannot be cast to float", enum_name(obj.get_type()));
			}
			return r;
		}
		case MsgPack::Type::BOOLEAN:
			return static_cast<double>(obj.boolean());
		default:
			THROW(CastError, "Type {} cannot be cast to float", enum_name(obj.get_type()));
	}
}

std::string
Cast::string(const MsgPack& obj)
{
	switch (obj.get_type()) {
		case MsgPack::Type::POSITIVE_INTEGER:
			return strings::format("{}", obj.u64());
		case MsgPack::Type::NEGATIVE_INTEGER:
			return strings::format("{}", obj.i64());
		case MsgPack::Type::FLOAT:
			return strings::format("{}", obj.f64());
		case MsgPack::Type::STR:
			return obj.str();
		case MsgPack::Type::BOOLEAN:
			return obj.boolean() ? "true" : "false";
		default:
			return obj.to_string();
	}
}

bool
Cast::boolean(const MsgPack& obj)
{
	switch (obj.get_type()) {
		case MsgPack::Type::POSITIVE_INTEGER:
			return obj.u64() != 0;
		case MsgPack::Type::NEGATIVE_INTEGER:
			return obj.i64() != 0;
		case MsgPack::Type::FLOAT:
			return obj.f64() != 0;
		case MsgPack::Type::STR: {
			auto value = obj.str_view();
			switch (value.size()) {
				case 0:
					return false;
				case 1:
					switch (value[0]) {
						case '0':
						case 'f':
						case 'F':
							return false;
						// case '1':
						// case 't':
						// case 'T':
						// 	return true;
					}
					break;
				// case 4:
				// 	switch (value[0]) {
				// 		case 't':
				// 		case 'T': {
				// 			auto lower_value = strings::lower(value);
				// 			if (lower_value == "true") {
				// 				return true;
				// 			}
				// 		}
				// 	}
				// 	break;
				case 5:
					switch (value[0]) {
						case 'f':
						case 'F': {
							auto lower_value = strings::lower(value);
							if (lower_value == "false") {
								return false;
							}
						}
					}
					break;
			}
			return true;
		}
		case MsgPack::Type::BOOLEAN:
			return obj.boolean();
		default:
			THROW(CastError, "Type {} cannot be cast to boolean", enum_name(obj.get_type()));
	}
}

std::string
Cast::uuid(const MsgPack& obj)
{
	if (obj.is_string()) {
		return obj.str();
	}
	THROW(CastError, "Type {} cannot be cast to uuid", enum_name(obj.get_type()));
}

MsgPack
Cast::datetime(const MsgPack& obj)
{
	switch (obj.get_type()) {
		case MsgPack::Type::POSITIVE_INTEGER:
		case MsgPack::Type::NEGATIVE_INTEGER:
		case MsgPack::Type::FLOAT:
		case MsgPack::Type::STR:
		case MsgPack::Type::MAP:
			return obj;
		default:
			THROW(CastError, "Type {} cannot be cast to datetime", enum_name(obj.get_type()));
	}
}

MsgPack
Cast::time(const MsgPack& obj)
{
	switch (obj.get_type()) {
		case MsgPack::Type::POSITIVE_INTEGER:
		case MsgPack::Type::NEGATIVE_INTEGER:
		case MsgPack::Type::FLOAT:
		case MsgPack::Type::STR:
			return obj;
		default:
			THROW(CastError, "Type {} cannot be cast to time", enum_name(obj.get_type()));
	}
}

MsgPack
Cast::timedelta(const MsgPack& obj)
{
	switch (obj.get_type()) {
		case MsgPack::Type::POSITIVE_INTEGER:
		case MsgPack::Type::NEGATIVE_INTEGER:
		case MsgPack::Type::FLOAT:
		case MsgPack::Type::STR:
			return obj;
		default:
			THROW(CastError, "Type {} cannot be cast to timedelta", enum_name(obj.get_type()));
	}
}

std::string
Cast::ewkt(const MsgPack& obj)
{
	if (obj.is_string()) {
		return obj.str();
	}
	THROW(CastError, "Type {} cannot be cast to ewkt", enum_name(obj.get_type()));
}

Cast::HashType
Cast::get_hash_type(std::string_view cast_word)
{
	static const auto _ = cast_hash;
	return static_cast<HashType>(_.fhh(cast_word));
}

FieldType
Cast::get_field_type(std::string_view cast_word)
{
	if (cast_word.empty() || cast_word[0] != reserved__) {
		THROW(CastError, "Unknown cast type {}", repr(cast_word));
	}
	switch (get_hash_type(cast_word)) {
		case HashType::INTEGER:           return FieldType::integer;
		case HashType::POSITIVE:          return FieldType::positive;
		case HashType::FLOAT:             return FieldType::floating;
		case HashType::BOOLEAN:           return FieldType::boolean;
		case HashType::KEYWORD:           return FieldType::keyword;
		case HashType::TEXT:              return FieldType::text;
		case HashType::STRING:            return FieldType::string;
		case HashType::UUID:              return FieldType::uuid;
		case HashType::DATETIME:          return FieldType::datetime;
		case HashType::TIME:              return FieldType::time;
		case HashType::TIMEDELTA:         return FieldType::timedelta;
		case HashType::EWKT:              return FieldType::geo;
		case HashType::POINT:             return FieldType::geo;
		case HashType::CIRCLE:            return FieldType::geo;
		case HashType::CONVEX:            return FieldType::geo;
		case HashType::POLYGON:           return FieldType::geo;
		case HashType::CHULL:             return FieldType::geo;
		case HashType::MULTIPOINT:        return FieldType::geo;
		case HashType::MULTICIRCLE:       return FieldType::geo;
		case HashType::MULTIPOLYGON:      return FieldType::geo;
		case HashType::MULTICHULL:        return FieldType::geo;
		case HashType::GEO_COLLECTION:    return FieldType::geo;
		case HashType::GEO_INTERSECTION:  return FieldType::geo;
		case HashType::CHAI:              return FieldType::script;
		default:
			THROW(CastError, "Unknown cast type {}", repr(cast_word));
	}
}
<|endoftext|>


<commit_before>/*-------------------------------------------------------------------------
 *
 * nested_loop_join.cpp
 * file description
 *
 * Copyright(c) 2015, CMU
 *
 * /peloton/src/executor/nested_loop_join_executor.cpp
 *
 *-------------------------------------------------------------------------
 */

#include "backend/executor/nested_loop_join_executor.h"

#include <vector>

#include "backend/common/types.h"
#include "backend/common/logger.h"
#include "backend/executor/logical_tile_factory.h"
#include "backend/expression/abstract_expression.h"
#include "backend/expression/container_tuple.h"

namespace peloton {
namespace executor {

/**
 * @brief Constructor for nested loop join executor.
 * @param node Nested loop join node corresponding to this executor.
 */
NestedLoopJoinExecutor::NestedLoopJoinExecutor(planner::AbstractPlanNode *node,
                                               ExecutorContext *executor_context)
            : AbstractExecutor(node, executor_context) {}

/**
 * @brief Do some basic checks and create the schema for the output logical
 * tiles.
 * @return true on success, false otherwise.
 */
bool NestedLoopJoinExecutor::DInit() {
  assert(children_.size() == 2);

  // Grab data from plan node.
  const planner::NestedLoopJoinNode &node =
      GetPlanNode<planner::NestedLoopJoinNode>();

  // NOTE: predicate can be null for cartesian product
  predicate_ = node.GetPredicate();
  left_scan_start = true;
  proj_info_ = node.GetProjInfo();

  return true;
}

/**
 * @brief Creates logical tiles from the two input logical tiles after applying
 * join predicate.
 * @return true on success, false otherwise.
 */
bool NestedLoopJoinExecutor::DExecute() {
  LOG_TRACE("********** Nested Loop Join executor :: 2 children \n");

  bool right_scan_end = false;
  // Try to get next tile from RIGHT child
  if (children_[1]->Execute() == false) {
    LOG_TRACE("Did not get right tile \n");
    right_scan_end = true;
  }

  if (right_scan_end == true) {
    LOG_TRACE("Resetting scan for right tile \n");
    children_[1]->Init();
    if (children_[1]->Execute() == false) {
      LOG_ERROR("Did not get right tile on second try\n");
      return false;
    }
  }

  LOG_TRACE("Got right tile \n");

  if (left_scan_start == true || right_scan_end == true) {
    left_scan_start = false;
    // Try to get next tile from LEFT child
    if (children_[0]->Execute() == false) {
      LOG_TRACE("Did not get left tile \n");
      return false;
    }
    LOG_TRACE("Got left tile \n");
  } else {
    LOG_TRACE("Already have left tile \n");
  }

  std::unique_ptr<LogicalTile> left_tile(children_[0]->GetOutput());
  std::unique_ptr<LogicalTile> right_tile(children_[1]->GetOutput());

  // Check the input logical tiles.
  assert(left_tile.get() != nullptr);
  assert(right_tile.get() != nullptr);

  // Construct output logical tile.
  std::unique_ptr<LogicalTile> output_tile(LogicalTileFactory::GetTile());

  auto left_tile_schema = left_tile.get()->GetSchema();
  auto right_tile_schema = right_tile.get()->GetSchema();

  for (auto &col : right_tile_schema) {
    col.position_list_idx += left_tile.get()->GetPositionLists().size();
  }

  auto output_tile_schema = BuildSchema(left_tile_schema, right_tile_schema);

  // Set the output logical tile schema
  output_tile.get()->SetSchema(std::move(output_tile_schema));

  // Now, let's compute the position lists for the output tile

  // Cartesian product

  // Add everything from two logical tiles
  auto left_tile_position_lists = left_tile.get()->GetPositionLists();
  auto right_tile_position_lists = right_tile.get()->GetPositionLists();

  // Compute output tile column count
  size_t left_tile_column_count = left_tile_position_lists.size();
  size_t right_tile_column_count = right_tile_position_lists.size();
  size_t output_tile_column_count =
      left_tile_column_count + right_tile_column_count;

  assert(left_tile_column_count > 0);
  assert(right_tile_column_count > 0);

  // Compute output tile row count
  size_t left_tile_row_count = left_tile_position_lists[0].size();
  size_t right_tile_row_count = right_tile_position_lists[0].size();

  // Construct position lists for output tile
  std::vector<std::vector<oid_t> > position_lists;
  for (size_t column_itr = 0; column_itr < output_tile_column_count;
       column_itr++)
    position_lists.push_back(std::vector<oid_t>());

  LOG_TRACE("left col count: %lu, right col count: %lu", left_tile_column_count, right_tile_column_count);
  LOG_TRACE("left col count: %lu, right col count: %lu", left_tile.get()->GetColumnCount(), right_tile.get()->GetColumnCount());
  LOG_TRACE("left row count: %lu, right row count: %lu", left_tile_row_count, right_tile_row_count);

  auto &direct_map_list = proj_info_->GetDirectMapList();

  // Go over every pair of tuples in left and right logical tiles
  for (size_t left_tile_row_itr = 0; left_tile_row_itr < left_tile_row_count;
       left_tile_row_itr++) {
    for (size_t right_tile_row_itr = 0;
         right_tile_row_itr < right_tile_row_count; right_tile_row_itr++) {
      // TODO: OPTIMIZATION : Can split the control flow into two paths -
      // one for cartesian product and one for join
      // Then, we can skip this branch atleast for the cartesian product path.

      // Join predicate exists
      if (predicate_ != nullptr) {
        expression::ContainerTuple<executor::LogicalTile> left_tuple(
            left_tile.get(), left_tile_row_itr);
        expression::ContainerTuple<executor::LogicalTile> right_tuple(
            right_tile.get(), right_tile_row_itr);

        // Join predicate is false. Skip pair and continue.
        if (predicate_->Evaluate(&left_tuple, &right_tuple, executor_context_)
                .IsFalse()) {
          continue;
        }
      }

      // Insert a tuple into the output logical tile
      for (auto &entry : direct_map_list) {
        if (entry.second.first == 0) {
         position_lists[entry.first].push_back(
            left_tile_position_lists[entry.second.second]
                                    [left_tile_row_itr]);
        } else {
          position_lists[entry.first]
            .push_back(right_tile_position_lists[entry.second.second]
                                                [right_tile_row_itr]);
        }
      }

      // First, copy the elements in left logical tile's tuple
    }
  }

  for (auto col : position_lists) {
    LOG_TRACE("col");
    for (auto elm : col) {
      (void)elm;  // silent compiler
      LOG_TRACE("elm: %u", elm);
    }
  }

  // Check if we have any matching tuples.
  if (position_lists[0].size() > 0) {
    output_tile.get()->SetPositionListsAndVisibility(std::move(position_lists));
    SetOutput(output_tile.release());
    return true;
  }
  // Try again
  else {
    // If we are out of any more pairs of child tiles to examine,
    // then we will return false earlier in this function.
    // So, we don't have to return false here.
    DExecute();
  }

  return true;
}

std::vector<LogicalTile::ColumnInfo> NestedLoopJoinExecutor::BuildSchema(std::vector<LogicalTile::ColumnInfo> left,
                                                  std::vector<LogicalTile::ColumnInfo> right) {

  assert(proj_info_->GetTargetList().size() == 0);
  auto &direct_map_list = proj_info_->GetDirectMapList();
  std::vector<LogicalTile::ColumnInfo> schema(direct_map_list.size());
  for (auto &entry : direct_map_list) {
    if (entry.second.first == 0) {
      assert(entry.second.second < left.size());
      schema[entry.first] = left[entry.second.second];
    } else {
      assert(entry.second.second < right.size());
      schema[entry.first] = right[entry.second.second];
    }
  }
  return schema;
}

}  // namespace executor
}  // namespace peloton
<commit_msg>projection for join is working<commit_after>/*-------------------------------------------------------------------------
 *
 * nested_loop_join.cpp
 * file description
 *
 * Copyright(c) 2015, CMU
 *
 * /peloton/src/executor/nested_loop_join_executor.cpp
 *
 *-------------------------------------------------------------------------
 */

#include "backend/executor/nested_loop_join_executor.h"

#include <vector>

#include "backend/common/types.h"
#include "backend/common/logger.h"
#include "backend/executor/logical_tile_factory.h"
#include "backend/expression/abstract_expression.h"
#include "backend/expression/container_tuple.h"

namespace peloton {
namespace executor {

/**
 * @brief Constructor for nested loop join executor.
 * @param node Nested loop join node corresponding to this executor.
 */
NestedLoopJoinExecutor::NestedLoopJoinExecutor(planner::AbstractPlanNode *node,
                                               ExecutorContext *executor_context)
            : AbstractExecutor(node, executor_context) {}

/**
 * @brief Do some basic checks and create the schema for the output logical
 * tiles.
 * @return true on success, false otherwise.
 */
bool NestedLoopJoinExecutor::DInit() {
  assert(children_.size() == 2);

  // Grab data from plan node.
  const planner::NestedLoopJoinNode &node =
      GetPlanNode<planner::NestedLoopJoinNode>();

  // NOTE: predicate can be null for cartesian product
  predicate_ = node.GetPredicate();
  left_scan_start = true;
  proj_info_ = node.GetProjInfo();

  return true;
}

/**
 * @brief Creates logical tiles from the two input logical tiles after applying
 * join predicate.
 * @return true on success, false otherwise.
 */
bool NestedLoopJoinExecutor::DExecute() {
  LOG_INFO("********** Nested Loop Join executor :: 2 children \n");

  bool right_scan_end = false;
  // Try to get next tile from RIGHT child
  if (children_[1]->Execute() == false) {
    LOG_INFO("Did not get right tile \n");
    right_scan_end = true;
  }

  if (right_scan_end == true) {
    LOG_INFO("Resetting scan for right tile \n");
    children_[1]->Init();
    if (children_[1]->Execute() == false) {
      LOG_ERROR("Did not get right tile on second try\n");
      return false;
    }
  }

  LOG_INFO("Got right tile \n");

  if (left_scan_start == true || right_scan_end == true) {
    left_scan_start = false;
    // Try to get next tile from LEFT child
    if (children_[0]->Execute() == false) {
      LOG_INFO("Did not get left tile \n");
      return false;
    }
    LOG_INFO("Got left tile \n");
  } else {
    LOG_INFO("Already have left tile \n");
  }

  std::unique_ptr<LogicalTile> left_tile(children_[0]->GetOutput());
  std::unique_ptr<LogicalTile> right_tile(children_[1]->GetOutput());

  // Check the input logical tiles.
  assert(left_tile.get() != nullptr);
  assert(right_tile.get() != nullptr);

  // Construct output logical tile.
  std::unique_ptr<LogicalTile> output_tile(LogicalTileFactory::GetTile());

  auto left_tile_schema = left_tile.get()->GetSchema();
  auto right_tile_schema = right_tile.get()->GetSchema();

  for (auto &col : right_tile_schema) {
    col.position_list_idx += left_tile.get()->GetPositionLists().size();
  }

  auto output_tile_schema = BuildSchema(left_tile_schema, right_tile_schema);

  // Set the output logical tile schema
  output_tile.get()->SetSchema(std::move(output_tile_schema));

  // Now, let's compute the position lists for the output tile

  // Cartesian product

  // Add everything from two logical tiles
  auto left_tile_position_lists = left_tile.get()->GetPositionLists();
  auto right_tile_position_lists = right_tile.get()->GetPositionLists();

  // Compute output tile column count
  size_t left_tile_column_count = left_tile_position_lists.size();
  size_t right_tile_column_count = right_tile_position_lists.size();
  size_t output_tile_column_count =
      left_tile_column_count + right_tile_column_count;

  assert(left_tile_column_count > 0);
  assert(right_tile_column_count > 0);

  // Compute output tile row count
  size_t left_tile_row_count = left_tile_position_lists[0].size();
  size_t right_tile_row_count = right_tile_position_lists[0].size();

  // Construct position lists for output tile
  std::vector<std::vector<oid_t> > position_lists;
  for (size_t column_itr = 0; column_itr < output_tile_column_count;
       column_itr++)
    position_lists.push_back(std::vector<oid_t>());

  LOG_INFO("left col count: %lu, right col count: %lu", left_tile_column_count, right_tile_column_count);
  LOG_INFO("left col count: %lu, right col count: %lu", left_tile.get()->GetColumnCount(), right_tile.get()->GetColumnCount());
  LOG_INFO("left row count: %lu, right row count: %lu", left_tile_row_count, right_tile_row_count);

  // Go over every pair of tuples in left and right logical tiles
  for (size_t left_tile_row_itr = 0; left_tile_row_itr < left_tile_row_count;
       left_tile_row_itr++) {
    for (size_t right_tile_row_itr = 0;
         right_tile_row_itr < right_tile_row_count; right_tile_row_itr++) {
      // TODO: OPTIMIZATION : Can split the control flow into two paths -
      // one for cartesian product and one for join
      // Then, we can skip this branch atleast for the cartesian product path.

      // Join predicate exists
      if (predicate_ != nullptr) {
        expression::ContainerTuple<executor::LogicalTile> left_tuple(
            left_tile.get(), left_tile_row_itr);
        expression::ContainerTuple<executor::LogicalTile> right_tuple(
            right_tile.get(), right_tile_row_itr);

        // Join predicate is false. Skip pair and continue.
        if (predicate_->Evaluate(&left_tuple, &right_tuple, executor_context_)
                .IsFalse()) {
          continue;
        }
      }

      // Insert a tuple into the output logical tile
      // First, copy the elements in left logical tile's tuple
           for (size_t output_tile_column_itr = 0;
                output_tile_column_itr < left_tile_column_count;
                output_tile_column_itr++) {
             position_lists[output_tile_column_itr].push_back(
                 left_tile_position_lists[output_tile_column_itr]
                                         [left_tile_row_itr]);
           }

           // Then, copy the elements in left logical tile's tuple
           for (size_t output_tile_column_itr = 0;
                output_tile_column_itr < right_tile_column_count;
                output_tile_column_itr++) {
             position_lists[left_tile_column_count + output_tile_column_itr]
                 .push_back(right_tile_position_lists[output_tile_column_itr]
                                                     [right_tile_row_itr]);
           }

      // First, copy the elements in left logical tile's tuple
    }
  }

  for (auto col : position_lists) {
    LOG_INFO("col");
    for (auto elm : col) {
      (void)elm;  // silent compiler
      LOG_INFO("elm: %u", elm);
    }
  }

  // Check if we have any matching tuples.
  if (position_lists[0].size() > 0) {
    output_tile.get()->SetPositionListsAndVisibility(std::move(position_lists));
    SetOutput(output_tile.release());
    return true;
  }
  // Try again
  else {
    // If we are out of any more pairs of child tiles to examine,
    // then we will return false earlier in this function.
    // So, we don't have to return false here.
    DExecute();
  }

  return true;
}

std::vector<LogicalTile::ColumnInfo> NestedLoopJoinExecutor::BuildSchema(std::vector<LogicalTile::ColumnInfo> left,
                                                  std::vector<LogicalTile::ColumnInfo> right) {

  assert(proj_info_->GetTargetList().size() == 0);
  auto &direct_map_list = proj_info_->GetDirectMapList();
  std::vector<LogicalTile::ColumnInfo> schema(direct_map_list.size());
  for (auto &entry : direct_map_list) {
    if (entry.second.first == 0) {
      assert(entry.second.second < left.size());
      schema[entry.first] = left[entry.second.second];
    } else {
      assert(entry.second.second < right.size());
      schema[entry.first] = right[entry.second.second];
    }
  }
  return schema;
}

}  // namespace executor
}  // namespace peloton
<|endoftext|>


<commit_before>#include <iostream>
#include <vector>
using namespace std;

//
// The goal of the program is to verify Burnside's lemma.
// Burnside's lemma is useful for counting things with symmetry.
//
// This program uses the lemma to compute the number of necklaces
// that can be formed by n = 5 beads with c = 10 colors such that
// all reflections and rotations of the same coloring is counted
// only once.
//
// Here is the key ingredient in the proof for the Burnside's lemma
//
// y in Orbit of x means y = g x, define a map from X to 2^G as follow:
//
// Map an element y to the set of group element g such that y = g x
// y = h x => y = g g^{-1} h x = g (g^{-1} h) x,
// Notice g^{-1} h x = g^{-1} g x = x, therefore for every group element
// y maps to, it is a coset element.
// On the other hand, every coset element is valid to be mapped to by y,
// Therefore we can map injectively an element in the orbit to a coset
// Therefore, the size of the orbit is the number of cosets = |G|/|Gx|
//
// Last but not least, if for each element, we add up the size its stablizer group,
// we get this:
//
//   sum for each x, sum |Gx|
// = for each orbit, for each orbit element, sum |Gx|
// = for each orbit, sum |G|/|Gx| * |Gx|
// = for each orbit, sum |G|
// = number of orbit * |G|
//
// So this is the Burnside's lemma, you can calculate the number of orbits
// by summing the size of all the stablizer group and then divide it by the
// size of the group.
//
// Note that when we compute sum for each x, sum |Gx|, it is equivalent to
// flip to loop and ask, for each permutation, sum the number of configuration it fixes.
//
// This is where the Polya enumeration formula comes in. After we factor the
// permutation into disjoint cycles, we figure that in order for a configuration is to be fixed
// It must have the same color for all nodes within a cycle, therefore,
// for each cycle, we can make c choices for the color, and therefore we can count the number
// of configuration get fixed by a permutation without enumerating the configurations at all.
//

int main(int argc, char** argv)
{
	vector<vector<int>> group_elements;
	int n = 5;
	int c = 10; // Polya's enumeration work much better when c is large - enumerating the configuration space is expensive
	for (int offset = 0; offset < n; offset++)
	{
		vector<int> forward;
		for (int i = 0; i < n; i++)
		{
			forward.push_back((i + offset) % n);
		}
		group_elements.push_back(forward);
		vector<int> backward;
		for (int i = 0; i < n; i++)
		{
			backward.push_back(((n - i) + offset) % n);
		}
		group_elements.push_back(backward);
	}

	bool burnside = true;
	bool polya = true;

	cout << "Begin Group" << endl;
	for (size_t i = 0; i < group_elements.size(); i++)
	{
		for (size_t j = 0; j < group_elements[i].size(); j++)
		{
			cout << group_elements[i][j] << " ";
		}
		cout << endl;
	}
	cout << "End Group" << endl;
	if (burnside)
	{
		cout << "Starting brute force verification of Burnside's lemma" << endl;
		// This version of the code directly exercise the Burnside's lemma as is:
		// This is inefficient because we have to go through all configurations
		vector<int> config;
		vector<int> mirror;
		config.resize(n);
		mirror.resize(n);

		int all_stablizer_count = 0;
		for (size_t k = 0; k < group_elements.size(); k++)
		{
			for (size_t j = 0; j < group_elements[k].size(); j++)
			{
				cout << group_elements[k][j] << " ";
			}
			int fixed_count = 0;
			int seq = 0;

			// A simple odometer to loop through all the config
			while (true)
			{
				int cur = seq;
				bool last = true;
				for (int i = 0; i < n; i++)
				{
					config[i] = cur % c;
					cur = cur / c;
					last = last & (config[i] == c - 1);
				}

				// Here we have got a configuration - check if it is fixed by the current permutation

				bool is_fixed = true;
				for (int l = 0; is_fixed && l < n; l++)
				{
					is_fixed = is_fixed && (config[group_elements[k][l]] == config[l]);
				}

				if (is_fixed)
				{
					fixed_count++;
				}

				if (last)
				{
					break;
				}
				seq++;
			}
			cout << " fixes " << fixed_count << " configurations" << endl;
			all_stablizer_count += fixed_count;
		}
		cout << all_stablizer_count << " " << group_elements.size() << endl;
	}

	if (polya)
	{
		cout << "Starting polya's enumeration formula" << endl;
		int all_stablizer_count = 0;
		for (size_t i = 0; i < group_elements.size(); i++)
		{
			vector<bool> used;
			used.resize(group_elements[i].size());
			for (size_t j = 0; j < used.size(); j++)
			{
				used[j] = false;
			}
			for (size_t j = 0; j < group_elements[i].size(); j++)
			{
				cout << group_elements[i][j] << " ";
			}
			int fixed_count = 1;
			for (size_t j = 0; j < group_elements[i].size(); j++)
			{
				size_t k = j;
				int element_in_cycle = 0;
				cout << "(";
				while (!used[k])
				{
					element_in_cycle++;
					cout << k << " ";
					used[k] = true;
					k = group_elements[i][k];
				}
				cout << ") [" << element_in_cycle << "] ";
				if (element_in_cycle != 0)
				{
					fixed_count *= c;
				}
			}
			cout << " fixes " << fixed_count << " configurations" << endl;
			all_stablizer_count += fixed_count;
		}
		cout << all_stablizer_count << " " << group_elements.size() << endl;
	}
}<commit_msg>Tab to space<commit_after>#include <iostream>
#include <vector>
using namespace std;

//
// The goal of the program is to verify Burnside's lemma.
// Burnside's lemma is useful for counting things with symmetry.
//
// This program uses the lemma to compute the number of necklaces
// that can be formed by n = 5 beads with c = 10 colors such that
// all reflections and rotations of the same coloring is counted
// only once.
//
// Here is the key ingredient in the proof for the Burnside's lemma
//
// y in Orbit of x means y = g x, define a map from X to 2^G as follow:
//
// Map an element y to the set of group element g such that y = g x
// y = h x => y = g g^{-1} h x = g (g^{-1} h) x,
// Notice g^{-1} h x = g^{-1} g x = x, therefore for every group element
// y maps to, it is a coset element.
// On the other hand, every coset element is valid to be mapped to by y,
// Therefore we can map injectively an element in the orbit to a coset
// Therefore, the size of the orbit is the number of cosets = |G|/|Gx|
//
// Last but not least, if for each element, we add up the size its stablizer group,
// we get this:
//
//   sum for each x, sum |Gx|
// = for each orbit, for each orbit element, sum |Gx|
// = for each orbit, sum |G|/|Gx| * |Gx|
// = for each orbit, sum |G|
// = number of orbit * |G|
//
// So this is the Burnside's lemma, you can calculate the number of orbits
// by summing the size of all the stablizer group and then divide it by the
// size of the group.
//
// Note that when we compute sum for each x, sum |Gx|, it is equivalent to
// flip to loop and ask, for each permutation, sum the number of configuration it fixes.
//
// This is where the Polya enumeration formula comes in. After we factor the
// permutation into disjoint cycles, we figure that in order for a configuration is to be fixed
// It must have the same color for all nodes within a cycle, therefore,
// for each cycle, we can make c choices for the color, and therefore we can count the number
// of configuration get fixed by a permutation without enumerating the configurations at all.
//

int main(int argc, char** argv)
{
    vector<vector<int>> group_elements;
    int n = 5;
    int c = 10; // Polya's enumeration work much better when c is large - enumerating the configuration space is expensive
    for (int offset = 0; offset < n; offset++)
    {
        vector<int> forward;
        for (int i = 0; i < n; i++)
        {
            forward.push_back((i + offset) % n);
        }
        group_elements.push_back(forward);
        vector<int> backward;
        for (int i = 0; i < n; i++)
        {
            backward.push_back(((n - i) + offset) % n);
        }
        group_elements.push_back(backward);
    }

    bool burnside = true;
    bool polya = true;

    cout << "Begin Group" << endl;
    for (size_t i = 0; i < group_elements.size(); i++)
    {
        for (size_t j = 0; j < group_elements[i].size(); j++)
        {
            cout << group_elements[i][j] << " ";
        }
        cout << endl;
    }
    cout << "End Group" << endl;
    if (burnside)
    {
        cout << "Starting brute force verification of Burnside's lemma" << endl;
        // This version of the code directly exercise the Burnside's lemma as is:
        // This is inefficient because we have to go through all configurations
        vector<int> config;
        vector<int> mirror;
        config.resize(n);
        mirror.resize(n);

        int all_stablizer_count = 0;
        for (size_t k = 0; k < group_elements.size(); k++)
        {
            for (size_t j = 0; j < group_elements[k].size(); j++)
            {
                cout << group_elements[k][j] << " ";
            }
            int fixed_count = 0;
            int seq = 0;

            // A simple odometer to loop through all the config
            while (true)
            {
                int cur = seq;
                bool last = true;
                for (int i = 0; i < n; i++)
                {
                    config[i] = cur % c;
                    cur = cur / c;
                    last = last & (config[i] == c - 1);
                }

                // Here we have got a configuration - check if it is fixed by the current permutation

                bool is_fixed = true;
                for (int l = 0; is_fixed && l < n; l++)
                {
                    is_fixed = is_fixed && (config[group_elements[k][l]] == config[l]);
                }

                if (is_fixed)
                {
                    fixed_count++;
                }

                if (last)
                {
                    break;
                }
                seq++;
            }
            cout << " fixes " << fixed_count << " configurations" << endl;
            all_stablizer_count += fixed_count;
        }
        cout << all_stablizer_count << " " << group_elements.size() << endl;
    }

    if (polya)
    {
        cout << "Starting polya's enumeration formula" << endl;
        int all_stablizer_count = 0;
        for (size_t i = 0; i < group_elements.size(); i++)
        {
            vector<bool> used;
            used.resize(group_elements[i].size());
            for (size_t j = 0; j < used.size(); j++)
            {
                used[j] = false;
            }
            for (size_t j = 0; j < group_elements[i].size(); j++)
            {
                cout << group_elements[i][j] << " ";
            }
            int fixed_count = 1;
            for (size_t j = 0; j < group_elements[i].size(); j++)
            {
                size_t k = j;
                int element_in_cycle = 0;
                cout << "(";
                while (!used[k])
                {
                    element_in_cycle++;
                    cout << k << " ";
                    used[k] = true;
                    k = group_elements[i][k];
                }
                cout << ") [" << element_in_cycle << "] ";
                if (element_in_cycle != 0)
                {
                    fixed_count *= c;
                }
            }
            cout << " fixes " << fixed_count << " configurations" << endl;
            all_stablizer_count += fixed_count;
        }
        cout << all_stablizer_count << " " << group_elements.size() << endl;
    }
}<|endoftext|>


<commit_before>// Time:  O(max(r, c) * wlogw)
// Space: O(w^2)

class Solution {
public:
    int shortestDistance(vector<vector<int>>& maze, vector<int>& start, vector<int>& destination) {
        static const vector<vector<int>> dirs = {{-1, 0}, {0, 1}, {0, -1}, {1, 0}};
        priority_queue<node, vector<node>, greater<node>> heap;
        unordered_set<int> visited;
        heap.emplace(0, start);

        while (!heap.empty()) {
            int dist = 0;
            vector<int> node;
            tie(dist, node) = heap.top();
            heap.pop();
            if (visited.count(hash(maze, node))) {
                continue;
            }
            if (node[0] == destination[0] &&
                node[1] == destination[1]) {
                return dist;
            }

            visited.emplace(hash(maze, node));
            for (const auto& dir : dirs) {
                int neighbor_dist = 0;
                vector<int> neighbor;
                tie(neighbor_dist, neighbor) = findNeighbor(maze, node, dir);
                heap.emplace(dist + neighbor_dist, neighbor);
            }
        }

        return -1;
    }

private:
    using node = pair<int, vector<int>>;

    node findNeighbor(const vector<vector<int>>& maze,
                      const vector<int>& node, const vector<int>& dir) {
        vector<int> cur_node = node;
        int dist = 0;

        while (0 <= cur_node[0] + dir[0] && cur_node[0] + dir[0] < maze.size() &&
               0 <= cur_node[1] + dir[1] && cur_node[1] + dir[1] < maze[0].size() &&
               !maze[cur_node[0] + dir[0]][cur_node[1] + dir[1]]) {
            cur_node[0] += dir[0];
            cur_node[1] += dir[1];
            ++dist;
        }
        return {dist, cur_node};
    }

    int hash(const vector<vector<int>>& maze, const vector<int>& node) {
        return node[0] * maze[0].size() + node[1];
    }
};
<commit_msg>Update the-maze-ii.cpp<commit_after>// Time:  O(max(r, c) * wlogw)
// Space: O(w)

class Solution {
public:
    int shortestDistance(vector<vector<int>>& maze, vector<int>& start, vector<int>& destination) {
        static const vector<vector<int>> dirs = {{-1, 0}, {0, 1}, {0, -1}, {1, 0}};
        priority_queue<node, vector<node>, greater<node>> heap;
        unordered_set<int> visited;
        heap.emplace(0, start);

        while (!heap.empty()) {
            int dist = 0;
            vector<int> node;
            tie(dist, node) = heap.top();
            heap.pop();
            if (visited.count(hash(maze, node))) {
                continue;
            }
            if (node[0] == destination[0] &&
                node[1] == destination[1]) {
                return dist;
            }

            visited.emplace(hash(maze, node));
            for (const auto& dir : dirs) {
                int neighbor_dist = 0;
                vector<int> neighbor;
                tie(neighbor_dist, neighbor) = findNeighbor(maze, node, dir);
                heap.emplace(dist + neighbor_dist, neighbor);
            }
        }

        return -1;
    }

private:
    using node = pair<int, vector<int>>;

    node findNeighbor(const vector<vector<int>>& maze,
                      const vector<int>& node, const vector<int>& dir) {
        vector<int> cur_node = node;
        int dist = 0;

        while (0 <= cur_node[0] + dir[0] && cur_node[0] + dir[0] < maze.size() &&
               0 <= cur_node[1] + dir[1] && cur_node[1] + dir[1] < maze[0].size() &&
               !maze[cur_node[0] + dir[0]][cur_node[1] + dir[1]]) {
            cur_node[0] += dir[0];
            cur_node[1] += dir[1];
            ++dist;
        }
        return {dist, cur_node};
    }

    int hash(const vector<vector<int>>& maze, const vector<int>& node) {
        return node[0] * maze[0].size() + node[1];
    }
};
<|endoftext|>


<commit_before>// Time:  O(logn)
// Space: O(1)

class Solution {
public:
    /**
     * @param num an integer
     * @return true if num is an ugly number or false
     */
    bool isUgly(int num) {
        if (num == 0) {
            return false;
        }
        for (const auto& i : {2, 3, 5}) {
            while (num % i == 0) {
                num /= i;
            }
        }
        return num == 1;
    }
};
<commit_msg>Update ugly-number.cpp<commit_after>// Time:  O(logn) = O(1)
// Space: O(1)

class Solution {
public:
    /**
     * @param num an integer
     * @return true if num is an ugly number or false
     */
    bool isUgly(int num) {
        if (num == 0) {
            return false;
        }
        for (const auto& i : {2, 3, 5}) {
            while (num % i == 0) {
                num /= i;
            }
        }
        return num == 1;
    }
};
<|endoftext|>


<commit_before>#include "mat4.h"
#include <memory.h>
#include <string.h>

namespace fd {
namespace core {
namespace math {

void mat4::LoadRows(__m128* rows) const {
	rows[0] = _mm_set_ps(m[0 + 3 * 4], m[0 + 2 * 4], m[0 + 1 * 4], m[0 + 0 * 4]);
	rows[1] = _mm_set_ps(m[1 + 3 * 4], m[1 + 2 * 4], m[1 + 1 * 4], m[1 + 0 * 4]);
	rows[2] = _mm_set_ps(m[2 + 3 * 4], m[2 + 2 * 4], m[2 + 1 * 4], m[2 + 0 * 4]);
	rows[3] = _mm_set_ps(m[3 + 3 * 4], m[3 + 2 * 4], m[3 + 1 * 4], m[3 + 0 * 4]);
}

void mat4::LoadColumns(__m128* columns) const {
	columns[0] = _mm_loadu_ps(m);
	columns[1] = _mm_loadu_ps(m+4);
	columns[2] = _mm_loadu_ps(m+8);
	columns[3] = _mm_loadu_ps(m+12);
}

mat4::mat4() {
	memset(m, 0, sizeof(m));
}

mat4::mat4(float32 diagonal) : mat4() {
	m[0 + 0 * 4] = diagonal;
	m[1 + 1 * 4] = diagonal;
	m[2 + 2 * 4] = diagonal;
	m[3 + 3 * 4] = diagonal;
}

mat4 mat4::Scale(const vec3& v) {
	mat4 m;

	m.m[0 + 0 * 4] = v.x;
	m.m[1 + 1 * 4] = v.y;
	m.m[2 + 2 * 4] = v.z;
	m.m[3 + 3 * 4] = 1;

	return m;
}

mat4 mat4::Translate(const vec3& v) {
	mat4 m(1);

	m.m[3 + 0 * 4] = v.x;
	m.m[3 + 1 * 4] = v.y;
	m.m[3 + 2 * 4] = v.z;

	return m;
}

mat4 mat4::Rotate(const vec3& v) {
	mat4 x(1), y(1), z(1);

	float32 xcos = cosf((float32)FD_TO_RADIANS_F(v.x));
	float32 xsin = sinf((float32)FD_TO_RADIANS_F(v.x));
	float32 ycos = cosf((float32)FD_TO_RADIANS_F(v.y));
	float32 ysin = sinf((float32)FD_TO_RADIANS_F(v.y));
	float32 zcos = cosf((float32)FD_TO_RADIANS_F(v.z));
	float32 zsin = sinf((float32)FD_TO_RADIANS_F(v.z));

	x.m[1 + 1 * 4] = xcos; x.m[1 + 2 * 4] = -xsin;
	x.m[2 + 1 * 4] = xsin; x.m[2 + 2 * 4] = xcos;

	y.m[0 + 0 * 4] = ycos; y.m[0 + 2 * 4] = -ysin;
	y.m[2 + 0 * 4] = ysin; y.m[2 + 2 * 4] = ycos;

	z.m[0 + 0 * 4] = zcos; z.m[0 + 1 * 4] = -zsin;
	z.m[1 + 0 * 4] = zsin; z.m[1 + 1 * 4] = zcos;

	return x * y * z;
}

mat4 mat4::Perspective(float32 aspect, float32 fov, float32 zNear, float32 zFar) {
	mat4 m(1);

	m.m[0 + 0 * 4] = 1.0f / (aspect * (tanh(fov * 0.5f)));
	m.m[1 + 1 * 4] = 1.0f / (tanh(fov * 0.5f));
	m.m[2 + 2 * 4] = zFar / (zFar - zNear);
	m.m[3 + 2 * 4] = 1;
	m.m[2 + 3 * 4] = -zNear * (zFar / (zFar - zNear));
	m.m[3 + 3 * 4] = 0;

	return m;
}

mat4 mat4::operator*(const mat4& r) const {
	mat4 tmp;

	__m128 row[4];
	__m128 col[4];

	r.LoadColumns(col);
	LoadRows(row);

	__m128 res;

	for (uint_t y = 0; y < 4; y++) {
		for (uint_t x = 0; x < 4; x++) {
			res = _mm_mul_ps(row[x], col[y]);

			tmp.m[x + y * 4] = M128(res, 0)+ M128(res, 1) + M128(res, 2) + M128(res, 3);
		}
	}

	return tmp;
}

vec3 mat4::operator*(const vec3& v) const {
	__m128 row[4];
	__m128 col;

	LoadRows(row);

	col = _mm_set_ps(0, v.z, v.y, v.x);

	__m128 res = _mm_mul_ps(row[0], col);

	for (uint_t i = 1; i < 4; i++)
		res = _mm_fmadd_ps(row[i], col, res);

	return vec3(M128(res, 0), M128(res, 1), M128(res, 2));
}

vec4 mat4::operator*(const vec4& v) const {
	__m128 row[4];
	__m128 col;

	LoadRows(row);

	col = _mm_set_ps(v.w, v.z, v.y, v.x);

	__m128 res = _mm_mul_ps(row[0], col);

	for (uint_t i = 1; i < 4; i++)
		res = _mm_fmadd_ps(row[i], col, res);

	return vec4(M128(res, 0), M128(res, 1), M128(res, 2), M128(res, 3));
}

mat4 mat4::Transpose(mat4 m) {
	float tmp[16];
	memcpy(tmp, m.m, sizeof(m));

	for (uint32 y = 0; y < 4; y++) {
		for (uint32 x = 0; x < 4; x++) {
			m.m[y + x * 4] = tmp[x + y * 4];
		}
	}

	return m;
}

} } }<commit_msg>Fixed truncation warning<commit_after>#include "mat4.h"
#include <memory.h>
#include <string.h>

namespace fd {
namespace core {
namespace math {

void mat4::LoadRows(__m128* rows) const {
	rows[0] = _mm_set_ps(m[0 + 3 * 4], m[0 + 2 * 4], m[0 + 1 * 4], m[0 + 0 * 4]);
	rows[1] = _mm_set_ps(m[1 + 3 * 4], m[1 + 2 * 4], m[1 + 1 * 4], m[1 + 0 * 4]);
	rows[2] = _mm_set_ps(m[2 + 3 * 4], m[2 + 2 * 4], m[2 + 1 * 4], m[2 + 0 * 4]);
	rows[3] = _mm_set_ps(m[3 + 3 * 4], m[3 + 2 * 4], m[3 + 1 * 4], m[3 + 0 * 4]);
}

void mat4::LoadColumns(__m128* columns) const {
	columns[0] = _mm_loadu_ps(m);
	columns[1] = _mm_loadu_ps(m+4);
	columns[2] = _mm_loadu_ps(m+8);
	columns[3] = _mm_loadu_ps(m+12);
}

mat4::mat4() {
	memset(m, 0, sizeof(m));
}

mat4::mat4(float32 diagonal) : mat4() {
	m[0 + 0 * 4] = diagonal;
	m[1 + 1 * 4] = diagonal;
	m[2 + 2 * 4] = diagonal;
	m[3 + 3 * 4] = diagonal;
}

mat4 mat4::Scale(const vec3& v) {
	mat4 m;

	m.m[0 + 0 * 4] = v.x;
	m.m[1 + 1 * 4] = v.y;
	m.m[2 + 2 * 4] = v.z;
	m.m[3 + 3 * 4] = 1;

	return m;
}

mat4 mat4::Translate(const vec3& v) {
	mat4 m(1);

	m.m[3 + 0 * 4] = v.x;
	m.m[3 + 1 * 4] = v.y;
	m.m[3 + 2 * 4] = v.z;

	return m;
}

mat4 mat4::Rotate(const vec3& v) {
	mat4 x(1), y(1), z(1);

	float32 xcos = cosf((float32)FD_TO_RADIANS_F(v.x));
	float32 xsin = sinf((float32)FD_TO_RADIANS_F(v.x));
	float32 ycos = cosf((float32)FD_TO_RADIANS_F(v.y));
	float32 ysin = sinf((float32)FD_TO_RADIANS_F(v.y));
	float32 zcos = cosf((float32)FD_TO_RADIANS_F(v.z));
	float32 zsin = sinf((float32)FD_TO_RADIANS_F(v.z));

	x.m[1 + 1 * 4] = xcos; x.m[1 + 2 * 4] = -xsin;
	x.m[2 + 1 * 4] = xsin; x.m[2 + 2 * 4] = xcos;

	y.m[0 + 0 * 4] = ycos; y.m[0 + 2 * 4] = -ysin;
	y.m[2 + 0 * 4] = ysin; y.m[2 + 2 * 4] = ycos;

	z.m[0 + 0 * 4] = zcos; z.m[0 + 1 * 4] = -zsin;
	z.m[1 + 0 * 4] = zsin; z.m[1 + 1 * 4] = zcos;

	return x * y * z;
}

mat4 mat4::Perspective(float32 aspect, float32 fov, float32 zNear, float32 zFar) {
	mat4 m(1);

	m.m[0 + 0 * 4] = 1.0f / (aspect * ((float32)tanh(fov * 0.5f)));
	m.m[1 + 1 * 4] = 1.0f / ((float32)tanh(fov * 0.5f));
	m.m[2 + 2 * 4] = zFar / (zFar - zNear);
	m.m[3 + 2 * 4] = 1;
	m.m[2 + 3 * 4] = -zNear * (zFar / (zFar - zNear));
	m.m[3 + 3 * 4] = 0;

	return m;
}

mat4 mat4::operator*(const mat4& r) const {
	mat4 tmp;

	__m128 row[4];
	__m128 col[4];

	r.LoadColumns(col);
	LoadRows(row);

	__m128 res;

	for (uint_t y = 0; y < 4; y++) {
		for (uint_t x = 0; x < 4; x++) {
			res = _mm_mul_ps(row[x], col[y]);

			tmp.m[x + y * 4] = M128(res, 0)+ M128(res, 1) + M128(res, 2) + M128(res, 3);
		}
	}

	return tmp;
}

vec3 mat4::operator*(const vec3& v) const {
	__m128 row[4];
	__m128 col;

	LoadRows(row);

	col = _mm_set_ps(0, v.z, v.y, v.x);

	__m128 res = _mm_mul_ps(row[0], col);

	for (uint_t i = 1; i < 4; i++)
		res = _mm_fmadd_ps(row[i], col, res);

	return vec3(M128(res, 0), M128(res, 1), M128(res, 2));
}

vec4 mat4::operator*(const vec4& v) const {
	__m128 row[4];
	__m128 col;

	LoadRows(row);

	col = _mm_set_ps(v.w, v.z, v.y, v.x);

	__m128 res = _mm_mul_ps(row[0], col);

	for (uint_t i = 1; i < 4; i++)
		res = _mm_fmadd_ps(row[i], col, res);

	return vec4(M128(res, 0), M128(res, 1), M128(res, 2), M128(res, 3));
}

mat4 mat4::Transpose(mat4 m) {
	float tmp[16];
	memcpy(tmp, m.m, sizeof(m));

	for (uint32 y = 0; y < 4; y++) {
		for (uint32 x = 0; x < 4; x++) {
			m.m[y + x * 4] = tmp[x + y * 4];
		}
	}

	return m;
}

} } }<|endoftext|>


<commit_before><commit_msg>coverity#708715 unused member variable<commit_after><|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: ActionMapTypesOOo.hxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 15:35:10 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _XMLOFF_ACTIONMAPTYPESOOO_HXX
#define _XMLOFF_ACTIONMAPTYPESOOO_HXX

enum ActionMapTypesOOo
{
    PROP_OOO_GRAPHIC_ATTR_ACTIONS,
    PROP_OOO_GRAPHIC_ELEM_ACTIONS,
    PROP_OOO_DRAWING_PAGE_ATTR_ACTIONS,
    PROP_OOO_PAGE_LAYOUT_ATTR_ACTIONS,
    PROP_OOO_HEADER_FOOTER_ATTR_ACTIONS,
    PROP_OOO_TEXT_ATTR_ACTIONS,
    PROP_OOO_TEXT_ELEM_ACTIONS,
    PROP_OOO_PARAGRAPH_ATTR_ACTIONS,
    PROP_OOO_PARAGRAPH_ELEM_ACTIONS,
    PROP_OOO_SECTION_ATTR_ACTIONS,
    PROP_OOO_TABLE_ATTR_ACTIONS,
    PROP_OOO_TABLE_COLUMN_ATTR_ACTIONS,
    PROP_OOO_TABLE_ROW_ATTR_ACTIONS,
    PROP_OOO_TABLE_CELL_ATTR_ACTIONS,
    PROP_OOO_TABLE_CELL_ELEM_ACTIONS,
    PROP_OOO_LIST_LEVEL_ATTR_ACTIONS,
    PROP_OOO_CHART_ATTR_ACTIONS,
    PROP_OOO_CHART_ELEM_ACTIONS,
    MAX_OOO_PROP_ACTIONS,
    OOO_STYLE_ACTIONS = MAX_OOO_PROP_ACTIONS,
    OOO_FONT_DECL_ACTIONS,
    OOO_SHAPE_ACTIONS,
    OOO_CONNECTOR_ACTIONS,
    OOO_INDEX_ENTRY_TAB_STOP_ACTIONS,
    OOO_TAB_STOP_ACTIONS,
    OOO_LINENUMBERING_ACTIONS,
    OOO_FOOTNOTE_SEP_ACTIONS,
    OOO_DROP_CAP_ACTIONS,
    OOO_COLUMNS_ACTIONS,
    OOO_TEXT_VALUE_TYPE_ACTIONS,
    OOO_TABLE_VALUE_TYPE_ACTIONS,
    OOO_PARA_ACTIONS,
    OOO_STYLE_REF_ACTIONS,
    OOO_MASTER_PAGE_ACTIONS,
    OOO_ANNOTATION_ACTIONS,
    OOO_CHANGE_INFO_ACTIONS,
    OOO_FRAME_ELEM_ACTIONS,
    OOO_FRAME_ATTR_ACTIONS,
    OOO_BACKGROUND_IMAGE_ACTIONS,
    OOO_DDE_CONNECTION_DECL_ACTIONS,
    OOO_EVENT_ACTIONS,
    OOO_FORM_CONTROL_ACTIONS,
    OOO_FORM_COLUMN_ACTIONS,
    OOO_FORM_PROP_ACTIONS,
    OOO_XLINK_ACTIONS,
    OOO_CONFIG_ITEM_SET_ACTIONS,
    OOO_FORMULA_ACTIONS,
    OOO_CHART_ACTIONS,
    OOO_ERROR_MACRO_ACTIONS,
    OOO_DDE_CONV_MODE_ACTIONS,
    OOO_ALPHABETICAL_INDEX_MARK_ACTIONS,
    OOO_DATAPILOT_MEMBER_ACTIONS,
    OOO_DATAPILOT_LEVEL_ACTIONS,
    OOO_SOURCE_SERVICE_ACTIONS,
    OOO_DRAW_AREA_POLYGON_ACTIONS,
    OOO_SCRIPT_ACTIONS,
    MAX_OOO_ACTIONS
};

#endif  //  _XMLOFF_ACTIONMAPTYPESOOO_HXX
<commit_msg>INTEGRATION: CWS changefileheader (1.7.450); FILE MERGED 2008/03/31 16:28:48 rt 1.7.450.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: ActionMapTypesOOo.hxx,v $
 * $Revision: 1.8 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef _XMLOFF_ACTIONMAPTYPESOOO_HXX
#define _XMLOFF_ACTIONMAPTYPESOOO_HXX

enum ActionMapTypesOOo
{
    PROP_OOO_GRAPHIC_ATTR_ACTIONS,
    PROP_OOO_GRAPHIC_ELEM_ACTIONS,
    PROP_OOO_DRAWING_PAGE_ATTR_ACTIONS,
    PROP_OOO_PAGE_LAYOUT_ATTR_ACTIONS,
    PROP_OOO_HEADER_FOOTER_ATTR_ACTIONS,
    PROP_OOO_TEXT_ATTR_ACTIONS,
    PROP_OOO_TEXT_ELEM_ACTIONS,
    PROP_OOO_PARAGRAPH_ATTR_ACTIONS,
    PROP_OOO_PARAGRAPH_ELEM_ACTIONS,
    PROP_OOO_SECTION_ATTR_ACTIONS,
    PROP_OOO_TABLE_ATTR_ACTIONS,
    PROP_OOO_TABLE_COLUMN_ATTR_ACTIONS,
    PROP_OOO_TABLE_ROW_ATTR_ACTIONS,
    PROP_OOO_TABLE_CELL_ATTR_ACTIONS,
    PROP_OOO_TABLE_CELL_ELEM_ACTIONS,
    PROP_OOO_LIST_LEVEL_ATTR_ACTIONS,
    PROP_OOO_CHART_ATTR_ACTIONS,
    PROP_OOO_CHART_ELEM_ACTIONS,
    MAX_OOO_PROP_ACTIONS,
    OOO_STYLE_ACTIONS = MAX_OOO_PROP_ACTIONS,
    OOO_FONT_DECL_ACTIONS,
    OOO_SHAPE_ACTIONS,
    OOO_CONNECTOR_ACTIONS,
    OOO_INDEX_ENTRY_TAB_STOP_ACTIONS,
    OOO_TAB_STOP_ACTIONS,
    OOO_LINENUMBERING_ACTIONS,
    OOO_FOOTNOTE_SEP_ACTIONS,
    OOO_DROP_CAP_ACTIONS,
    OOO_COLUMNS_ACTIONS,
    OOO_TEXT_VALUE_TYPE_ACTIONS,
    OOO_TABLE_VALUE_TYPE_ACTIONS,
    OOO_PARA_ACTIONS,
    OOO_STYLE_REF_ACTIONS,
    OOO_MASTER_PAGE_ACTIONS,
    OOO_ANNOTATION_ACTIONS,
    OOO_CHANGE_INFO_ACTIONS,
    OOO_FRAME_ELEM_ACTIONS,
    OOO_FRAME_ATTR_ACTIONS,
    OOO_BACKGROUND_IMAGE_ACTIONS,
    OOO_DDE_CONNECTION_DECL_ACTIONS,
    OOO_EVENT_ACTIONS,
    OOO_FORM_CONTROL_ACTIONS,
    OOO_FORM_COLUMN_ACTIONS,
    OOO_FORM_PROP_ACTIONS,
    OOO_XLINK_ACTIONS,
    OOO_CONFIG_ITEM_SET_ACTIONS,
    OOO_FORMULA_ACTIONS,
    OOO_CHART_ACTIONS,
    OOO_ERROR_MACRO_ACTIONS,
    OOO_DDE_CONV_MODE_ACTIONS,
    OOO_ALPHABETICAL_INDEX_MARK_ACTIONS,
    OOO_DATAPILOT_MEMBER_ACTIONS,
    OOO_DATAPILOT_LEVEL_ACTIONS,
    OOO_SOURCE_SERVICE_ACTIONS,
    OOO_DRAW_AREA_POLYGON_ACTIONS,
    OOO_SCRIPT_ACTIONS,
    MAX_OOO_ACTIONS
};

#endif  //  _XMLOFF_ACTIONMAPTYPESOOO_HXX
<|endoftext|>


<commit_before>/*
Copyright (c) 2012 Carsten Burstedde, Donna Calhoun
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include <fclaw2d_forestclaw.h>
#include <fclaw2d_clawpatch.hpp>
#include <fclaw2d_partition.h>

#include <sc_statistics.h>

#define FCLAW2D_STATS_SET(stats,ddata,NAME) do {                               \
    SC_CHECK_ABORT (!(ddata)->timers[FCLAW2D_TIMER_ ## NAME].running,          \
                    "Timer " #NAME " still running in amrreset");              \
    sc_stats_set1 ((stats) + FCLAW2D_TIMER_ ## NAME,                           \
                   (ddata)->timers[FCLAW2D_TIMER_ ## NAME].cumulative, #NAME); \
} while (0)

void amrreset(fclaw2d_domain_t **domain)
{
    fclaw2d_domain_data_t *ddata = get_domain_data (*domain);

    for(int i = 0; i < (*domain)->num_blocks; i++)
    {
        fclaw2d_block_t *block = (*domain)->blocks + i;
        fclaw2d_block_data_t *bd = (fclaw2d_block_data_t *) block->user;

        for(int j = 0; j < block->num_patches; j++)
        {
            fclaw2d_patch_t *patch = block->patches + j;
            fclaw2d_patch_delete_cp(patch);
            fclaw2d_patch_delete_data(patch);
#if 0
            fclaw2d_patch_data_t *pdata = (fclaw2d_patch_data_t *) patch->user;
            delete pdata->cp;
            pdata->cp = NULL;
            FCLAW2D_FREE (pdata);
            patch->user = NULL;
#endif
            ++ddata->count_delete_clawpatch;
        }

        FCLAW2D_FREE (bd);
        block->user = NULL;
    }

    fclaw2d_partition_delete(domain);

#if 0
    // Free old parallel ghost patch data structure, must exist by construction.
    delete_ghost_patches(*domain);
    fclaw2d_domain_exchange_t *e_old = fclaw2d_partition_get_exchange_data(*domain);
    fclaw2d_domain_free_after_exchange (*domain, e_old);
#endif

    /* Output memory discrepancy for the ClawPatch */
    if (ddata->count_set_clawpatch != ddata->count_delete_clawpatch) {
        printf ("[%d] This domain had Clawpatch set %d and deleted %d times\n",
                (*domain)->mpirank,
                ddata->count_set_clawpatch, ddata->count_delete_clawpatch);
    }

    /* Evaluate timers if this domain has not been superseded yet. */
    if (ddata->is_latest_domain) {
        sc_statinfo_t stats[FCLAW2D_TIMER_COUNT];

        fclaw2d_timer_stop (&ddata->timers[FCLAW2D_TIMER_WALLTIME]);

        FCLAW2D_STATS_SET (stats, ddata, INIT);
        FCLAW2D_STATS_SET (stats, ddata, REGRID);
        FCLAW2D_STATS_SET (stats, ddata, OUTPUT);
        FCLAW2D_STATS_SET (stats, ddata, CHECK);
        FCLAW2D_STATS_SET (stats, ddata, ADVANCE);
        FCLAW2D_STATS_SET (stats, ddata, EXCHANGE);
        FCLAW2D_STATS_SET (stats, ddata, BUILDPATCHES);
        FCLAW2D_STATS_SET (stats, ddata, WALLTIME);
        sc_stats_set1 (&stats[FCLAW2D_TIMER_UNACCOUNTED],
                       ddata->timers[FCLAW2D_TIMER_WALLTIME].cumulative -
                       (ddata->timers[FCLAW2D_TIMER_INIT].cumulative +
                        ddata->timers[FCLAW2D_TIMER_REGRID].cumulative +
                        ddata->timers[FCLAW2D_TIMER_OUTPUT].cumulative +
                        ddata->timers[FCLAW2D_TIMER_CHECK].cumulative +
                        ddata->timers[FCLAW2D_TIMER_ADVANCE].cumulative +
                        ddata->timers[FCLAW2D_TIMER_EXCHANGE].cumulative),
                       "UNACCOUNTED");
        sc_stats_compute ((*domain)->mpicomm, FCLAW2D_TIMER_COUNT, stats);
        sc_stats_print (sc_package_id, SC_LP_PRODUCTION, FCLAW2D_TIMER_COUNT,
                        stats, 1, 0);
        SC_GLOBAL_PRODUCTIONF ("Procs %d advance %d %g exchange %d %g "
                               "regrid %d %g\n", (*domain)->mpisize,
                               ddata->count_amr_advance,
                               stats[FCLAW2D_TIMER_ADVANCE].average,
                               ddata->count_ghost_exchange,
                               stats[FCLAW2D_TIMER_EXCHANGE].average,
                               ddata->count_amr_regrid,
                               stats[FCLAW2D_TIMER_REGRID].average);
        SC_GLOBAL_PRODUCTIONF ("Max/P %d advance %d %g exchange %d %g "
                               "regrid %d %g\n", (*domain)->mpisize,
                               ddata->count_amr_advance,
                               stats[FCLAW2D_TIMER_ADVANCE].max,
                               ddata->count_ghost_exchange,
                               stats[FCLAW2D_TIMER_EXCHANGE].max,
                               ddata->count_amr_regrid,
                               stats[FCLAW2D_TIMER_REGRID].max);
    }

    delete_domain_data(*domain);  // Delete allocated pointers to set of functions.

    fclaw2d_domain_destroy(*domain);
    *domain = NULL;
}
<commit_msg>Lowered log level for timing stats output at end of run<commit_after>/*
Copyright (c) 2012 Carsten Burstedde, Donna Calhoun
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include <fclaw2d_forestclaw.h>
#include <fclaw2d_clawpatch.hpp>
#include <fclaw2d_partition.h>

#include <sc_statistics.h>

#define FCLAW2D_STATS_SET(stats,ddata,NAME) do {                               \
    SC_CHECK_ABORT (!(ddata)->timers[FCLAW2D_TIMER_ ## NAME].running,          \
                    "Timer " #NAME " still running in amrreset");              \
    sc_stats_set1 ((stats) + FCLAW2D_TIMER_ ## NAME,                           \
                   (ddata)->timers[FCLAW2D_TIMER_ ## NAME].cumulative, #NAME); \
} while (0)

void amrreset(fclaw2d_domain_t **domain)
{
    fclaw2d_domain_data_t *ddata = get_domain_data (*domain);

    for(int i = 0; i < (*domain)->num_blocks; i++)
    {
        fclaw2d_block_t *block = (*domain)->blocks + i;
        fclaw2d_block_data_t *bd = (fclaw2d_block_data_t *) block->user;

        for(int j = 0; j < block->num_patches; j++)
        {
            fclaw2d_patch_t *patch = block->patches + j;
            fclaw2d_patch_delete_cp(patch);
            fclaw2d_patch_delete_data(patch);
#if 0
            fclaw2d_patch_data_t *pdata = (fclaw2d_patch_data_t *) patch->user;
            delete pdata->cp;
            pdata->cp = NULL;
            FCLAW2D_FREE (pdata);
            patch->user = NULL;
#endif
            ++ddata->count_delete_clawpatch;
        }

        FCLAW2D_FREE (bd);
        block->user = NULL;
    }

    fclaw2d_partition_delete(domain);

#if 0
    // Free old parallel ghost patch data structure, must exist by construction.
    delete_ghost_patches(*domain);
    fclaw2d_domain_exchange_t *e_old = fclaw2d_partition_get_exchange_data(*domain);
    fclaw2d_domain_free_after_exchange (*domain, e_old);
#endif

    /* Output memory discrepancy for the ClawPatch */
    if (ddata->count_set_clawpatch != ddata->count_delete_clawpatch) {
        printf ("[%d] This domain had Clawpatch set %d and deleted %d times\n",
                (*domain)->mpirank,
                ddata->count_set_clawpatch, ddata->count_delete_clawpatch);
    }

    /* Evaluate timers if this domain has not been superseded yet. */
    if (ddata->is_latest_domain) {
        sc_statinfo_t stats[FCLAW2D_TIMER_COUNT];

        fclaw2d_timer_stop (&ddata->timers[FCLAW2D_TIMER_WALLTIME]);

        FCLAW2D_STATS_SET (stats, ddata, INIT);
        FCLAW2D_STATS_SET (stats, ddata, REGRID);
        FCLAW2D_STATS_SET (stats, ddata, OUTPUT);
        FCLAW2D_STATS_SET (stats, ddata, CHECK);
        FCLAW2D_STATS_SET (stats, ddata, ADVANCE);
        FCLAW2D_STATS_SET (stats, ddata, EXCHANGE);
        FCLAW2D_STATS_SET (stats, ddata, BUILDPATCHES);
        FCLAW2D_STATS_SET (stats, ddata, WALLTIME);
        sc_stats_set1 (&stats[FCLAW2D_TIMER_UNACCOUNTED],
                       ddata->timers[FCLAW2D_TIMER_WALLTIME].cumulative -
                       (ddata->timers[FCLAW2D_TIMER_INIT].cumulative +
                        ddata->timers[FCLAW2D_TIMER_REGRID].cumulative +
                        ddata->timers[FCLAW2D_TIMER_OUTPUT].cumulative +
                        ddata->timers[FCLAW2D_TIMER_CHECK].cumulative +
                        ddata->timers[FCLAW2D_TIMER_ADVANCE].cumulative +
                        ddata->timers[FCLAW2D_TIMER_EXCHANGE].cumulative),
                       "UNACCOUNTED");
        sc_stats_compute ((*domain)->mpicomm, FCLAW2D_TIMER_COUNT, stats);
        sc_stats_print (sc_package_id, SC_LP_ESSENTIAL, FCLAW2D_TIMER_COUNT,
                        stats, 1, 0);
        SC_GLOBAL_ESSENTIALF ("Procs %d advance %d %g exchange %d %g "
                               "regrid %d %g\n", (*domain)->mpisize,
                               ddata->count_amr_advance,
                               stats[FCLAW2D_TIMER_ADVANCE].average,
                               ddata->count_ghost_exchange,
                               stats[FCLAW2D_TIMER_EXCHANGE].average,
                               ddata->count_amr_regrid,
                               stats[FCLAW2D_TIMER_REGRID].average);
        SC_GLOBAL_ESSENTIALF ("Max/P %d advance %d %g exchange %d %g "
                               "regrid %d %g\n", (*domain)->mpisize,
                               ddata->count_amr_advance,
                               stats[FCLAW2D_TIMER_ADVANCE].max,
                               ddata->count_ghost_exchange,
                               stats[FCLAW2D_TIMER_EXCHANGE].max,
                               ddata->count_amr_regrid,
                               stats[FCLAW2D_TIMER_REGRID].max);
    }

    delete_domain_data(*domain);  // Delete allocated pointers to set of functions.

    fclaw2d_domain_destroy(*domain);
    *domain = NULL;
}
<|endoftext|>