int execute_app( const pal::string_t& impl_dll_dir, const corehost_init_t* init, const int argc, const pal::char_t* argv[]) { pal::dll_t corehost; corehost_main_fn host_main = nullptr; corehost_load_fn host_load = nullptr; corehost_unload_fn host_unload = nullptr; int code = load_host_library(impl_dll_dir, &corehost, &host_load, &host_main, &host_unload); if (code != StatusCode::Success) { trace::error(_X("Could not load host policy library [%s]"), impl_dll_dir.c_str()); return code; } if ((code = host_load(init)) == 0) { code = host_main(argc, argv); (void)host_unload(); } pal::unload_library(corehost); return code; }
int load_host_library( const pal::string_t& lib_dir, pal::dll_t* h_host, corehost_load_fn* load_fn, corehost_main_fn* main_fn, corehost_unload_fn* unload_fn) { pal::string_t host_path; if (!library_exists_in_dir(lib_dir, LIBHOSTPOLICY_NAME, &host_path)) { return StatusCode::CoreHostLibMissingFailure; } // Load library if (!pal::load_library(host_path.c_str(), h_host)) { trace::info(_X("Load library of %s failed"), host_path.c_str()); return StatusCode::CoreHostLibLoadFailure; } // Obtain entrypoint symbols *load_fn = (corehost_load_fn)pal::get_symbol(*h_host, "corehost_load"); *main_fn = (corehost_main_fn)pal::get_symbol(*h_host, "corehost_main"); *unload_fn = (corehost_unload_fn)pal::get_symbol(*h_host, "corehost_unload"); return (*main_fn) && (*load_fn) && (*unload_fn) ? StatusCode::Success : StatusCode::CoreHostEntryPointFailure; }
static int thermopro_tp11_sensor_callback(r_device *decoder, bitbuffer_t *bitbuffer) { int temp_raw, row; float temp_c; bitrow_t *bb = bitbuffer->bb; unsigned int device, value; data_t *data; // Compare first four bytes of rows that have 32 or 33 bits. row = bitbuffer_find_repeated_row(bitbuffer, 2, 32); if (row < 0) return 0; if (bitbuffer->bits_per_row[row] > 33) return 0; value = (bb[row][0] << 16) + (bb[row][1] << 8) + bb[row][2]; device = value >> 12; // Validate code for known devices. if ((device == 0xb34 || device == 0xdb4 ) && !valid(value, bb[row][3])) return 0; temp_raw = value & 0xfff; temp_c = (temp_raw - 200) / 10.; data = data_make( "model", "", DATA_STRING, _X("Thermopro-TP11","Thermopro TP11 Thermometer"), "id", "Id", DATA_INT, device, "temperature_C", "Temperature", DATA_FORMAT, "%.01f C", DATA_DOUBLE, temp_c, NULL); decoder_output_data(decoder, data); return 1; }
bool pal::getcwd(pal::string_t* recv) { recv->clear(); pal::char_t buf[MAX_PATH]; DWORD result = GetCurrentDirectoryW(MAX_PATH, buf); if (result < MAX_PATH) { recv->assign(buf); return true; } else if (result != 0) { std::vector<pal::char_t> str; str.resize(result); result = GetCurrentDirectoryW(str.size(), str.data()); assert(result <= str.size()); if (result != 0) { recv->assign(str.data()); return true; } } assert(result == 0); trace::error(_X("Failed to obtain working directory, HRESULT: 0x%X"), HRESULT_FROM_WIN32(GetLastError())); return false; }
bool coreclr_exists_in_dir(const pal::string_t& candidate) { pal::string_t test(candidate); append_path(&test, LIBCORECLR_NAME); trace::verbose(_X("Checking if CoreCLR path exists=[%s]"), test.c_str()); return pal::file_exists(test); }
static int silvercrest_callback(r_device *decoder, bitbuffer_t *bitbuffer) { uint8_t *b; // bits of a row uint8_t cmd; data_t *data; if (bitbuffer->bits_per_row[1] !=33) return 0; /* select second row, first might be bad */ b = bitbuffer->bb[1]; if ((b[0] == 0x7c) && (b[1] == 0x26)) { cmd = b[2] & 0xF; // Validate button if ((b[3]&0xF) != cmd_lu_tab[cmd]) return 0; data = data_make( "model", "", DATA_STRING, _X("Silvercrest-Remote","Silvercrest Remote Control"), "button", "", DATA_INT, cmd, NULL); decoder_output_data(decoder, data); return 1; } return 0; }
// [OBSOLETE] Replaced by hostfxr_resolve_sdk2 // // Determines the directory location of the SDK accounting for // global.json and multi-level lookup policy. // // Invoked via MSBuild SDK resolver to locate SDK props and targets // from an msbuild other than the one bundled by the CLI. // // Parameters: // exe_dir // The main directory where SDKs are located in sdk\[version] // sub-folders. Pass the directory of a dotnet executable to // mimic how that executable would search in its own directory. // It is also valid to pass nullptr or empty, in which case // multi-level lookup can still search other locations if // it has not been disabled by the user's environment. // // working_dir // The directory where the search for global.json (which can // control the resolved SDK version) starts and proceeds // upwards. // // buffer // The buffer where the resolved SDK path will be written. // // buffer_size // The size of the buffer argument in pal::char_t units. // // Return value: // <0 - Invalid argument // 0 - SDK could not be found. // >0 - The number of characters (including null terminator) // required to store the located SDK. // // If resolution succeeds and the positive return value is less than // or equal to buffer_size (i.e. the the buffer is large enough), // then the resolved SDK path is copied to the buffer and null // terminated. Otherwise, no data is written to the buffer. // // String encoding: // Windows - UTF-16 (pal::char_t is 2 byte wchar_t) // Unix - UTF-8 (pal::char_t is 1 byte char) // SHARED_API int32_t hostfxr_resolve_sdk( const pal::char_t* exe_dir, const pal::char_t* working_dir, pal::char_t buffer[], int32_t buffer_size) { trace::setup(); trace::info(_X("--- Invoked hostfxr [commit hash: %s] hostfxr_resolve_sdk"), _STRINGIFY(REPO_COMMIT_HASH)); if (buffer_size < 0 || (buffer_size > 0 && buffer == nullptr)) { trace::error(_X("hostfxr_resolve_sdk received an invalid argument.")); return -1; } if (exe_dir == nullptr) { exe_dir = _X(""); } if (working_dir == nullptr) { working_dir = _X(""); } pal::string_t cli_sdk; if (!sdk_resolver_t::resolve_sdk_dotnet_path(exe_dir, working_dir, &cli_sdk)) { // sdk_resolver_t::resolve_sdk_dotnet_path handles tracing for this error case. return 0; } if (cli_sdk.size() < buffer_size) { size_t length = cli_sdk.copy(buffer, buffer_size - 1); assert(length == cli_sdk.size()); assert(length < buffer_size); buffer[length] = 0; } else { trace::info(_X("hostfxr_resolve_sdk received a buffer that is too small to hold the located SDK path.")); } return cli_sdk.size() + 1; }
/** * Initialize resolved paths to known entries like coreclr, jit. */ void deps_resolver_t::init_known_entry_path(const deps_entry_t& entry, const pal::string_t& path) { if (entry.asset_type != deps_entry_t::asset_types::native) { return; } if (m_coreclr_path.empty() && ends_with(entry.relative_path, _X("/") + pal::string_t(LIBCORECLR_NAME), false)) { m_coreclr_path = path; return; } if (m_clrjit_path.empty() && ends_with(entry.relative_path, _X("/") + pal::string_t(LIBCLRJIT_NAME), false)) { m_clrjit_path = path; return; } }
bool pal::get_default_breadcrumb_store(string_t* recv) { recv->clear(); pal::char_t* prog_dat; HRESULT hr = ::SHGetKnownFolderPath(FOLDERID_ProgramData, 0, NULL, &prog_dat); if (hr != S_OK) { trace::verbose(_X("Failed to read default breadcrumb store 0x%X"), hr); return false; } recv->assign(prog_dat); append_path(recv, _X("Microsoft")); append_path(recv, _X("NetFramework")); append_path(recv, _X("BreadcrumbStore")); return true; }
bool pal::get_default_breadcrumb_store(string_t* recv) { recv->clear(); pal::string_t prog_dat; if (!get_file_path_from_env(_X("ProgramData"), &prog_dat)) { // We should have the path in prog_dat. trace::verbose(_X("Failed to read default breadcrumb store [%s]"), prog_dat.c_str()); return false; } recv->assign(prog_dat); append_path(recv, _X("Microsoft")); append_path(recv, _X("NetFramework")); append_path(recv, _X("BreadcrumbStore")); return true; }
void tpafile::add_from_local_dir(const pal::string_t& dir) { trace::verbose(_X("adding files from %s to TPA"), dir.c_str()); const pal::char_t * const tpa_extensions[] = { _X(".ni.dll"), // Probe for .ni.dll first so that it's preferred if ni and il coexist in the same dir _X(".dll"), _X(".ni.exe"), _X(".exe"), }; std::set<pal::string_t> added_assemblies; // Get directory entries auto files = pal::readdir(dir); for (auto ext : tpa_extensions) { auto len = pal::strlen(ext); for (auto file : files) { // Can't be a match if it's the same length as the extension :) if (file.length() > len) { // Extract the same amount of text from the end of file name auto file_ext = file.substr(file.length() - len, len); // Check if this file name matches if (pal::strcasecmp(ext, file_ext.c_str()) == 0) { // Get the assembly name by stripping the extension // and add it to the set so we can de-dupe auto asm_name = file.substr(0, file.length() - len); // TODO(anurse): Also check if already in TPA file if (added_assemblies.find(asm_name) == added_assemblies.end()) { added_assemblies.insert(asm_name); tpaentry_t entry; entry.asset_type = pal::string_t(_X("runtime")); entry.library_name = pal::string_t(asm_name); entry.library_version = pal::string_t(_X("")); pal::string_t relpath(dir); relpath.push_back(DIR_SEPARATOR); relpath.append(file); entry.relative_path = relpath; entry.asset_name = asm_name; trace::verbose(_X("adding %s to TPA list from %s"), asm_name.c_str(), relpath.c_str()); m_entries.push_back(entry); } } } } } }
xnet_tcp_client_ptr xclient::connect_to(const xstring& host, xport_t port) { xnet_tcp_client_ptr tcp_client(new xnet_tcp_client(io_service())); tcp_client->set_uuid(_X("{30201EA2-7AD5-46e8-91D6-7D3E878C8DC4}")); //tcp_client->set_handler_manager(); tcp_client->connect_to(host, port); return tcp_client; }
static void text(context_t *ctx, const xmlChar *text, changemode_t *textMode) { if (NULL!=textMode) { ctx->modeTxt=xmlStrcat(ctx->modeTxt, textMode->mode); ctx->modeTxt=xmlStrcat(ctx->modeTxt, _X(": \"")); ctx->modeTxt=xmlStrcat(ctx->modeTxt, text); ctx->modeTxt=xmlStrcat(ctx->modeTxt, _X("\"\n")); } if (NULL!=textMode && textMode->deleted) { if (!ctx->deleted) { ctx->parTxt=xmlStrcat(ctx->parTxt, _X("[]")); } ctx->deleted=OPC_TRUE; } else { ctx->parTxt=xmlStrcat(ctx->parTxt, text); ctx->deleted=OPC_FALSE; } }
runtime_config_t::runtime_config_t(const pal::string_t& path) : m_fx_roll_fwd(true) , m_path(path) , m_portable(false) { m_valid = ensure_parsed(); trace::verbose(_X("Runtime config [%s] is valid=[%d]"), path.c_str(), m_valid); }
bool deps_json_t::perform_rid_fallback(rid_specific_assets_t* portable_assets, const rid_fallback_graph_t& rid_fallback_graph) { pal::string_t host_rid = get_own_rid(); for (auto& package : portable_assets->libs) { pal::string_t matched_rid = package.second.rid_assets.count(host_rid) ? host_rid : _X(""); if (matched_rid.empty()) { if (rid_fallback_graph.count(host_rid) == 0) { trace::warning(_X("The targeted framework does not support the runtime '%s'. Some native libraries from [%s] may fail to load on this platform."), host_rid.c_str(), package.first.c_str()); } else { const auto& fallback_rids = rid_fallback_graph.find(host_rid)->second; auto iter = std::find_if(fallback_rids.begin(), fallback_rids.end(), [&package](const pal::string_t& rid) { return package.second.rid_assets.count(rid); }); if (iter != fallback_rids.end()) { matched_rid = *iter; } } } if (matched_rid.empty()) { package.second.rid_assets.clear(); } for (auto iter = package.second.rid_assets.begin(); iter != package.second.rid_assets.end(); /* */) { if (iter->first != matched_rid) { trace::verbose(_X("Chose %s, so removing rid (%s) specific assets for package %s"), matched_rid.c_str(), iter->first.c_str(), package.first.c_str()); iter = package.second.rid_assets.erase(iter); } else { ++iter; } } } return true; }
bool pal::find_coreclr(pal::string_t* recv) { pal::string_t candidate; // Try %LocalAppData%\dotnet if (pal::getenv(_X("LocalAppData"), &candidate)) { append_path(&candidate, _X("dotnet")); append_path(&candidate, _X("runtime")); append_path(&candidate, _X("coreclr")); if (coreclr_exists_in_dir(candidate)) { recv->assign(candidate); return true; } } // Try %ProgramFiles%. Note this works for both x86 and x64/wow64 as per: // https://msdn.microsoft.com/en-us/library/windows/desktop/aa384274(v=vs.85).aspx // candidate.clear(); getenv clears it. if (pal::getenv(_X("ProgramFiles"), &candidate)) { append_path(&candidate, _X("dotnet")); append_path(&candidate, _X("bin")); if (coreclr_exists_in_dir(candidate)) { recv->assign(candidate); return true; } } return false; }
bool pal::get_default_breadcrumb_store(string_t* recv) { recv->clear(); pal::string_t ext; if (pal::getenv(_X("CORE_BREADCRUMBS"), &ext) && pal::realpath(&ext)) { // We should have the path in ext. trace::info(_X("Realpath CORE_BREADCRUMBS [%s]"), ext.c_str()); } if (!pal::directory_exists(ext)) { trace::info(_X("Directory core breadcrumbs [%s] was not specified or found"), ext.c_str()); ext.clear(); append_path(&ext, _X("opt")); append_path(&ext, _X("corebreadcrumbs")); if (!pal::directory_exists(ext)) { trace::info(_X("Fallback directory core breadcrumbs at [%s] was not found"), ext.c_str()); return false; } } if (access(ext.c_str(), (R_OK | W_OK)) != 0) { trace::info(_X("Breadcrumb store [%s] is not ACL-ed with rw-"), ext.c_str()); } recv->assign(ext); return true; }
void tpafile::write_native_paths(pal::string_t& output) { std::set<pal::string_t> items; for (auto search_path : m_native_search_paths) { if (items.find(search_path) == items.end()) { trace::verbose(_X("adding native search path: %s"), search_path.c_str()); output.append(search_path); output.push_back(PATH_SEPARATOR); items.insert(search_path); } } for (auto entry : m_entries) { auto dir = entry.relative_path.substr(0, entry.relative_path.find_last_of(DIR_SEPARATOR)); if (pal::strcmp(entry.asset_type.c_str(), _X("native")) == 0 && items.find(dir) == items.end()) { // Resolve the full path for (auto search_path : m_package_search_paths) { pal::string_t candidate; candidate.reserve(search_path.length() + entry.library_name.length() + entry.library_version.length() + dir.length() + 3); candidate.append(search_path); append_path(candidate, entry.library_name.c_str()); append_path(candidate, entry.library_version.c_str()); append_path(candidate, get_directory(entry.relative_path).c_str()); if (pal::file_exists(candidate)) { trace::verbose(_X("adding native search path: %s"), candidate.c_str()); output.append(candidate); output.push_back(PATH_SEPARATOR); items.insert(dir); break; } } } } }
bool pal::get_default_servicing_directory(string_t* recv) { recv->clear(); // See https://github.com/dotnet/cli/issues/2179 #ifdef _TARGET_X86_ // In WOW64 mode, PF maps to PFx86. if (!pal::getenv(_X("ProgramFiles"), recv)) #elif defined(_TARGET_AMD64_) if (!pal::getenv(_X("ProgramFiles(x86)"), recv)) #endif { return false; } append_path(recv, _X("coreservicing")); return true; }
// ----------------------------------------------------------------------------- // Given a "base" directory, yield the local path of this file // // Parameters: // base - The base directory to look for the relative path of this entry // str - If the method returns true, contains the file path for this deps // entry relative to the "base" directory // // Returns: // If the file exists in the path relative to the "base" directory. // bool deps_entry_t::to_dir_path(const pal::string_t& base, pal::string_t* str) const { if (asset_type == asset_types::resources) { pal::string_t pal_relative_path = relative_path; if (_X('/') != DIR_SEPARATOR) { replace_char(&pal_relative_path, _X('/'), DIR_SEPARATOR); } pal::string_t ietf_dir = get_directory(pal_relative_path); pal::string_t ietf = get_filename(ietf_dir); pal::string_t base_ietf_dir = base; append_path(&base_ietf_dir, ietf.c_str()); trace::verbose(_X("Detected a resource asset, will query dir/ietf-tag/resource base: %s asset: %s"), base_ietf_dir.c_str(), asset_name.c_str()); return to_path(base_ietf_dir, true, str); } return to_path(base, true, str); }
void ExpandNonHostArgument(const dnx::char_t* value, std::vector<const dnx::char_t*>& expanded_args) { if (string_ends_with_ignore_case(value, _X(".dll")) || string_ends_with_ignore_case(value, _X(".exe"))) { // "dnx /path/App.dll arg1" --> "dnx --appbase /path/ /path/App.dll arg1" // "dnx /path/App.exe arg1" --> "dnx --appbase /path/ /path/App.exe arg1" // "dnx App.exe arg1" --> "dnx --appbase . App.exe arg1" AppendAppbaseFromFile(value, expanded_args); expanded_args.push_back(allocate_and_copy(value)); return; } // "dnx run" --> "dnx --appbase . Microsoft.Dnx.ApplicationHost run" expanded_args.push_back(allocate_and_copy(_X("--appbase"))); expanded_args.push_back(allocate_and_copy(_X("."))); expanded_args.push_back(allocate_and_copy(_X("Microsoft.Dnx.ApplicationHost"))); expanded_args.push_back(allocate_and_copy(value)); }
pal::proc_t pal::get_symbol(dll_t library, const char* name) { auto result = dlsym(library, name); if (result == nullptr) { trace::error(_X("Failed to resolve library symbol %s, error: %s"), name, dlerror()); } return result; }
pal::string_t pal::get_timestamp() { std::time_t t = std::time(0); const std::size_t elems = 100; char_t buf[elems]; std::wcsftime(buf, elems, _X("%c GMT"), std::gmtime(&t)); return pal::string_t(buf); }
void ExpandProject(const dnx::char_t* project_path, std::vector<const dnx::char_t*>& expanded_args) { auto split_idx = split_path(project_path); // note that we split the path first and check the file name to handle paths like c:\MyApp\my_project.json // (`split_idx + 1` works fine since `split_path` returns -1 if it does not find `\` or '/') if (dnx::utils::strings_equal_ignore_case(project_path + split_idx + 1, _X("project.json"))) { // "dnx /path/project.json run" --> "dnx --appbase /path/ Microsoft.Dnx.ApplicationHost run" AppendAppbaseFromFile(project_path, expanded_args); expanded_args.push_back(allocate_and_copy(_X("Microsoft.Dnx.ApplicationHost"))); return; } expanded_args.push_back(allocate_and_copy(_X("--appbase"))); expanded_args.push_back(allocate_and_copy(project_path)); expanded_args.push_back(allocate_and_copy(_X("Microsoft.Dnx.ApplicationHost"))); }
bool pal::get_default_servicing_directory(string_t* recv) { if (!get_wow_mode_program_files(recv)) { return false; } append_path(recv, _X("coreservicing")); return true; }
bool pal::load_library(const string_t* in_path, dll_t* dll) { string_t path = *in_path; // LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR: // In framework-dependent apps, coreclr would come from another directory than the host, // so make sure coreclr dependencies can be resolved from coreclr.dll load dir. if (LongFile::IsPathNotFullyQualified(path)) { if (!pal::realpath(&path)) { trace::error(_X("Failed to load the dll from [%s], HRESULT: 0x%X"), path.c_str(), HRESULT_FROM_WIN32(GetLastError())); return false; } } //Adding the assert to ensure relative paths which are not just filenames are not used for LoadLibrary Calls assert(!LongFile::IsPathNotFullyQualified(path) || !LongFile::ContainsDirectorySeparator(path)); *dll = ::LoadLibraryExW(path.c_str(), NULL, LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR | LOAD_LIBRARY_SEARCH_DEFAULT_DIRS); if (*dll == nullptr) { trace::error(_X("Failed to load the dll from [%s], HRESULT: 0x%X"), path.c_str(), HRESULT_FROM_WIN32(GetLastError())); return false; } // Pin the module HMODULE dummy_module; if (!::GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN, path.c_str(), &dummy_module)) { trace::error(_X("Failed to pin library [%s] in [%s]"), path.c_str(), _STRINGIFY(__FUNCTION__)); return false; } if (trace::is_enabled()) { string_t buf; GetModuleFileNameWrapper(*dll, &buf); trace::info(_X("Loaded library from %s"), buf.c_str()); } return true; }
bool get_sdk_self_registered_dir(pal::string_t* recv) { #if !defined(_TARGET_AMD64_) && !defined(_TARGET_X86_) // Self-registered SDK installation directory is only supported for x64 and x86 architectures. return false; #else recv->clear(); // ***Used only for testing*** pal::string_t environmentOverride; if (pal::getenv(_X("_DOTNET_TEST_SDK_SELF_REGISTERED_DIR"), &environmentOverride)) { recv->assign(environmentOverride); return true; } // *************************** DWORD size = 0; const HKEY hkey = HKEY_LOCAL_MACHINE; // The registry search occurs in the 32-bit registry in all cases. const DWORD flags = RRF_RT_REG_SZ | RRF_SUBKEY_WOW6432KEY; pal::string_t sub_key = pal::string_t(_X("SOFTWARE\\dotnet\\Setup\\InstalledVersions\\")) + get_arch() + pal::string_t(_X("\\sdk")); pal::char_t* value = _X("InstallLocation"); // Determine the size of the buffer LONG result = ::RegGetValueW(hkey, sub_key.c_str(), value, flags, nullptr, nullptr, &size); if (result != ERROR_SUCCESS || size == 0) { return false; } // Get the key's value std::vector<pal::char_t> buffer(size/sizeof(pal::char_t)); result = ::RegGetValueW(hkey, sub_key.c_str(), value, flags, nullptr, &buffer[0], &size); if (result != ERROR_SUCCESS) { return false; } recv->assign(buffer.data()); return true; #endif }
// X macro'd taylor series, attempted 6 digit accuracy float CFMathsHelpers::__fast_cos(float t) { // accuracy reduced to 4 digits if radians are out of bounds if ((float)((int)t & 0x7FFFFFF) > PI) t = __radian_bound(t); #define _X(exp) total += sign * acc / __factorial_templ<exp>::val(); sign *= -1; acc *= t_sqr; float acc = t * t, total = 1.f, t_sqr = t * t; int sign = -1; _X(2) _X(4); _X(6) _X(8) _X(10) _X(12) _X(14) _X(16); #undef _X return total; }
pal::string_t resolve_sdk_version(pal::string_t sdk_path) { trace::verbose(_X("--- Resolving SDK version from SDK dir [%s]"), sdk_path.c_str()); pal::string_t retval; std::vector<pal::string_t> versions; pal::readdir(sdk_path, &versions); fx_ver_t max_ver(-1, -1, -1); fx_ver_t max_pre(-1, -1, -1); for (const auto& version : versions) { trace::verbose(_X("Considering version... [%s]"), version.c_str()); fx_ver_t ver(-1, -1, -1); if (fx_ver_t::parse(version, &ver, true)) { max_ver = std::max(ver, max_ver); } if (fx_ver_t::parse(version, &ver, false)) { max_pre = std::max(ver, max_pre); } } // No production, use the max pre-release. if (max_ver == fx_ver_t(-1, -1, -1)) { trace::verbose(_X("No production version found, so using latest prerelease")); max_ver = max_pre; } pal::string_t max_ver_str = max_ver.as_str(); append_path(&sdk_path, max_ver_str.c_str()); trace::verbose(_X("Checking if resolved SDK dir [%s] exists"), sdk_path.c_str()); if (pal::directory_exists(sdk_path)) { retval = sdk_path; } trace::verbose(_X("Resolved SDK dir is [%s]"), retval.c_str()); return retval; }
// X macro'd taylor series, attempted 6 digit accuracy float CFMathsHelpers::__fast_sin(float t) { // accuracy reduced to 4 digits if radians are out of bounds if ((float)((int)t & 0x7FFFFFF) > PI) t = __radian_bound(t); #define _X(exp) total += sign * acc / __factorial_templ<exp>::val(); sign *= -1; acc *= t_sqr; float acc = t * t * t, total = t, t_sqr = t * t; int sign = -1; _X(3) _X(5) _X(7) _X(9) _X(11) _X(13) _X(15) _X(17); #undef _X return total; }