Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 115 additions & 0 deletions misc/scripts/exp_lut_generator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
#!/usr/bin/env python
import decimal
import os
from argparse import ArgumentParser
from math import e
from typing import List

BIT_COUNT = 64
MAX_VALUE = 2**BIT_COUNT

DEFAULT_DIVISOR_BASE = 2
DEFAULT_DIVISOR_POWER = 16
DEFAULT_EXP_BASE = e


def generate_exp_lut(divisor_base: int, divisor_power: int, exp_base: decimal.Decimal):
divisor: int = divisor_base**divisor_power

exp_lut: List[int] = []

for index in range(BIT_COUNT):
exponent: decimal.Decimal = (2**index) / divisor
value: int = int(decimal.Decimal(exp_base**exponent) * decimal.Decimal(divisor) + decimal.Decimal(0.5))
if value > MAX_VALUE:
break
exp_lut.append(value)

lut_identifier: str = (
f"LUT_{divisor_base}_{divisor_power}_EXP_{'e' if exp_base == e else ('%g' % exp_base).replace('.', 'p')}"
)
lut_size: int = len(exp_lut)

generated_options = ""
if (
DEFAULT_DIVISOR_BASE is not divisor_base
or DEFAULT_DIVISOR_POWER is not divisor_power
or DEFAULT_EXP_BASE is not exp_base
):
generated_options += " with `"

if DEFAULT_DIVISOR_BASE is not divisor_base:
generated_options += f"-b {divisor_base}"
if DEFAULT_DIVISOR_POWER is not divisor_power or DEFAULT_EXP_BASE is not exp_base:
generated_options += " "

if DEFAULT_DIVISOR_POWER is not divisor_power:
generated_options += f"-p {divisor_power}"
if DEFAULT_EXP_BASE is not exp_base:
generated_options += " "

if DEFAULT_EXP_BASE is not exp_base:
generated_options += f"-e {exp_base:g}"

generated_options += "`"

source: str = f"""// This file was generated using the `misc/scripts/exp_lut_generator.py` script{generated_options}.

#pragma once

#include <array>
#include <cstddef>
#include <cstdint>

static constexpr uint64_t {lut_identifier}_DIVISOR = {divisor};
static constexpr size_t {lut_identifier}_SIZE = {lut_size};

static constexpr std::array<int64_t, {lut_identifier}_SIZE> {lut_identifier} {{
"""

for value in exp_lut[:-1]:
source += f"\t{value},\n"

source += f"\t{exp_lut[-1]}\n"
source += "};\n"

fixed_point_lut_path: str = os.path.join(
os.path.dirname(__file__), f"../../src/openvic-simulation/types/fixed_point/FixedPoint{lut_identifier}.hpp"
)
with open(fixed_point_lut_path, "w", newline="\n") as file:
file.write(source)

print(f"`FixedPoint{lut_identifier}.hpp` generated successfully.")


if __name__ == "__main__":
parser = ArgumentParser(
prog="Fixed Point Exp LUT Generator", description="Fixed-Point Exponential Look-Up Table generator"
)
parser.add_argument(
"-b",
"--base",
type=int,
default=DEFAULT_DIVISOR_BASE,
choices=range(2, 65),
help="The base of the fixed point divisor",
)
parser.add_argument(
"-p",
"--power",
type=int,
default=DEFAULT_DIVISOR_POWER,
choices=range(1, 65),
help="The power of the fixed point divisor",
)
parser.add_argument(
"-e",
"--exp",
type=float,
default=DEFAULT_EXP_BASE,
help="The base of the exponential function the look-up table represents",
)
args = parser.parse_args()

generate_exp_lut(args.base, args.power, args.exp)
exit(0)
152 changes: 152 additions & 0 deletions misc/scripts/sin_lut_generator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
#!/usr/bin/env python
import decimal
import os
from argparse import ArgumentParser

DEFAULT_PRECISION = 16
DEFAULT_COUNT = 9


def decimal_pi() -> decimal.Decimal:
"""Compute Pi to the current precision.

>>> print(pdecimal_pii())
3.141592653589793238462643383

"""
decimal.getcontext().prec += 2 # extra digits for intermediate steps
three: decimal.Decimal = decimal.Decimal(3) # substitute "three=3.0" for regular floats
lasts: decimal.Decimal = decimal.Decimal(0)
t: decimal.Decimal = three
n, na, d, da = 1, 0, 0, 24
s: decimal.Decimal = three
while s != lasts:
lasts = s
n, na = n + na, na + 8
d, da = d + da, da + 32
t = (t * n) / d
s += decimal.Decimal(t)
decimal.getcontext().prec -= 2
return +s # unary plus applies the new precision


def decimal_sin(x: decimal.Decimal) -> decimal.Decimal:
"""Return the sine of x as measured in radians.

The Taylor series approximation works best for a small value of x.
For larger values, first compute x = x % (2 * pi).

>>> print(decimal_sin(Decimal('0.5')))
0.4794255386042030002732879352
>>> print(decimal_sin(0.5))
0.479425538604
>>> print(decimal_sin(0.5+0j))
(0.479425538604+0j)

"""
decimal.getcontext().prec += 2
i, fact, num, sign = 1, 1, x, 1
s: decimal.Decimal = x
lasts: decimal.Decimal = decimal.Decimal(0)
while s != lasts:
lasts = s
i += 2
fact *= i * (i - 1)
num *= x * x
sign *= -1
s += num / fact * sign
decimal.getcontext().prec -= 2
return +s


def generate_sin_lut(precision: int, count_log2: int):
one = 1 << precision
count = 1 << count_log2

SinLut = []

for i in range(count):
angle: decimal.Decimal = 2 * decimal_pi() * i / count

sin_value: decimal.Decimal = decimal_sin(angle) # sin(angle)
moved_sin: decimal.Decimal = sin_value * one
rounded_sin: int = (
int(moved_sin + decimal.Decimal(0.5)) if moved_sin > 0 else int(moved_sin - decimal.Decimal(0.5))
)
SinLut.append(rounded_sin)

SinLut.append(SinLut[0])

generated_options = ""
if DEFAULT_PRECISION is not precision or DEFAULT_COUNT is not count_log2:
generated_options += " with `"

if DEFAULT_PRECISION is not precision:
generated_options += f"-p {precision}"
if DEFAULT_COUNT is not count_log2:
generated_options += " "

if DEFAULT_COUNT is not count_log2:
generated_options += f"-c {count_log2}"

generated_options += "`"

source = f"""// This file was generated using the `misc/scripts/sin_lut_generator.py` script{generated_options}.

#pragma once

#include <array>
#include <cstdint>

static constexpr uint32_t SIN_LUT_PRECISION = {precision};
static constexpr uint32_t SIN_LUT_COUNT_LOG2 = {count_log2};
static constexpr int32_t SIN_LUT_SHIFT = SIN_LUT_PRECISION - SIN_LUT_COUNT_LOG2;

static constexpr std::array<int64_t, (1 << SIN_LUT_COUNT_LOG2) + 1> SIN_LUT = {{
"""

VALS_PER_LINE = 16

lines = [SinLut[i : i + VALS_PER_LINE] for i in range(0, len(SinLut), VALS_PER_LINE)]

for line in lines[:-1]:
source += f"\t{', '.join(str(value) for value in line)},\n"

source += f"\t{', '.join(str(value) for value in lines[-1])}\n"
source += "};\n"

fixed_point_sin_path: str = os.path.join(
os.path.dirname(__file__), "../../src/openvic-simulation/types/fixed_point/FixedPointLUT_sin.hpp"
)
with open(fixed_point_sin_path, "w", newline="\n") as file:
file.write(source)

print("`FixedPointLUT_sin.hpp` generated successfully.")


if __name__ == "__main__":
parser = ArgumentParser(prog="Fixed Point Sin LUT Generator", description="Fixed-Point Sin Look-Up Table generator")
parser.add_argument(
"-p",
"--precision",
type=int,
default=DEFAULT_PRECISION,
choices=range(1, 65),
help="The number of bits after the point (fractional bits)",
)
parser.add_argument(
"-c",
"--count",
type=int,
default=DEFAULT_COUNT,
choices=range(1, 65),
help="The base 2 log of the number of values in the look-up table (must be <= precision)",
)
args = parser.parse_args()

if args.precision < args.count:
print("ERROR: invalid count ", args.count, " - can't be greater than precision (", args.precision, ")")
exit(-1)
else:
generate_sin_lut(args.precision, args.count)
exit(0)
22 changes: 11 additions & 11 deletions src/headless/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,10 @@ static bool run_headless(Dataloader::path_vector_t const& roots, bool run_tests)

if (run_tests) {
Testing testing { game_manager.get_definition_manager() };
std::cout << std::endl << "Testing Loaded" << std::endl << std::endl;
std::cout << '\n' << "Testing Loaded" << '\n' << '\n';
testing.execute_all_scripts();
testing.report_results();
std::cout << "Testing Executed" << std::endl << std::endl;
std::cout << "Testing Executed" << '\n' << '\n';
}

Logger::info("===== Setting up instance... =====");
Expand Down Expand Up @@ -166,14 +166,14 @@ int main(int argc, char const* argv[]) {
if (!root.empty()) {
return true;
} else {
std::cerr << "Empty path after giving \"" << path << "\" to " << path_use
<< " command line argument \"" << command << "\"." << std::endl;
std::cerr << "Empty path after giving \"" << path << "\" to " << path_use << " command line argument \""
<< command << "\"." << '\n';
}
} else {
std::cerr << "Missing path after " << path_use << " command line argument \"" << command << "\"." << std::endl;
std::cerr << "Missing path after " << path_use << " command line argument \"" << command << "\"." << '\n';
}
} else {
std::cerr << "Duplicate " << path_use << " command line argument \"-b\"." << std::endl;
std::cerr << "Duplicate " << path_use << " command line argument \"-b\"." << '\n';
}
print_help(std::cerr, program_name);
return false;
Expand Down Expand Up @@ -201,7 +201,7 @@ int main(int argc, char const* argv[]) {
if (root.empty()) {
root = Dataloader::search_for_game_path();
if (root.empty()) {
std::cerr << "Search for base directory path failed!" << std::endl;
std::cerr << "Search for base directory path failed!" << '\n';
print_help(std::cerr, program_name);
return -1;
}
Expand All @@ -212,16 +212,16 @@ int main(int argc, char const* argv[]) {
roots.emplace_back(root / mod_directory / argv[argn++]);
}

std::cout << "!!! HEADLESS SIMULATION START !!!" << std::endl;
std::cout << "!!! HEADLESS SIMULATION START !!!" << '\n';

const bool ret = run_headless(roots, run_tests);

std::cout << "!!! HEADLESS SIMULATION END !!!" << std::endl;
std::cout << "!!! HEADLESS SIMULATION END !!!" << '\n';

std::cout << "\nLoad returned: " << (ret ? "SUCCESS" : "FAILURE") << std::endl;
std::cout << "\nLoad returned: " << (ret ? "SUCCESS" : "FAILURE") << '\n';

std::cout << "\nLogger Summary: Info = " << Logger::get_info_count() << ", Warning = " << Logger::get_warning_count()
<< ", Error = " << Logger::get_error_count() << std::endl;
<< ", Error = " << Logger::get_error_count() << '\n';

return ret ? 0 : -1;
}
2 changes: 1 addition & 1 deletion src/openvic-simulation/GameManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ bool GameManager::set_roots(Dataloader::path_vector_t const& roots) {
return true;
}

bool GameManager::load_definitions(Dataloader::localisation_callback_t localisation_callback) {
bool GameManager::load_definitions(Dataloader::localisation_callback_t const& localisation_callback) {
if (definitions_loaded) {
Logger::error("Cannot load definitions - already loaded!");
return false;
Expand Down
2 changes: 1 addition & 1 deletion src/openvic-simulation/GameManager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ namespace OpenVic {

bool set_roots(Dataloader::path_vector_t const& roots);

bool load_definitions(Dataloader::localisation_callback_t localisation_callback);
bool load_definitions(Dataloader::localisation_callback_t const& localisation_callback);

bool setup_instance(Bookmark const* bookmark);

Expand Down
10 changes: 5 additions & 5 deletions src/openvic-simulation/dataloader/Dataloader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ fs::path Dataloader::lookup_file(std::string_view path, bool print_error) const
std::error_code ec;
for (fs::directory_entry const& entry : fs::directory_iterator { composed.parent_path(), ec }) {
if (entry.is_regular_file()) {
const fs::path file = entry;
fs::path const& file = entry;
if (StringUtils::strings_equal_case_insensitive(file.filename().string(), filename)) {
return file;
}
Expand Down Expand Up @@ -108,7 +108,7 @@ Dataloader::path_vector_t Dataloader::_lookup_files_in_dir(
path_vector_t ret;
struct file_entry_t {
fs::path file;
fs::path const* root;
fs::path const* root = nullptr;
};
string_map_t<file_entry_t> found_files;
for (fs::path const& root : roots) {
Expand Down Expand Up @@ -1171,10 +1171,10 @@ static bool _load_localisation_file(Dataloader::localisation_callback_t callback
return ret;
}

bool Dataloader::load_localisation_files(localisation_callback_t callback, std::string_view localisation_dir) const {
return apply_to_files(
bool Dataloader::load_localisation_files(localisation_callback_t const& callback, std::string_view localisation_dir) const {
return apply_to_files( //
lookup_files_in_dir(localisation_dir, ".csv"),
[callback](fs::path path) -> bool {
[callback](fs::path const& path) -> bool {
return _load_localisation_file(callback, parse_csv(path).get_lines());
}
);
Expand Down
4 changes: 2 additions & 2 deletions src/openvic-simulation/dataloader/Dataloader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ namespace OpenVic {
/// a non-empty hint_path, performs empty path behavior.
/// @return fs::path The root directory of a valid Victoria 2 install, or an empty path.
///
static fs::path search_for_game_path(fs::path hint_path = {});
static fs::path search_for_game_path(fs::path const& hint_path = {});

/* In reverse-load order, so base defines first and final loaded mod last */
bool set_roots(path_vector_t const& new_roots);
Expand Down Expand Up @@ -137,7 +137,7 @@ namespace OpenVic {
/* Args: key, locale, localisation */
using localisation_callback_t = NodeTools::callback_t<std::string_view, locale_t, std::string_view>;
bool load_localisation_files(
localisation_callback_t callback, std::string_view localisation_dir = "localisation"
localisation_callback_t const& callback, std::string_view localisation_dir = "localisation"
) const;
};
}
Loading