<commit_before>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// version: $Id$
// author:  Vassil Vassilev <vvasielv@cern.ch>
//------------------------------------------------------------------------------

#include "cling/Interpreter/Transaction.h"

#include "cling/Utils/AST.h"

#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/PrettyPrinter.h"

using namespace clang;

namespace cling {

  Transaction::~Transaction() {
    for (size_t i = 0; i < m_NestedTransactions.size(); ++i)
      delete m_NestedTransactions[i];
  }

  void Transaction::appendUnique(DeclGroupRef DGR) {
    for (const_iterator I = decls_begin(), E = decls_end(); I != E; ++I) {
      if (DGR.isNull() || (*I).getAsOpaquePtr() == DGR.getAsOpaquePtr())
        return;
    }
    // register the wrapper if any.
    if (DGR.isSingleDecl()) {
      if (FunctionDecl* FD = dyn_cast<FunctionDecl>(DGR.getSingleDecl()))
        if (utils::Analyze::IsWrapper(FD)) {
          assert(!m_WrapperFD && "Two wrappers in one transaction?");
          m_WrapperFD = FD;
        }
    }
    m_DeclQueue.push_back(DGR);
  }

  void Transaction::dump() const {
    if (!size())
      return;

    ASTContext& C = getFirstDecl().getSingleDecl()->getASTContext();
    PrintingPolicy Policy = C.getPrintingPolicy();
    Policy.DumpSourceManager = &C.getSourceManager();
    print(llvm::outs(), Policy, /*Indent*/0, /*PrintInstantiation*/true);
  }

  void Transaction::dumpPretty() const {
    if (!size())
      return;

    ASTContext& C = getFirstDecl().getSingleDecl()->getASTContext();
    PrintingPolicy Policy(C.getLangOpts());
    print(llvm::outs(), Policy, /*Indent*/0, /*PrintInstantiation*/true);
  }

  void Transaction::print(llvm::raw_ostream& Out, const PrintingPolicy& Policy,
                          unsigned Indent, bool PrintInstantiation) const {
    int nestedT = 0;
    for (const_iterator I = decls_begin(), E = decls_end(); I != E; ++I) {
      if (I->isNull()) {
        assert(hasNestedTransactions() && "DGR is null even if no nesting?");
        // print the nested decl
        Out<<"+====================================================+\n";
        Out<<"|       Nested Transaction" << nestedT << "          |\n";
        Out<<"+====================================================+\n";
        m_NestedTransactions[nestedT++]->print(Out, Policy, Indent,
                                               PrintInstantiation);
        Out<<"+====================================================+\n";
        Out<<"|         End Transaction" << nestedT << "           |\n";
        Out<<"+====================================================+\n";
      }
      for (DeclGroupRef::const_iterator J = I->begin(), L = I->end();J != L;++J)
        if (*J)
          (*J)->print(Out, Policy, Indent, PrintInstantiation);
        else
          Out << "<<NULL DECL>>";
    }
  }

} // end namespace cling
<commit_msg>If the first decl happens to be null ask the wrapper function for the ASTContext.<commit_after>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// version: $Id$
// author:  Vassil Vassilev <vvasielv@cern.ch>
//------------------------------------------------------------------------------

#include "cling/Interpreter/Transaction.h"

#include "cling/Utils/AST.h"

#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/PrettyPrinter.h"

using namespace clang;

namespace cling {

  Transaction::~Transaction() {
    for (size_t i = 0; i < m_NestedTransactions.size(); ++i)
      delete m_NestedTransactions[i];
  }

  void Transaction::appendUnique(DeclGroupRef DGR) {
    for (const_iterator I = decls_begin(), E = decls_end(); I != E; ++I) {
      if (DGR.isNull() || (*I).getAsOpaquePtr() == DGR.getAsOpaquePtr())
        return;
    }
    // register the wrapper if any.
    if (DGR.isSingleDecl()) {
      if (FunctionDecl* FD = dyn_cast<FunctionDecl>(DGR.getSingleDecl()))
        if (utils::Analyze::IsWrapper(FD)) {
          assert(!m_WrapperFD && "Two wrappers in one transaction?");
          m_WrapperFD = FD;
        }
    }
    m_DeclQueue.push_back(DGR);
  }

  void Transaction::dump() const {
    if (!size())
      return;

    ASTContext& C = getFirstDecl().getSingleDecl()->getASTContext();
    PrintingPolicy Policy = C.getPrintingPolicy();
    Policy.DumpSourceManager = &C.getSourceManager();
    print(llvm::outs(), Policy, /*Indent*/0, /*PrintInstantiation*/true);
  }

  void Transaction::dumpPretty() const {
    if (!size())
      return;
    ASTContext* C;
    if (m_WrapperFD)
      C = &(m_WrapperFD->getASTContext());
    if (!getFirstDecl().isNull())
      C = &(getFirstDecl().getSingleDecl()->getASTContext());

    PrintingPolicy Policy(C->getLangOpts());
    print(llvm::outs(), Policy, /*Indent*/0, /*PrintInstantiation*/true);
  }

  void Transaction::print(llvm::raw_ostream& Out, const PrintingPolicy& Policy,
                          unsigned Indent, bool PrintInstantiation) const {
    int nestedT = 0;
    for (const_iterator I = decls_begin(), E = decls_end(); I != E; ++I) {
      if (I->isNull()) {
        assert(hasNestedTransactions() && "DGR is null even if no nesting?");
        // print the nested decl
        Out<< "\n";
        Out<<"+====================================================+\n";
        Out<<"        Nested Transaction" << nestedT << "           \n";
        Out<<"+====================================================+\n";
        m_NestedTransactions[nestedT++]->print(Out, Policy, Indent,
                                               PrintInstantiation);
        Out<< "\n";
        Out<<"+====================================================+\n";
        Out<<"          End Transaction" << nestedT << "            \n";
        Out<<"+====================================================+\n";
      }
      for (DeclGroupRef::const_iterator J = I->begin(), L = I->end();J != L;++J)
        if (*J)
          (*J)->print(Out, Policy, Indent, PrintInstantiation);
        else
          Out << "<<NULL DECL>>";
    }
  }

} // end namespace cling
<|endoftext|>


<commit_before>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/installer/gcapi/gcapi.h"

#include <atlbase.h>
#include <atlcom.h>
#include <windows.h>
#include <sddl.h>
#include <stdlib.h>
#include <strsafe.h>
#include <tlhelp32.h>

#include "google_update_idl.h"

namespace {

const wchar_t kChromeRegClientsKey[] = L"Software\\Google\\Update\\Clients\\{8A69D345-D564-463c-AFF1-A69D9E530F96}";
const wchar_t kChromeRegClientStateKey[] = L"Software\\Google\\Update\\ClientState\\{8A69D345-D564-463c-AFF1-A69D9E530F96}";
const wchar_t kChromeRegLaunchCmd[] = L"InstallerSuccessLaunchCmdLine";
const wchar_t kChromeRegLastLaunchCmd[] = L"LastInstallerSuccessLaunchCmdLine";
const wchar_t kChromeRegVersion[] = L"pv";
const wchar_t kNoChromeOfferUntil[] = L"SOFTWARE\\Google\\No Chrome Offer Until";

// Remove any registry key with non-numeric value or with the numeric value
// equal or less than today's date represented in YYYYMMDD form.
void CleanUpRegistryValues() {
  HKEY key = NULL;
  if (::RegOpenKeyEx(HKEY_LOCAL_MACHINE, kNoChromeOfferUntil,
      0, KEY_ALL_ACCESS, &key) != ERROR_SUCCESS)
    return;

  DWORD index = 0;
  wchar_t value_name[260];
  DWORD value_name_len = _countof(value_name);
  DWORD value_type = REG_DWORD;
  DWORD value_data = 0;
  DWORD value_len = sizeof(DWORD);

  // First, remove any value whose type is not DWORD
  index = 0;
  value_len = 0;
  while (::RegEnumValue(key, index, value_name, &value_name_len,
      NULL, &value_type, NULL, &value_len) == ERROR_SUCCESS) {
    if (value_type == REG_DWORD)
      index++;
    else
      ::RegDeleteValue(key, value_name);

    value_name_len = _countof(value_name);
    value_type = REG_DWORD;
    value_len = sizeof(DWORD);
  }

  // Get today's date, and format it as YYYYMMDD numeric value
  SYSTEMTIME now;
  ::GetLocalTime(&now);
  DWORD expiration_date = now.wYear * 10000 + now.wMonth * 100 + now.wDay;

  // Remove any DWORD value smaller than the number represent the
  // expiration date (YYYYMMDD)
  index = 0;
  while (::RegEnumValue(key, index, value_name, &value_name_len,
      NULL, &value_type, (LPBYTE) &value_data, &value_len) == ERROR_SUCCESS) {
    if (value_type == REG_DWORD && value_data > expiration_date)
      index++;  // move on to next value
    else
      ::RegDeleteValue(key, value_name);  // delete this value

    value_name_len = _countof(value_name);
    value_type = REG_DWORD;
    value_data = 0;
    value_len = sizeof(DWORD);
  }

  ::RegCloseKey(key);
}

// Return the company name specified in the file version info resource.
bool GetCompanyName(const wchar_t* filename, wchar_t* buffer, DWORD out_len) {
  wchar_t file_version_info[8192];
  DWORD handle = 0;
  DWORD buffer_size = 0;

  buffer_size = ::GetFileVersionInfoSize(filename, &handle);
  // Cannot stats the file or our buffer size is too small (very unlikely)
  if (buffer_size == 0 || buffer_size > _countof(file_version_info))
    return false;

  buffer_size = _countof(file_version_info);
  memset(file_version_info, 0, buffer_size);
  if (!::GetFileVersionInfo(filename, handle, buffer_size, file_version_info))
    return false;

  DWORD data_len = 0;
  LPVOID data = NULL;
  // Retrieve the language and codepage code if exists.
  buffer_size = 0;
  if (!::VerQueryValue(file_version_info, TEXT("\\VarFileInfo\\Translation"),
      reinterpret_cast<LPVOID *>(&data), reinterpret_cast<UINT *>(&data_len)))
    return false;
  if (data_len != 4)
    return false;

  wchar_t info_name[256];
  DWORD lang = 0;
  // Formulate the string to retrieve the company name of the specific
  // language codepage.
  memcpy(&lang, data, 4);
  ::StringCchPrintf(info_name, _countof(info_name),
      L"\\StringFileInfo\\%02X%02X%02X%02X\\CompanyName",
      (lang & 0xff00)>>8, (lang & 0xff), (lang & 0xff000000)>>24,
      (lang & 0xff0000)>>16);

  data_len = 0;
  if (!::VerQueryValue(file_version_info, info_name,
      reinterpret_cast<LPVOID *>(&data), reinterpret_cast<UINT *>(&data_len)))
    return false;
  if (data_len <= 0 || data_len >= out_len)
    return false;

  memset(buffer, 0, out_len);
  ::StringCchCopyN(buffer, out_len, (const wchar_t*)data, data_len);
  return true;
}

// Return true if we can re-offer Chrome; false, otherwise.
// Each partner can only offer Chrome once every six months.
bool CanReOfferChrome() {
  wchar_t filename[MAX_PATH+1];
  wchar_t company[MAX_PATH];

  // If we cannot retrieve the version info of the executable or company
  // name, we allow the Chrome to be offered because there is no past
  // history to be found.
  if (::GetModuleFileName(NULL, filename, MAX_PATH) == 0)
    return true;
  if (!GetCompanyName(filename, company, sizeof(company)))
    return true;

  bool can_re_offer = true;
  DWORD disposition = 0;
  HKEY key = NULL;
  if (::RegCreateKeyEx(HKEY_LOCAL_MACHINE, kNoChromeOfferUntil,
      0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE,
      NULL, &key, &disposition) == ERROR_SUCCESS) {
    // Cannot re-offer, if the timer already exists and is not expired yet
    if (::RegQueryValueEx(key, company, 0, 0, 0, 0) == ERROR_SUCCESS) {
      // The expired timers were already removed in CleanUpRegistryValues.
      // So if the key is not found, we can offer the Chrome.
      can_re_offer = false;
    } else {
      // Set expiration date for offer as six months from today,
      // represented as a YYYYMMDD numeric value
      SYSTEMTIME timer;
      ::GetLocalTime(&timer);
      timer.wMonth = timer.wMonth + 6;
      if (timer.wMonth > 12) {
        timer.wMonth = timer.wMonth - 12;
        timer.wYear = timer.wYear + 1;
      }
      DWORD value = timer.wYear * 10000 + timer.wMonth * 100 + timer.wDay;
      ::RegSetValueEx(key, company, 0, REG_DWORD, (LPBYTE)&value, sizeof(DWORD));
    }

    ::RegCloseKey(key);
  }

  return can_re_offer;
}

// Helper function to read a value from registry. Returns true if value
// is read successfully and stored in parameter value. Returns false otherwise.
bool ReadValueFromRegistry(HKEY root_key, const wchar_t *sub_key,
                           const wchar_t *value_name, wchar_t *value,
                           size_t *size) {
  HKEY key;
  if ((::RegOpenKeyEx(root_key, sub_key, NULL,
                      KEY_READ, &key) == ERROR_SUCCESS) &&
      (::RegQueryValueEx(key, value_name, NULL, NULL,
                         reinterpret_cast<LPBYTE>(value),
                         reinterpret_cast<LPDWORD>(size)) == ERROR_SUCCESS)) {
    ::RegCloseKey(key);
    return true;
  }
  return false;
}

bool IsChromeInstalled(HKEY root_key) {
  wchar_t version[64];
  size_t size = _countof(version);
  if (ReadValueFromRegistry(root_key, kChromeRegClientsKey, kChromeRegVersion,
                            version, &size))
    return true;
  return false;
}

bool IsWinXPSp1OrLater(bool* is_vista_or_later) {
  OSVERSIONINFOEX osviex = { sizeof(OSVERSIONINFOEX) };
  int r = ::GetVersionEx((LPOSVERSIONINFO)&osviex);
  // If this failed we're on Win9X or a pre NT4SP6 OS
  if (!r)
    return false;

  if (osviex.dwMajorVersion < 5)
    return false;

  if (osviex.dwMajorVersion > 5) {
    *is_vista_or_later = true;
    return true;    // way beyond Windows XP;
  }

  if (osviex.dwMinorVersion >= 1 && osviex.wServicePackMajor >= 1)
    return true;    // Windows XP SP1 or better

  return false;     // Windows 2000, WinXP no Service Pack
}

// Note this function should not be called on old Windows versions where these
// Windows API are not available. We always invoke this function after checking
// that current OS is Vista or later.
bool VerifyAdminGroup() {
  SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
  PSID Group;
  BOOL check = ::AllocateAndInitializeSid(&NtAuthority, 2,
                                          SECURITY_BUILTIN_DOMAIN_RID,
                                          DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0,
                                          0, 0, 0,
                                          &Group);
  if (check) {
    if (!::CheckTokenMembership(NULL, Group, &check))
      check = FALSE;
  }
  ::FreeSid(Group);
  return (check == TRUE);
}

bool VerifyHKLMAccess(const wchar_t* sub_key) {
  HKEY root = HKEY_LOCAL_MACHINE;
  wchar_t str[] = L"test";
  bool result = false;
  DWORD disposition = 0;
  HKEY key = NULL;

  if (::RegCreateKeyEx(root, sub_key, 0, NULL,
                       REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL,
                       &key, &disposition) == ERROR_SUCCESS) {
    if (::RegSetValueEx(key, str, 0, REG_SZ, (LPBYTE)str,
        (DWORD)lstrlen(str)) == ERROR_SUCCESS) {
      result = true;
      RegDeleteValue(key, str);
    }

    //  If we create the main key, delete the entire key.
    if (disposition == REG_CREATED_NEW_KEY)
      RegDeleteKey(key, NULL);

    RegCloseKey(key);
  }

  return result;
}

bool IsRunningElevated() {
  // This method should be called only for Vista or later.
  bool is_vista_or_later = false;
  IsWinXPSp1OrLater(&is_vista_or_later);
  if (!is_vista_or_later || !VerifyAdminGroup())
    return false;

  HANDLE process_token;
  if (!::OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &process_token))
    return false;

  TOKEN_ELEVATION_TYPE elevation_type = TokenElevationTypeDefault;
  DWORD size_returned = 0;
  if (!::GetTokenInformation(process_token, TokenElevationType,
                             &elevation_type, sizeof(elevation_type),
                             &size_returned)) {
    ::CloseHandle(process_token);
    return false;
  }

  ::CloseHandle(process_token);
  return (elevation_type == TokenElevationTypeFull);
}

bool GetUserIdForProcess(size_t pid, wchar_t** user_sid) {
  HANDLE process_handle = ::OpenProcess(PROCESS_QUERY_INFORMATION, TRUE, pid);
  if (process_handle == NULL)
    return false;

  HANDLE process_token;
  bool result = false;
  if (::OpenProcessToken(process_handle, TOKEN_QUERY, &process_token)) {
    DWORD size = 0;
    ::GetTokenInformation(process_token, TokenUser, NULL, 0, &size);
    if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER ||
        ::GetLastError() == ERROR_SUCCESS) {
      DWORD actual_size = 0;
      BYTE* token_user = new BYTE[size];
      if ((::GetTokenInformation(process_token, TokenUser, token_user, size,
                                &actual_size)) &&
          (actual_size <= size)) {
        PSID sid = reinterpret_cast<TOKEN_USER*>(token_user)->User.Sid;
        if (::ConvertSidToStringSid(sid, user_sid))
          result = true;
      }
      delete[] token_user;
    }
    ::CloseHandle(process_token);
  }
  ::CloseHandle(process_handle);
  return result;
}
}  // namespace

#pragma comment(linker, "/EXPORT:GoogleChromeCompatibilityCheck=_GoogleChromeCompatibilityCheck@4,PRIVATE")
DLLEXPORT BOOL __stdcall GoogleChromeCompatibilityCheck(DWORD *reasons) {
  DWORD local_reasons = 0;

  bool is_vista_or_later = false;
  // System requirements?
  if (!IsWinXPSp1OrLater(&is_vista_or_later))
    local_reasons |= GCCC_ERROR_OSNOTSUPPORTED;

  if (IsChromeInstalled(HKEY_LOCAL_MACHINE))
    local_reasons |= GCCC_ERROR_SYSTEMLEVELALREADYPRESENT;

  if (IsChromeInstalled(HKEY_CURRENT_USER))
    local_reasons |= GCCC_ERROR_USERLEVELALREADYPRESENT;

  if (!VerifyHKLMAccess(kChromeRegClientsKey)) {
    local_reasons |= GCCC_ERROR_ACCESSDENIED;
  } else if (is_vista_or_later && !VerifyAdminGroup()) {
    // For Vista or later check for elevation since even for admin user we could
    // be running in non-elevated mode. We require integrity level High.
    local_reasons |= GCCC_ERROR_INTEGRITYLEVEL;
  }

  // First clean up the registry keys left over previously.
  // Then only check whether we can re-offer, if everything else is OK.
  CleanUpRegistryValues();
  if (local_reasons == 0 && !CanReOfferChrome())
    local_reasons |= GCCC_ERROR_ALREADYOFFERED;

  // Done. Copy/return results.
  if (reasons != NULL)
    *reasons = local_reasons;

  return (*reasons == 0);
}

#pragma comment(linker, "/EXPORT:LaunchGoogleChrome=_LaunchGoogleChrome@0,PRIVATE")
DLLEXPORT BOOL __stdcall LaunchGoogleChrome() {
  wchar_t launch_cmd[MAX_PATH];
  size_t size = _countof(launch_cmd);
  if (!ReadValueFromRegistry(HKEY_LOCAL_MACHINE, kChromeRegClientStateKey,
                             kChromeRegLastLaunchCmd, launch_cmd, &size)) {
    size = _countof(launch_cmd);
    if (!ReadValueFromRegistry(HKEY_LOCAL_MACHINE, kChromeRegClientStateKey,
                               kChromeRegLaunchCmd, launch_cmd, &size)) {
      return false;
    }
  }

  HRESULT hr = ::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
  if (hr != S_OK) {
    if (hr == S_FALSE)
      ::CoUninitialize();
    return false;
  }

  if (::CoInitializeSecurity(NULL, -1, NULL, NULL,
                             RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
                             RPC_C_IMP_LEVEL_IDENTIFY, NULL,
                             EOAC_DYNAMIC_CLOAKING, NULL) != S_OK) {
    ::CoUninitialize();
    return false;
  }

  bool impersonation_success = false;
  if (IsRunningElevated()) {
    wchar_t* curr_proc_sid;
    if (!GetUserIdForProcess(GetCurrentProcessId(), &curr_proc_sid)) {
      ::CoUninitialize();
      return false;
    }

    DWORD pid = 0;
    ::GetWindowThreadProcessId(::GetShellWindow(), &pid);
    if (pid <= 0) {
      ::LocalFree(curr_proc_sid);
      ::CoUninitialize();
      return false;
    }

    wchar_t* exp_proc_sid;
    if (GetUserIdForProcess(pid, &exp_proc_sid)) {
      if (_wcsicmp(curr_proc_sid, exp_proc_sid) == 0) {
        HANDLE process_handle = ::OpenProcess(
            PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION, TRUE, pid);
        if (process_handle != NULL) {
          HANDLE process_token;
          HANDLE user_token;
          if (::OpenProcessToken(process_handle, TOKEN_DUPLICATE | TOKEN_QUERY,
                                 &process_token) &&
              ::DuplicateTokenEx(process_token,
                                 TOKEN_IMPERSONATE | TOKEN_QUERY |
                                     TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE,
                                 NULL, SecurityImpersonation,
                                 TokenPrimary, &user_token) &&
              (::ImpersonateLoggedOnUser(user_token) != 0)) {
            impersonation_success = true;
          }
          ::CloseHandle(user_token);
          ::CloseHandle(process_token);
          ::CloseHandle(process_handle);
        }
      }
      ::LocalFree(exp_proc_sid);
    }

    ::LocalFree(curr_proc_sid);
    if (!impersonation_success) {
      ::CoUninitialize();
      return false;
    }
  }

  bool ret = false;
  CComPtr<IProcessLauncher> ipl;
  if (!FAILED(ipl.CoCreateInstance(__uuidof(ProcessLauncherClass), NULL,
                                   CLSCTX_LOCAL_SERVER))) {
    if (!FAILED(ipl->LaunchCmdLine(launch_cmd)))
      ret = true;
    ipl.Release();
  }

  if (impersonation_success)
    ::RevertToSelf();
  ::CoUninitialize();
  return ret;
}
<commit_msg>* Remove re-offer check from criteria checker.<commit_after>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/installer/gcapi/gcapi.h"

#include <atlbase.h>
#include <atlcom.h>
#include <windows.h>
#include <sddl.h>
#include <stdlib.h>
#include <strsafe.h>
#include <tlhelp32.h>

#include "google_update_idl.h"

namespace {

const wchar_t kChromeRegClientsKey[] = L"Software\\Google\\Update\\Clients\\{8A69D345-D564-463c-AFF1-A69D9E530F96}";
const wchar_t kChromeRegClientStateKey[] = L"Software\\Google\\Update\\ClientState\\{8A69D345-D564-463c-AFF1-A69D9E530F96}";
const wchar_t kChromeRegLaunchCmd[] = L"InstallerSuccessLaunchCmdLine";
const wchar_t kChromeRegLastLaunchCmd[] = L"LastInstallerSuccessLaunchCmdLine";
const wchar_t kChromeRegVersion[] = L"pv";

// Helper function to read a value from registry. Returns true if value
// is read successfully and stored in parameter value. Returns false otherwise.
bool ReadValueFromRegistry(HKEY root_key, const wchar_t *sub_key,
                           const wchar_t *value_name, wchar_t *value,
                           size_t *size) {
  HKEY key;
  if ((::RegOpenKeyEx(root_key, sub_key, NULL,
                      KEY_READ, &key) == ERROR_SUCCESS) &&
      (::RegQueryValueEx(key, value_name, NULL, NULL,
                         reinterpret_cast<LPBYTE>(value),
                         reinterpret_cast<LPDWORD>(size)) == ERROR_SUCCESS)) {
    ::RegCloseKey(key);
    return true;
  }
  return false;
}

bool IsChromeInstalled(HKEY root_key) {
  wchar_t version[64];
  size_t size = _countof(version);
  if (ReadValueFromRegistry(root_key, kChromeRegClientsKey, kChromeRegVersion,
                            version, &size))
    return true;
  return false;
}

bool IsWinXPSp1OrLater(bool* is_vista_or_later) {
  OSVERSIONINFOEX osviex = { sizeof(OSVERSIONINFOEX) };
  int r = ::GetVersionEx((LPOSVERSIONINFO)&osviex);
  // If this failed we're on Win9X or a pre NT4SP6 OS
  if (!r)
    return false;

  if (osviex.dwMajorVersion < 5)
    return false;

  if (osviex.dwMajorVersion > 5) {
    *is_vista_or_later = true;
    return true;    // way beyond Windows XP;
  }

  if (osviex.dwMinorVersion >= 1 && osviex.wServicePackMajor >= 1)
    return true;    // Windows XP SP1 or better

  return false;     // Windows 2000, WinXP no Service Pack
}

// Note this function should not be called on old Windows versions where these
// Windows API are not available. We always invoke this function after checking
// that current OS is Vista or later.
bool VerifyAdminGroup() {
  SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
  PSID Group;
  BOOL check = ::AllocateAndInitializeSid(&NtAuthority, 2,
                                          SECURITY_BUILTIN_DOMAIN_RID,
                                          DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0,
                                          0, 0, 0,
                                          &Group);
  if (check) {
    if (!::CheckTokenMembership(NULL, Group, &check))
      check = FALSE;
  }
  ::FreeSid(Group);
  return (check == TRUE);
}

bool VerifyHKLMAccess(const wchar_t* sub_key) {
  HKEY root = HKEY_LOCAL_MACHINE;
  wchar_t str[] = L"test";
  bool result = false;
  DWORD disposition = 0;
  HKEY key = NULL;

  if (::RegCreateKeyEx(root, sub_key, 0, NULL,
                       REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL,
                       &key, &disposition) == ERROR_SUCCESS) {
    if (::RegSetValueEx(key, str, 0, REG_SZ, (LPBYTE)str,
        (DWORD)lstrlen(str)) == ERROR_SUCCESS) {
      result = true;
      RegDeleteValue(key, str);
    }

    //  If we create the main key, delete the entire key.
    if (disposition == REG_CREATED_NEW_KEY)
      RegDeleteKey(key, NULL);

    RegCloseKey(key);
  }

  return result;
}

bool IsRunningElevated() {
  // This method should be called only for Vista or later.
  bool is_vista_or_later = false;
  IsWinXPSp1OrLater(&is_vista_or_later);
  if (!is_vista_or_later || !VerifyAdminGroup())
    return false;

  HANDLE process_token;
  if (!::OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &process_token))
    return false;

  TOKEN_ELEVATION_TYPE elevation_type = TokenElevationTypeDefault;
  DWORD size_returned = 0;
  if (!::GetTokenInformation(process_token, TokenElevationType,
                             &elevation_type, sizeof(elevation_type),
                             &size_returned)) {
    ::CloseHandle(process_token);
    return false;
  }

  ::CloseHandle(process_token);
  return (elevation_type == TokenElevationTypeFull);
}

bool GetUserIdForProcess(size_t pid, wchar_t** user_sid) {
  HANDLE process_handle = ::OpenProcess(PROCESS_QUERY_INFORMATION, TRUE, pid);
  if (process_handle == NULL)
    return false;

  HANDLE process_token;
  bool result = false;
  if (::OpenProcessToken(process_handle, TOKEN_QUERY, &process_token)) {
    DWORD size = 0;
    ::GetTokenInformation(process_token, TokenUser, NULL, 0, &size);
    if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER ||
        ::GetLastError() == ERROR_SUCCESS) {
      DWORD actual_size = 0;
      BYTE* token_user = new BYTE[size];
      if ((::GetTokenInformation(process_token, TokenUser, token_user, size,
                                &actual_size)) &&
          (actual_size <= size)) {
        PSID sid = reinterpret_cast<TOKEN_USER*>(token_user)->User.Sid;
        if (::ConvertSidToStringSid(sid, user_sid))
          result = true;
      }
      delete[] token_user;
    }
    ::CloseHandle(process_token);
  }
  ::CloseHandle(process_handle);
  return result;
}
}  // namespace

#pragma comment(linker, "/EXPORT:GoogleChromeCompatibilityCheck=_GoogleChromeCompatibilityCheck@4,PRIVATE")
DLLEXPORT BOOL __stdcall GoogleChromeCompatibilityCheck(DWORD *reasons) {
  DWORD local_reasons = 0;

  bool is_vista_or_later = false;
  // System requirements?
  if (!IsWinXPSp1OrLater(&is_vista_or_later))
    local_reasons |= GCCC_ERROR_OSNOTSUPPORTED;

  if (IsChromeInstalled(HKEY_LOCAL_MACHINE))
    local_reasons |= GCCC_ERROR_SYSTEMLEVELALREADYPRESENT;

  if (IsChromeInstalled(HKEY_CURRENT_USER))
    local_reasons |= GCCC_ERROR_USERLEVELALREADYPRESENT;

  if (!VerifyHKLMAccess(kChromeRegClientsKey)) {
    local_reasons |= GCCC_ERROR_ACCESSDENIED;
  } else if (is_vista_or_later && !VerifyAdminGroup()) {
    // For Vista or later check for elevation since even for admin user we could
    // be running in non-elevated mode. We require integrity level High.
    local_reasons |= GCCC_ERROR_INTEGRITYLEVEL;
  }

  // Done. Copy/return results.
  if (reasons != NULL)
    *reasons = local_reasons;

  return (*reasons == 0);
}

#pragma comment(linker, "/EXPORT:LaunchGoogleChrome=_LaunchGoogleChrome@0,PRIVATE")
DLLEXPORT BOOL __stdcall LaunchGoogleChrome() {
  wchar_t launch_cmd[MAX_PATH];
  size_t size = _countof(launch_cmd);
  if (!ReadValueFromRegistry(HKEY_LOCAL_MACHINE, kChromeRegClientStateKey,
                             kChromeRegLastLaunchCmd, launch_cmd, &size)) {
    size = _countof(launch_cmd);
    if (!ReadValueFromRegistry(HKEY_LOCAL_MACHINE, kChromeRegClientStateKey,
                               kChromeRegLaunchCmd, launch_cmd, &size)) {
      return false;
    }
  }

  HRESULT hr = ::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
  if (hr != S_OK) {
    if (hr == S_FALSE)
      ::CoUninitialize();
    return false;
  }

  if (::CoInitializeSecurity(NULL, -1, NULL, NULL,
                             RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
                             RPC_C_IMP_LEVEL_IDENTIFY, NULL,
                             EOAC_DYNAMIC_CLOAKING, NULL) != S_OK) {
    ::CoUninitialize();
    return false;
  }

  bool impersonation_success = false;
  if (IsRunningElevated()) {
    wchar_t* curr_proc_sid;
    if (!GetUserIdForProcess(GetCurrentProcessId(), &curr_proc_sid)) {
      ::CoUninitialize();
      return false;
    }

    DWORD pid = 0;
    ::GetWindowThreadProcessId(::GetShellWindow(), &pid);
    if (pid <= 0) {
      ::LocalFree(curr_proc_sid);
      ::CoUninitialize();
      return false;
    }

    wchar_t* exp_proc_sid;
    if (GetUserIdForProcess(pid, &exp_proc_sid)) {
      if (_wcsicmp(curr_proc_sid, exp_proc_sid) == 0) {
        HANDLE process_handle = ::OpenProcess(
            PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION, TRUE, pid);
        if (process_handle != NULL) {
          HANDLE process_token;
          HANDLE user_token;
          if (::OpenProcessToken(process_handle, TOKEN_DUPLICATE | TOKEN_QUERY,
                                 &process_token) &&
              ::DuplicateTokenEx(process_token,
                                 TOKEN_IMPERSONATE | TOKEN_QUERY |
                                     TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE,
                                 NULL, SecurityImpersonation,
                                 TokenPrimary, &user_token) &&
              (::ImpersonateLoggedOnUser(user_token) != 0)) {
            impersonation_success = true;
          }
          ::CloseHandle(user_token);
          ::CloseHandle(process_token);
          ::CloseHandle(process_handle);
        }
      }
      ::LocalFree(exp_proc_sid);
    }

    ::LocalFree(curr_proc_sid);
    if (!impersonation_success) {
      ::CoUninitialize();
      return false;
    }
  }

  bool ret = false;
  CComPtr<IProcessLauncher> ipl;
  if (!FAILED(ipl.CoCreateInstance(__uuidof(ProcessLauncherClass), NULL,
                                   CLSCTX_LOCAL_SERVER))) {
    if (!FAILED(ipl->LaunchCmdLine(launch_cmd)))
      ret = true;
    ipl.Release();
  }

  if (impersonation_success)
    ::RevertToSelf();
  ::CoUninitialize();
  return ret;
}
<|endoftext|>


<commit_before>/*
  Copyright 2013 SINTEF ICT, Applied Mathematics.
*/

#include <opm/core/utility/parameters/ParameterGroup.hpp>
#include <opm/core/linalg/LinearSolverFactory.hpp>
#include <opm/core/utility/ErrorMacros.hpp>
#include <opm/autodiff/AutoDiffBlock.hpp>
#include <opm/autodiff/AutoDiffHelpers.hpp>
#include <opm/core/grid.h>
#include <opm/core/grid/GridManager.hpp>
#include <algorithm>
#include <iterator>
#include <iostream>
#include <cmath>

#include "EquelleRuntimeCPU.hpp"

struct UserParameters
{
    // ============= Generated code starts here ================
    // k : Scalar = UserSpecifiedScalarWithDefault(0.3) # Heat diffusion constant.
    double k;
    // dt : Scalar = UserSpecifiedScalarWithDefault(0.5) # Time step length.
    double dt;
    // u0 : Collection Of Scalar On AllCells() = UserSpecifiedCollectionOfScalar( AllCells() )
    CollOfScalars u0;
    // dirichlet_boundary : Collection Of Face On BoundaryFaces() = UserSpecifiedCollectionOfFace( BoundaryFaces() )
    CollOfFaces dirichlet_boundary;
    // dirichlet_val : Collection Of Scalar On dirichlet_boundary = UserSpecifiedCollectionOfScalar( dirichlet_boundary )
    CollOfScalars dirichlet_val;

    // ============= Generated code ends here ================

    UserParameters(const Opm::parameter::ParameterGroup& param,
                   const EquelleRuntimeCPU& er)
    {
        // ============= Generated code starts here ================
        // k : Scalar = UserSpecifiedScalarWithDefault(0.3) # Heat diffusion constant.
        k = param.getDefault("k", 0.3);
        // dt : Scalar = UserSpecifiedScalarWithDefault(0.5) # Time step length.
        dt = param.getDefault("dt", 0.5);
        // u0 : Collection Of Scalar On AllCells() = UserSpecifiedCollectionOfScalar( AllCells() )
        u0 = er.getUserSpecifiedCollectionOfScalar(param, "u0", er.allCells().size());
        // dirichlet_boundary : Collection Of Face On BoundaryFaces() = UserSpecifiedCollectionOfFace( BoundaryFaces() )
        dirichlet_boundary = er.getUserSpecifiedCollectionOfFaceSubsetOf(param, "dirichlet_boundary", er.boundaryFaces());
        // dirichlet_val : Collection Of Scalar On dirichlet_boundary = UserSpecifiedCollectionOfScalar( dirichlet_boundary )
        dirichlet_val = er.getUserSpecifiedCollectionOfScalar(param, "dirichlet_val", dirichlet_boundary.size());
        // ============= Generated code ends here ================
    }
};

class ResidualComputer : public ResidualComputerInterface
{
public:
    /// Initialization.
    ResidualComputer(const EquelleRuntimeCPU& er, const UserParameters& up)
        : er_(er), up_(up)
    {
    }

    // Compute the (possibly nonlinear) residual with derivative information.
    // This is the most important generated function.
    CollOfScalarsAD compute(const CollOfScalarsAD& u) const
    {
        // ============= Generated code starts here ================

        // --------------------------------------------------------------------------------
        // vol = Volume( AllCells() )    # Deduced type: Scalar On AllCells()
        // --------------------------------------------------------------------------------
        const CollOfScalars vol = er_.norm( er_.allCells() );

        // --------------------------------------------------------------------------------
	// interior_faces = InteriorFaces()       # Deduced type:  Collection Of Face Subset Of AllFaces()
	// first = FirstCell(interior_faces)      # Deduced type:  Collection Of Cell On interior_faces
	//                                        # Equivalent to: Collection Of Cell On InteriorFaces()
	// second = SecondCell(interior_faces)    # Deduced type:  Same as for 'first'.
        // --------------------------------------------------------------------------------
        const CollOfFaces interior_faces = er_.interiorFaces();
        const CollOfCells first = er_.firstCell( interior_faces );
        const CollOfCells second = er_.secondCell( interior_faces );

        // --------------------------------------------------------------------------------
        // trans : Collection Of Scalar On interior_faces = k * Area(interior_faces) / Length(Centroid(first) - Centroid(second))
        //    # Deduced (and declared) type: Collection Of Scalar On interior_faces
        // --------------------------------------------------------------------------------
        // trans is a CollOfScalars and not a CollOfScalarsAD since it does not depend on u.
        const CollOfScalars trans = up_.k * er_.norm(interior_faces) / er_.norm(er_.centroid(first) - er_.centroid(second));

        // --------------------------------------------------------------------------------
        // fluxes : Collection Of Scalar On interior_faces = - trans * Gradient(u)
        //    # Deduced (and declared) type: Scalar On interior_faces
        // --------------------------------------------------------------------------------
        // fluxes is a CollOfScalarsAD since it depends on u.
        const CollOfScalarsAD fluxes = trans * (er_.negGradient(u));

        // --------------------------------------------------------------------------------
        // residual : Collection Of Scalar On AllCells() = u - u0 + (dt / vol) * Divergence(fluxes)
        //    # Deduced (and declared) type: Scalar On AllCells()
        // --------------------------------------------------------------------------------
        // residual is a CollOfScalarsAD since it depends on u and fluxes.
        const CollOfScalarsAD residual = u - up_.u0 + (up_.dt / vol) * (er_.divergence(fluxes));

        // ============= Hopefully generated code ends here ================

        return residual;
    }

private:
    const EquelleRuntimeCPU& er_;
    const UserParameters& up_;
};

int main(int argc, char** argv)
{
    // Get user parameters.
    Opm::parameter::ParameterGroup param(argc, argv, false);

    // Create the Equelle runtime.
    EquelleRuntimeCPU er(param);

    // ============= Generated code starts here ================

    // --------------------------------------------------------------------------------
    // k : Scalar = UserSpecifiedScalarWithDefault(0.3) # Heat diffusion constant.
    // dt : Scalar = UserSpecifiedScalarWithDefault(0.5) # Time step length.
    // u0 : Collection Of Scalar On AllCells() = UserSpecifiedCollectionOfScalar( AllCells() )
    // dirichlet_boundary : Collection Of Face On BoundaryFaces() = UserSpecifiedCollectionOfFace( BoundaryFaces() )
    // dirichlet_val : Collection Of Scalar On dirichlet_boundary = UserSpecifiedCollectionOfScalar( dirichlet_boundary )
    // --------------------------------------------------------------------------------
    const auto k = param.getDefault("k", 0.3);
    const auto dt = param.getDefault("dt", 0.5);
    const auto u0 = er.getUserSpecifiedCollectionOfScalar(param, "u0", er.allCells().size());
    const auto dirichlet_boundary = er.getUserSpecifiedCollectionOfFaceSubsetOf(param, "dirichlet_boundary", er.boundaryFaces());
    const auto dirichlet_val = er.getUserSpecifiedCollectionOfScalar(param, "dirichlet_val", dirichlet_boundary.size());

    // --------------------------------------------------------------------------------
    // # Compute interior transmissibilities.
    // vol = |AllCells()|                                         # Deduced type:  Collection Of Scalar On AllCells()
    // interior_faces = InteriorFaces()                           # Deduced type:  Collection Of Face
    // first = FirstCell(interior_faces)                          # Deduced type:  Collection Of Cell On interior_faces
    // 							          # Equivalent to: Collection Of Cell On InteriorFaces()
    // second = SecondCell(interior_faces)                        # Deduced type:  Same as for 'first'.
    // itrans : Collection Of Scalar On interior_faces = k * |interior_faces| / |Centroid(first) - Centroid(second)|
    // --------------------------------------------------------------------------------
    const auto vol = er.norm(er.allCells());
    const auto interior_faces = er.interiorFaces();
    const auto first = er.firstCell(interior_faces);
    const auto second = er.secondCell(interior_faces);
    const auto itrans = k * er.norm(interior_faces) / er.norm(er.centroid(first) - er.centroid(second));

    // --------------------------------------------------------------------------------
    // # Compute boundary transmissibilities.
    // bf = BoundaryFaces()
    // bf_cells = IsEmpty(FirstCell(bf)) ? SecondCell(bf) : FirstCell(bf)
    // bf_sign = IsEmpty(FirstCell(bf))) ? (-1 On bf_cells) : (1 On bf_cells)
    // btrans = k * |bf| / |Centroid(bf) - Centroid(bf_cells)|
    // --------------------------------------------------------------------------------
    const auto bf = er.boundaryFaces();
    const auto bf_cells = er.trinaryIf(er.isEmpty(er.firstCell(bf)), er.secondCell(bf), er.firstCell(bf));
    const auto bf_sign = er.trinaryIf(er.isEmpty(er.firstCell(bf)), er.operatorOn(double(-1), bf_cells), er.operatorOn(double(1), bf_cells));
    const auto btrans = k * er.norm(bf) / er.norm(er.centroid(bf) - er.centroid(bf_cells));

    // --------------------------------------------------------------------------------
    // # Compute quantities needed for boundary conditions.
    // dir_sign = bf_sign On dirichlet_boundary
    // --------------------------------------------------------------------------------
    const auto dir_sign = er.operatorOn(bf_sign, bf, dirichlet_boundary);

    // --------------------------------------------------------------------------------
    // # Compute flux for interior faces.
    // computeInteriorFlux : Function(u : Collection Of Scalar On AllCells()) -> Collection Of Scalar On InteriorFaces()
    // computeInteriorFlux(u) = {
    //     return -itrans * Gradient(u)
    // }
    // --------------------------------------------------------------------------------
    auto computeInteriorFlux = [&](const CollOfScalars u) -> CollOfScalars {
        return -itrans * er.gradient(u);
    };
    auto computeInteriorFluxAD = [&](const CollOfScalarsAD u) -> CollOfScalarsAD {
        return -itrans * er.gradient(u);
    };

    // --------------------------------------------------------------------------------
    // # Compute flux for boundary faces.
    // computeBoundaryFlux : Function(u : Collection Of Scalar On AllCells()) -> Collection Of Scalar On BoundaryFaces()
    // computeBoundaryFlux(u) = {
    //     # Compute flux at Dirichlet boundaries.
    //     dir_fluxes = btrans * dir_sign * (u_dirbdycells - dirichlet_val)
    //     # Extending with zero away from Dirichlet boundaries (i.e. assuming no-flow elsewhere).
    //     return dir_fluxes On BoundaryFaces()
    // }
    // --------------------------------------------------------------------------------
    auto computeBoundaryFlux = [&](const CollOfScalars u) -> CollOfScalars {
        const auto u_dirbdycells = er.operatorOn(u, er.allCells(), er.operatorOn(bf_cells, bf, dirichlet_boundary));
        const CollOfScalars dir_fluxes = dir_sign * (u_dirbdycells - dirichlet_val);
        return er.operatorOn(dir_fluxes, dirichlet_boundary, er.boundaryFaces());
    };
    auto computeBoundaryFluxAD = [&](const CollOfScalarsAD u) -> CollOfScalarsAD {
        const auto u_dirbdycells = er.operatorOn(u, er.allCells(), er.operatorOn(bf_cells, bf, dirichlet_boundary));
        const CollOfScalarsAD dir_fluxes = btrans * dir_sign * (u_dirbdycells - dirichlet_val);
        return er.operatorOn(dir_fluxes, dirichlet_boundary, er.boundaryFaces());
    };

    // --------------------------------------------------------------------------------
    // # Compute the residual for the heat equation.
    // computeResidual : Function(u : Collection Of Scalar On AllCells()) -> Collection Of Scalar On AllCells()
    // computeResidual(u) = {
    //     ifluxes = computeInteriorFlux(u)
    //     bfluxes = computeBoundaryFlux(u)
    //     # Extend both ifluxes and bfluxes to AllFaces() and add to get all fluxes.
    //     fluxes = (ifluxes On AllFaces()) + (bfluxes On AllFaces())
    //     # Deduced type: Collection Of Scalar On AllCells()
    //     residual = u - u0 + (dt / vol) * Divergence(fluxes)
    //     return residual
    // }
    // --------------------------------------------------------------------------------
    auto computeResidual = [&](const CollOfScalars u) -> CollOfScalars {
        const auto ifluxes = computeInteriorFlux(u);
        const auto bfluxes = computeBoundaryFlux(u);
        const auto fluxes = er.operatorOn(ifluxes, er.interiorFaces(), er.allFaces()) + er.operatorOn(bfluxes, er.boundaryFaces(), er.allFaces());
        const auto residual = u - u0 + (dt / vol) * er.divergence(fluxes);
        return residual;
    };
    auto computeResidualAD = [&](const CollOfScalarsAD u) -> CollOfScalarsAD {
        const auto ifluxes = computeInteriorFluxAD(u);
        const auto bfluxes = computeBoundaryFluxAD(u);
        const auto fluxes = er.operatorOn(ifluxes, er.interiorFaces(), er.allFaces()) + er.operatorOn(bfluxes, er.boundaryFaces(), er.allFaces());
        const auto residual = u - u0 + (dt / vol) * er.divergence(fluxes);
        return residual;
    };

    // --------------------------------------------------------------------------------
    // explicitu = u0 + computeResidual(u0)
    // u = NewtonSolve(computeResidual, u0)
    // --------------------------------------------------------------------------------
    const auto explicitu = u0 + computeResidual(u0);
    const auto u = er.newtonSolve(computeResidualAD, u0);

    // --------------------------------------------------------------------------------
    // Output(u)
    // Output(fluxes)
    // --------------------------------------------------------------------------------
    // Not handling output of fluxes currently, since they are not in scope here.
    er.output("Explicit u is equal to: ", explicitu);
    er.output("Implicit u is equal to: ", u);

    // ============= Generated code ends here ================

    return 0;
}

<commit_msg>Removed unused code in example.<commit_after>/*
  Copyright 2013 SINTEF ICT, Applied Mathematics.
*/

#include <opm/core/utility/parameters/ParameterGroup.hpp>
#include <opm/core/linalg/LinearSolverFactory.hpp>
#include <opm/core/utility/ErrorMacros.hpp>
#include <opm/autodiff/AutoDiffBlock.hpp>
#include <opm/autodiff/AutoDiffHelpers.hpp>
#include <opm/core/grid.h>
#include <opm/core/grid/GridManager.hpp>
#include <algorithm>
#include <iterator>
#include <iostream>
#include <cmath>

#include "EquelleRuntimeCPU.hpp"

int main(int argc, char** argv)
{
    // Get user parameters.
    Opm::parameter::ParameterGroup param(argc, argv, false);

    // Create the Equelle runtime.
    EquelleRuntimeCPU er(param);

    // ============= Generated code starts here ================

    // --------------------------------------------------------------------------------
    // k : Scalar = UserSpecifiedScalarWithDefault(0.3) # Heat diffusion constant.
    // dt : Scalar = UserSpecifiedScalarWithDefault(0.5) # Time step length.
    // u0 : Collection Of Scalar On AllCells() = UserSpecifiedCollectionOfScalar( AllCells() )
    // dirichlet_boundary : Collection Of Face On BoundaryFaces() = UserSpecifiedCollectionOfFace( BoundaryFaces() )
    // dirichlet_val : Collection Of Scalar On dirichlet_boundary = UserSpecifiedCollectionOfScalar( dirichlet_boundary )
    // --------------------------------------------------------------------------------
    const auto k = param.getDefault("k", 0.3);
    const auto dt = param.getDefault("dt", 0.5);
    const auto u0 = er.getUserSpecifiedCollectionOfScalar(param, "u0", er.allCells().size());
    const auto dirichlet_boundary = er.getUserSpecifiedCollectionOfFaceSubsetOf(param, "dirichlet_boundary", er.boundaryFaces());
    const auto dirichlet_val = er.getUserSpecifiedCollectionOfScalar(param, "dirichlet_val", dirichlet_boundary.size());

    // --------------------------------------------------------------------------------
    // # Compute interior transmissibilities.
    // vol = |AllCells()|                                         # Deduced type:  Collection Of Scalar On AllCells()
    // interior_faces = InteriorFaces()                           # Deduced type:  Collection Of Face
    // first = FirstCell(interior_faces)                          # Deduced type:  Collection Of Cell On interior_faces
    // 							          # Equivalent to: Collection Of Cell On InteriorFaces()
    // second = SecondCell(interior_faces)                        # Deduced type:  Same as for 'first'.
    // itrans : Collection Of Scalar On interior_faces = k * |interior_faces| / |Centroid(first) - Centroid(second)|
    // --------------------------------------------------------------------------------
    const auto vol = er.norm(er.allCells());
    const auto interior_faces = er.interiorFaces();
    const auto first = er.firstCell(interior_faces);
    const auto second = er.secondCell(interior_faces);
    const auto itrans = k * er.norm(interior_faces) / er.norm(er.centroid(first) - er.centroid(second));

    // --------------------------------------------------------------------------------
    // # Compute boundary transmissibilities.
    // bf = BoundaryFaces()
    // bf_cells = IsEmpty(FirstCell(bf)) ? SecondCell(bf) : FirstCell(bf)
    // bf_sign = IsEmpty(FirstCell(bf))) ? (-1 On bf_cells) : (1 On bf_cells)
    // btrans = k * |bf| / |Centroid(bf) - Centroid(bf_cells)|
    // --------------------------------------------------------------------------------
    const auto bf = er.boundaryFaces();
    const auto bf_cells = er.trinaryIf(er.isEmpty(er.firstCell(bf)), er.secondCell(bf), er.firstCell(bf));
    const auto bf_sign = er.trinaryIf(er.isEmpty(er.firstCell(bf)), er.operatorOn(double(-1), bf_cells), er.operatorOn(double(1), bf_cells));
    const auto btrans = k * er.norm(bf) / er.norm(er.centroid(bf) - er.centroid(bf_cells));

    // --------------------------------------------------------------------------------
    // # Compute quantities needed for boundary conditions.
    // dir_sign = bf_sign On dirichlet_boundary
    // --------------------------------------------------------------------------------
    const auto dir_sign = er.operatorOn(bf_sign, bf, dirichlet_boundary);

    // --------------------------------------------------------------------------------
    // # Compute flux for interior faces.
    // computeInteriorFlux : Function(u : Collection Of Scalar On AllCells()) -> Collection Of Scalar On InteriorFaces()
    // computeInteriorFlux(u) = {
    //     return -itrans * Gradient(u)
    // }
    // --------------------------------------------------------------------------------
    auto computeInteriorFlux = [&](const CollOfScalars u) -> CollOfScalars {
        return -itrans * er.gradient(u);
    };
    auto computeInteriorFluxAD = [&](const CollOfScalarsAD u) -> CollOfScalarsAD {
        return -itrans * er.gradient(u);
    };

    // --------------------------------------------------------------------------------
    // # Compute flux for boundary faces.
    // computeBoundaryFlux : Function(u : Collection Of Scalar On AllCells()) -> Collection Of Scalar On BoundaryFaces()
    // computeBoundaryFlux(u) = {
    //     # Compute flux at Dirichlet boundaries.
    //     dir_fluxes = btrans * dir_sign * (u_dirbdycells - dirichlet_val)
    //     # Extending with zero away from Dirichlet boundaries (i.e. assuming no-flow elsewhere).
    //     return dir_fluxes On BoundaryFaces()
    // }
    // --------------------------------------------------------------------------------
    auto computeBoundaryFlux = [&](const CollOfScalars u) -> CollOfScalars {
        const auto u_dirbdycells = er.operatorOn(u, er.allCells(), er.operatorOn(bf_cells, bf, dirichlet_boundary));
        const CollOfScalars dir_fluxes = dir_sign * (u_dirbdycells - dirichlet_val);
        return er.operatorOn(dir_fluxes, dirichlet_boundary, er.boundaryFaces());
    };
    auto computeBoundaryFluxAD = [&](const CollOfScalarsAD u) -> CollOfScalarsAD {
        const auto u_dirbdycells = er.operatorOn(u, er.allCells(), er.operatorOn(bf_cells, bf, dirichlet_boundary));
        const CollOfScalarsAD dir_fluxes = btrans * dir_sign * (u_dirbdycells - dirichlet_val);
        return er.operatorOn(dir_fluxes, dirichlet_boundary, er.boundaryFaces());
    };

    // --------------------------------------------------------------------------------
    // # Compute the residual for the heat equation.
    // computeResidual : Function(u : Collection Of Scalar On AllCells()) -> Collection Of Scalar On AllCells()
    // computeResidual(u) = {
    //     ifluxes = computeInteriorFlux(u)
    //     bfluxes = computeBoundaryFlux(u)
    //     # Extend both ifluxes and bfluxes to AllFaces() and add to get all fluxes.
    //     fluxes = (ifluxes On AllFaces()) + (bfluxes On AllFaces())
    //     # Deduced type: Collection Of Scalar On AllCells()
    //     residual = u - u0 + (dt / vol) * Divergence(fluxes)
    //     return residual
    // }
    // --------------------------------------------------------------------------------
    auto computeResidual = [&](const CollOfScalars u) -> CollOfScalars {
        const auto ifluxes = computeInteriorFlux(u);
        const auto bfluxes = computeBoundaryFlux(u);
        const auto fluxes = er.operatorOn(ifluxes, er.interiorFaces(), er.allFaces()) + er.operatorOn(bfluxes, er.boundaryFaces(), er.allFaces());
        const auto residual = u - u0 + (dt / vol) * er.divergence(fluxes);
        return residual;
    };
    auto computeResidualAD = [&](const CollOfScalarsAD u) -> CollOfScalarsAD {
        const auto ifluxes = computeInteriorFluxAD(u);
        const auto bfluxes = computeBoundaryFluxAD(u);
        const auto fluxes = er.operatorOn(ifluxes, er.interiorFaces(), er.allFaces()) + er.operatorOn(bfluxes, er.boundaryFaces(), er.allFaces());
        const auto residual = u - u0 + (dt / vol) * er.divergence(fluxes);
        return residual;
    };

    // --------------------------------------------------------------------------------
    // explicitu = u0 + computeResidual(u0)
    // u = NewtonSolve(computeResidual, u0)
    // --------------------------------------------------------------------------------
    const auto explicitu = u0 + computeResidual(u0);
    const auto u = er.newtonSolve(computeResidualAD, u0);

    // --------------------------------------------------------------------------------
    // Output(u)
    // Output(fluxes)
    // --------------------------------------------------------------------------------
    // Not handling output of fluxes currently, since they are not in scope here.
    er.output("Explicit u is equal to: ", explicitu);
    er.output("Implicit u is equal to: ", u);

    // ============= Generated code ends here ================

    return 0;
}

<|endoftext|>


<commit_before>#include "LIBSPU.H"
#include "LIBETC.H"
#include <stdio.h>
#include "EMULATOR.H"
#include "LIBAPI.H"

#include <string.h>

#define SPU_CENTERNOTE (49152)

short _spu_voice_centerNote[24] =
{
	SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE,
	SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE,
	SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE
};

SpuCommonAttr dword_424;//Might be wrong struct, need to check
int _spu_isCalled = 0;
int _spu_FiDMA = 0;///@TODO decl as extern find initial value
int _spu_EVdma = 0;
int _spu_rev_flag = 0;
int _spu_rev_reserve_wa = 0;
int _spu_rev_offsetaddr = 0;
int _spu_rev_startaddr = 0;
int _spu_AllocBlockNum = 0;
int _spu_AllocLastNum = 0;
int _spu_memList = 0;
int _spu_trans_mode = 0;
int _spu_transMode = 0;
int _spu_keystat = 0;
int _spu_RQmask = 0;
int _spu_RQvoice = 0;
int _spu_env = 0;
short* _spu_RXX = (short*)0x1F801C00;
int _spu_mem_mode_plus = 3;

unsigned long SpuWrite(unsigned char * addr, unsigned long size)
{
	//eprintf("SPU WRITE size=%d\n", size);
	//memcpy(spu_buf, addr, size);
	//spu_b_size = size;
	UNIMPLEMENTED();
	return 0;
}

long SpuSetTransferMode(long mode)
{
	long mode_fix = mode == 0 ? 0 : 1;

	//trans_mode = mode;
	//transMode = mode_fix;

	return mode_fix;
}

unsigned long SpuSetTransferStartAddr(unsigned long addr)
{
	UNIMPLEMENTED();
	return 0;
}

long SpuIsTransferCompleted(long flag)
{
	UNIMPLEMENTED();
	return 0;
}

void _SpuDataCallback(int a0)
{
	UNIMPLEMENTED();
}

void SpuStart()//(F)
{
	long event = 0;

	if (_spu_isCalled == 0)
	{
		_spu_isCalled = 1;
		EnterCriticalSection();
		_SpuDataCallback(_spu_FiDMA);
		event = OpenEvent(HwSPU, EvSpCOMP, EvMdNOINTR, NULL);
		_spu_EVdma = event;
		EnableEvent(event);
		ExitCriticalSection();
	}
	//loc_348
}

void _spu_init(int a0)
{
	UNIMPLEMENTED();
}

void _spu_FsetRXX(int a0, int a1, int a2)//(F)
{
	if (a2 == 0)
	{
		_spu_RXX[a0] = a1;
	}
	else
	{
		_spu_RXX[a0] = a1 >> _spu_mem_mode_plus;
	}
}

void _SpuInit(int a0)
{
	ResetCallback();
	_spu_init(a0);

	//s0 = a0
	if (a0 == 0)
	{
		for (int i = 0; i < sizeof(_spu_voice_centerNote) / sizeof(short); i++)
		{
			_spu_voice_centerNote[i] = SPU_CENTERNOTE;
		}
	}
	//loc_240
	SpuStart();

	_spu_rev_flag = 0;
	_spu_rev_reserve_wa = 0;
	dword_424.mask = 0;
	dword_424.mvol.left = 0;
	dword_424.mvol.right = 0;
	dword_424.mvolmode.left = 0;
	dword_424.mvolmode.right = 0;
	dword_424.mvolx.left = 0;
	dword_424.mvolx.right = 0;
	_spu_rev_offsetaddr = _spu_rev_startaddr;
	_spu_FsetRXX(209, _spu_rev_startaddr, 0);
	_spu_AllocBlockNum = 0;
	_spu_AllocLastNum = 0;
	_spu_memList = 0;
	_spu_trans_mode = 0;
	_spu_transMode = 0;
	_spu_keystat = 0;
	_spu_RQmask = 0;
	_spu_RQvoice = 0;
	_spu_env = 0;
}

void SpuInit(void)
{
	_SpuInit(0);
}

long SpuSetReverb(long on_off)
{
	UNIMPLEMENTED();
	return 0;
}

unsigned long SpuSetReverbVoice(long on_off, unsigned long voice_bit)
{
	UNIMPLEMENTED();
	return 0;
}

void SpuSetCommonAttr(SpuCommonAttr * attr)
{
	UNIMPLEMENTED();
}

long SpuInitMalloc(long num, char * top)
{
	if (num > 0)
	{
		///memList = top;
		//AllocLastNum = 0;
		//AllocBlockNum = num;
		//*((int*)memList) = mem_mode_plus = 0x4000 | 0x1010;
		//*((int*)memList + 1) = 0x4000;
	}

	return num;
}

long SpuMalloc(long size)
{
	return 0/*(long)(uintptr_t)malloc(size)*/;
}

long SpuMallocWithStartAddr(unsigned long addr, long size)
{
	UNIMPLEMENTED();
	return 0;
}

void SpuFree(unsigned long addr)
{
	/*free((void*)(uintptr_t)addr)*/;
}

void SpuSetCommonMasterVolume(short mvol_left, short mvol_right)// (F)
{
	//MasterVolume.VolumeLeft.Raw = mvol_left;
	//MasterVolume.VolumeRight.Raw = mvol_right;
}

long SpuSetReverbModeType(long mode)
{
	UNIMPLEMENTED();
	return 0;
}

void SpuSetReverbModeDepth(short depth_left, short depth_right)
{
	UNIMPLEMENTED();
}
<commit_msg>[Emu]: Implement SpuInitMalloc.<commit_after>#include "LIBSPU.H"
#include "LIBETC.H"
#include <stdio.h>
#include "EMULATOR.H"
#include "LIBAPI.H"

#include <string.h>

#define SPU_CENTERNOTE (49152)

short _spu_voice_centerNote[24] =
{
	SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE,
	SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE,
	SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE, SPU_CENTERNOTE
};

SpuCommonAttr dword_424;//Might be wrong struct, need to check
int _spu_isCalled = 0;
int _spu_FiDMA = 0;///@TODO decl as extern find initial value
int _spu_EVdma = 0;
int _spu_rev_flag = 0;
int _spu_rev_reserve_wa = 0;
int _spu_rev_offsetaddr = 0;
int _spu_rev_startaddr = 0;
int _spu_AllocBlockNum = 0;
int _spu_AllocLastNum = 0;
int _spu_memList = 0;
int _spu_trans_mode = 0;
int _spu_transMode = 0;
int _spu_keystat = 0;
int _spu_RQmask = 0;
int _spu_RQvoice = 0;
int _spu_env = 0;
short* _spu_RXX = (short*)0x1F801C00;
int _spu_mem_mode_plus = 3;

unsigned long SpuWrite(unsigned char * addr, unsigned long size)
{
	//eprintf("SPU WRITE size=%d\n", size);
	//memcpy(spu_buf, addr, size);
	//spu_b_size = size;
	UNIMPLEMENTED();
	return 0;
}

long SpuSetTransferMode(long mode)
{
	long mode_fix = mode == 0 ? 0 : 1;

	//trans_mode = mode;
	//transMode = mode_fix;

	return mode_fix;
}

unsigned long SpuSetTransferStartAddr(unsigned long addr)
{
	UNIMPLEMENTED();
	return 0;
}

long SpuIsTransferCompleted(long flag)
{
	UNIMPLEMENTED();
	return 0;
}

void _SpuDataCallback(int a0)
{
	UNIMPLEMENTED();
}

void SpuStart()//(F)
{
	long event = 0;

	if (_spu_isCalled == 0)
	{
		_spu_isCalled = 1;
		EnterCriticalSection();
		_SpuDataCallback(_spu_FiDMA);
		event = OpenEvent(HwSPU, EvSpCOMP, EvMdNOINTR, NULL);
		_spu_EVdma = event;
		EnableEvent(event);
		ExitCriticalSection();
	}
	//loc_348
}

void _spu_init(int a0)
{
	UNIMPLEMENTED();
}

void _spu_FsetRXX(int a0, int a1, int a2)//(F)
{
	if (a2 == 0)
	{
		_spu_RXX[a0] = a1;
	}
	else
	{
		_spu_RXX[a0] = a1 >> _spu_mem_mode_plus;
	}
}

void _SpuInit(int a0)
{
	ResetCallback();
	_spu_init(a0);

	if (a0 == 0)
	{
		for (int i = 0; i < sizeof(_spu_voice_centerNote) / sizeof(short); i++)
		{
			_spu_voice_centerNote[i] = SPU_CENTERNOTE;
		}
	}
	//loc_240
	SpuStart();

	_spu_rev_flag = 0;
	_spu_rev_reserve_wa = 0;
	dword_424.mask = 0;
	dword_424.mvol.left = 0;
	dword_424.mvol.right = 0;
	dword_424.mvolmode.left = 0;
	dword_424.mvolmode.right = 0;
	dword_424.mvolx.left = 0;
	dword_424.mvolx.right = 0;
	_spu_rev_offsetaddr = _spu_rev_startaddr;
	_spu_FsetRXX(209, _spu_rev_startaddr, 0);
	_spu_AllocBlockNum = 0;
	_spu_AllocLastNum = 0;
	_spu_memList = 0;
	_spu_trans_mode = 0;
	_spu_transMode = 0;
	_spu_keystat = 0;
	_spu_RQmask = 0;
	_spu_RQvoice = 0;
	_spu_env = 0;
}

void SpuInit(void)
{
	_SpuInit(0);
}

long SpuSetReverb(long on_off)
{
	UNIMPLEMENTED();
	return 0;
}

unsigned long SpuSetReverbVoice(long on_off, unsigned long voice_bit)
{
	UNIMPLEMENTED();
	return 0;
}

void SpuSetCommonAttr(SpuCommonAttr* attr)
{
	UNIMPLEMENTED();
}

long SpuInitMalloc(long num, char* top)//(F)
{
	if (num > 0)
	{
		//loc_214
		((int*)top)[0] = 0x40001010;
		_spu_memList = (uintptr_t)top;
		_spu_AllocLastNum = 0;
		_spu_AllocBlockNum = num;
		((int*)top)[1] = (0x10000000 << _spu_mem_mode_plus) - 0x1010;
	}

	return num;
}

long SpuMalloc(long size)
{
	return 0/*(long)(uintptr_t)malloc(size)*/;
}

long SpuMallocWithStartAddr(unsigned long addr, long size)
{
	UNIMPLEMENTED();
	return 0;
}

void SpuFree(unsigned long addr)
{
	/*free((void*)(uintptr_t)addr)*/;
}

void SpuSetCommonMasterVolume(short mvol_left, short mvol_right)// (F)
{
	//MasterVolume.VolumeLeft.Raw = mvol_left;
	//MasterVolume.VolumeRight.Raw = mvol_right;
}

long SpuSetReverbModeType(long mode)
{
	UNIMPLEMENTED();
	return 0;
}

void SpuSetReverbModeDepth(short depth_left, short depth_right)
{
	UNIMPLEMENTED();
}
<|endoftext|>


<commit_before>/*
 * EepromManager.cpp
 *
 * Created: 23/04/2013 03:15:44
 *  Author: mat
 */

#include "brewpi_avr.h"
#include <stddef.h>

#include "EepromManager.h"
#include "TempControl.h"
#include "EepromFormat.h"
#include "PiLink.h"

EepromManager eepromManager;
EepromAccess eepromAccess;

#define pointerOffset(x) offsetof(EepromFormat, x)

EepromManager::EepromManager()
{
	eepromSizeCheck();
}

bool EepromManager::hasSettings()
{
	uint8_t version = eepromAccess.readByte(pointerOffset(version));
	return (version==EEPROM_FORMAT_VERSION);
}

void EepromManager::resetEeprom()
{
	tempControl.loadDefaultConstants();
	tempControl.loadDefaultSettings();

	tempControl.cs.mode = MODE_BEER_CONSTANT;

	for (uint8_t c=0; c<EepromFormat::MAX_CHAMBERS; c++) {
		eptr_t pv = pointerOffset(chambers)+(c*sizeof(ChamberBlock)) ;
		tempControl.storeConstants(pv+offsetof(ChamberBlock, chamberSettings.cc));
		pv += offsetof(ChamberBlock, beer)+offsetof(BeerBlock, cs);
		for (uint8_t b=0; b<ChamberBlock::MAX_BEERS; b++) {
			tempControl.storeSettings(pv);
			pv += sizeof(BeerBlock);		// advance to next beer
		}
	}

	uint8_t count = saveDefaultDevices();

	for (uint16_t offset=pointerOffset(devices)+(sizeof(DeviceConfig)*count); offset<EepromFormat::MAX_EEPROM_SIZE; offset++)
		eepromAccess.writeByte(offset, 0);

	eepromAccess.writeByte(0, EEPROM_FORMAT_VERSION);
}

uint8_t EepromManager::saveDefaultDevices()
{
#if 1
	DeviceConfig config;
	clear((uint8_t*)&config, sizeof(config));

#if BREWPI_STATIC_CONFIG==BREWPI_SHIELD_REV_A
	// single-chamber single beer config from original shield

	config.chamber = 1;			// all devices in chamber 1
	config.hw.invert = 1;		// all pin devices inverted

	config.deviceHardware = DEVICE_HARDWARE_PIN;

	config.deviceFunction = DEVICE_CHAMBER_DOOR;
	config.hw.pinNr = doorPin;
	eepromManager.storeDevice(config, 0);

	config.deviceFunction = DEVICE_CHAMBER_HEAT;
	config.hw.pinNr = heatingPin;
	eepromManager.storeDevice(config, 1);

	config.deviceFunction = DEVICE_CHAMBER_COOL;
	config.hw.pinNr = heatingPin;
	eepromManager.storeDevice(config, 2);

	config.deviceHardware = DEVICE_HARDWARE_ONEWIRE_TEMP;
	config.hw.pinNr = fridgeSensorPin;
	config.deviceFunction = DEVICE_CHAMBER_TEMP;
	eepromManager.storeDevice(config, 3);

	config.beer = 1;
	config.hw.pinNr = beerSensorPin;
	config.deviceFunction = DEVICE_BEER_TEMP;
	eepromManager.storeDevice(config, 3);

	return 5;
#endif

#if BREWPI_STATIC_CONFIG==BREWPI_SHIELD_REV_C
	// the only component that's not dynamic is the door
	return 0;
#endif

#else
	return 0;
#endif
}

#define arraySize(x) (sizeof(x)/sizeof(x[0]))

bool EepromManager::applySettings()
{
	if (!hasSettings())
		return false;

	// start from a clean state
	deviceManager.setupUnconfiguredDevices();

	DEBUG_MSG(PSTR("Applying settings"));

	// load the one chamber and one beer for now
	eptr_t pv = pointerOffset(chambers);
	tempControl.loadConstants(pv+offsetof(ChamberBlock, chamberSettings.cc));
	tempControl.loadSettings(pv+offsetof(ChamberBlock, beer[0].cs));

	DEBUG_MSG(PSTR("Applied settings"));

	DeviceConfig deviceConfig;
	for (uint8_t index = 0; fetchDevice(deviceConfig, index); index++)
	{
		if (deviceConfig.deviceFunction!=0xFF && deviceManager.isDeviceValid(deviceConfig, deviceConfig, index))
			deviceManager.installDevice(deviceConfig);
		else {
			clear((uint8_t*)&deviceConfig, sizeof(deviceConfig));
			eepromManager.storeDevice(deviceConfig, index);
		}
	}

	return true;
}

void EepromManager::storeTempConstantsAndSettings()
{
	uint8_t chamber = 0;
	eptr_t pv = pointerOffset(chambers);
	pv += sizeof(ChamberBlock)*chamber;
	tempControl.storeConstants(pv+offsetof(ChamberBlock, chamberSettings.cc));

	storeTempSettings();
}

void EepromManager::storeTempSettings()
{
	uint8_t chamber = 0;
	eptr_t pv = pointerOffset(chambers);
	pv += sizeof(ChamberBlock)*chamber;
	// for now assume just one beer.
	tempControl.storeSettings(pv+offsetof(ChamberBlock, beer[0].cs));
}

bool EepromManager::fetchDevice(DeviceConfig& config, uint8_t deviceIndex)
{
	bool ok = (hasSettings() && deviceIndex<EepromFormat::MAX_DEVICES);
	if (ok)
		eepromAccess.readBlock(&config, pointerOffset(devices)+sizeof(DeviceConfig)*deviceIndex, sizeof(DeviceConfig));
	return ok;
}

bool EepromManager::storeDevice(const DeviceConfig& config, uint8_t deviceIndex)
{
	bool ok = (hasSettings() && deviceIndex<EepromFormat::MAX_DEVICES);
	if (ok)
		eepromAccess.writeBlock(pointerOffset(devices)+sizeof(DeviceConfig)*deviceIndex, &config, sizeof(DeviceConfig));
	return ok;
}

void fill(int8_t* p, uint8_t size) {
	while (size-->0) *p++ = -1;
}
void clear(uint8_t* p, uint8_t size) {
	while (size-->0) *p++ = 0;
}
<commit_msg>fix for revA fridge sensor not being initialized<commit_after>/*
 * EepromManager.cpp
 *
 * Created: 23/04/2013 03:15:44
 *  Author: mat
 */

#include "brewpi_avr.h"
#include <stddef.h>

#include "EepromManager.h"
#include "TempControl.h"
#include "EepromFormat.h"
#include "PiLink.h"

EepromManager eepromManager;
EepromAccess eepromAccess;

#define pointerOffset(x) offsetof(EepromFormat, x)

EepromManager::EepromManager()
{
	eepromSizeCheck();
}

bool EepromManager::hasSettings()
{
	uint8_t version = eepromAccess.readByte(pointerOffset(version));
	return (version==EEPROM_FORMAT_VERSION);
}

void EepromManager::resetEeprom()
{
	tempControl.loadDefaultConstants();
	tempControl.loadDefaultSettings();

	tempControl.cs.mode = MODE_BEER_CONSTANT;

	for (uint8_t c=0; c<EepromFormat::MAX_CHAMBERS; c++) {
		eptr_t pv = pointerOffset(chambers)+(c*sizeof(ChamberBlock)) ;
		tempControl.storeConstants(pv+offsetof(ChamberBlock, chamberSettings.cc));
		pv += offsetof(ChamberBlock, beer)+offsetof(BeerBlock, cs);
		for (uint8_t b=0; b<ChamberBlock::MAX_BEERS; b++) {
			tempControl.storeSettings(pv);
			pv += sizeof(BeerBlock);		// advance to next beer
		}
	}

	uint8_t count = saveDefaultDevices();

	for (uint16_t offset=pointerOffset(devices)+(sizeof(DeviceConfig)*count); offset<EepromFormat::MAX_EEPROM_SIZE; offset++)
		eepromAccess.writeByte(offset, 0);

	eepromAccess.writeByte(0, EEPROM_FORMAT_VERSION);
}

uint8_t EepromManager::saveDefaultDevices()
{
#if 1
	DeviceConfig config;
	clear((uint8_t*)&config, sizeof(config));

#if BREWPI_STATIC_CONFIG==BREWPI_SHIELD_REV_A
	// single-chamber single beer config from original shield

	config.chamber = 1;			// all devices in chamber 1
	config.hw.invert = 1;		// all pin devices inverted

	config.deviceHardware = DEVICE_HARDWARE_PIN;

	config.deviceFunction = DEVICE_CHAMBER_DOOR;
	config.hw.pinNr = doorPin;
	eepromManager.storeDevice(config, 0);

	config.deviceFunction = DEVICE_CHAMBER_HEAT;
	config.hw.pinNr = heatingPin;
	eepromManager.storeDevice(config, 1);

	config.deviceFunction = DEVICE_CHAMBER_COOL;
	config.hw.pinNr = heatingPin;
	eepromManager.storeDevice(config, 2);

	config.deviceHardware = DEVICE_HARDWARE_ONEWIRE_TEMP;
	config.hw.pinNr = fridgeSensorPin;
	config.deviceFunction = DEVICE_CHAMBER_TEMP;
	eepromManager.storeDevice(config, 3);

	config.beer = 1;
	config.hw.pinNr = beerSensorPin;
	config.deviceFunction = DEVICE_BEER_TEMP;
	eepromManager.storeDevice(config, 4);

	return 5;
#endif

#if BREWPI_STATIC_CONFIG==BREWPI_SHIELD_REV_C
	// the only component that's not dynamic is the door
	return 0;
#endif

#else
	return 0;
#endif
}

#define arraySize(x) (sizeof(x)/sizeof(x[0]))

bool EepromManager::applySettings()
{
	if (!hasSettings())
		return false;

	// start from a clean state
	deviceManager.setupUnconfiguredDevices();

	DEBUG_MSG(PSTR("Applying settings"));

	// load the one chamber and one beer for now
	eptr_t pv = pointerOffset(chambers);
	tempControl.loadConstants(pv+offsetof(ChamberBlock, chamberSettings.cc));
	tempControl.loadSettings(pv+offsetof(ChamberBlock, beer[0].cs));

	DEBUG_MSG(PSTR("Applied settings"));

	DeviceConfig deviceConfig;
	for (uint8_t index = 0; fetchDevice(deviceConfig, index); index++)
	{
		if (deviceConfig.deviceFunction!=0xFF && deviceManager.isDeviceValid(deviceConfig, deviceConfig, index))
			deviceManager.installDevice(deviceConfig);
		else {
			clear((uint8_t*)&deviceConfig, sizeof(deviceConfig));
			eepromManager.storeDevice(deviceConfig, index);
		}
	}

	return true;
}

void EepromManager::storeTempConstantsAndSettings()
{
	uint8_t chamber = 0;
	eptr_t pv = pointerOffset(chambers);
	pv += sizeof(ChamberBlock)*chamber;
	tempControl.storeConstants(pv+offsetof(ChamberBlock, chamberSettings.cc));

	storeTempSettings();
}

void EepromManager::storeTempSettings()
{
	uint8_t chamber = 0;
	eptr_t pv = pointerOffset(chambers);
	pv += sizeof(ChamberBlock)*chamber;
	// for now assume just one beer.
	tempControl.storeSettings(pv+offsetof(ChamberBlock, beer[0].cs));
}

bool EepromManager::fetchDevice(DeviceConfig& config, uint8_t deviceIndex)
{
	bool ok = (hasSettings() && deviceIndex<EepromFormat::MAX_DEVICES);
	if (ok)
		eepromAccess.readBlock(&config, pointerOffset(devices)+sizeof(DeviceConfig)*deviceIndex, sizeof(DeviceConfig));
	return ok;
}

bool EepromManager::storeDevice(const DeviceConfig& config, uint8_t deviceIndex)
{
	bool ok = (hasSettings() && deviceIndex<EepromFormat::MAX_DEVICES);
	if (ok)
		eepromAccess.writeBlock(pointerOffset(devices)+sizeof(DeviceConfig)*deviceIndex, &config, sizeof(DeviceConfig));
	return ok;
}

void fill(int8_t* p, uint8_t size) {
	while (size-->0) *p++ = -1;
}
void clear(uint8_t* p, uint8_t size) {
	while (size-->0) *p++ = 0;
}
<|endoftext|>


<commit_before>#include "Plane.h"
#include <GL/glew.h>
#include <MathGeoLib/include/Math/float3.h>
#include <MathGeoLib/include/Math/MathFunc.h>
#include "Globals.h"

::Plane::Plane(int planeSize) :
	Primitive(), PlaneSize(planeSize) {}

::Plane::Plane(const float3& position, Quat& rotation, int planeSize) :
	Primitive(position, rotation), PlaneSize(planeSize) {}

::Plane::Plane(const float3& position, Quat& rotation, const float3& color, int planeSize) :
	Primitive(position, rotation, color), PlaneSize(planeSize) {}

::Plane::~Plane() {}

void ::Plane::Draw()
{
	glDepthMask(GL_FALSE);
	glPushMatrix();
	glTranslatef(Position.x, Position.y, Position.z);
	float3 axis = Rotation.Axis();
	glRotatef(RadToDeg(Rotation.Angle()), axis.x, axis.y, axis.z);

	glColor4f(0.f, 0.f, 0.f, 0.f);

	glBegin(GL_QUADS);
	glVertex3f(-PlaneSize, -0.001, -PlaneSize);
	glVertex3f(-PlaneSize, -0.001, PlaneSize);
	glVertex3f(PlaneSize, -0.001, PlaneSize);
	glVertex3f(PlaneSize, -0.001, -PlaneSize);
	glEnd();

	glBegin(GL_LINES);
	for (int i = -PlaneSize; i <= PlaneSize; i++) {
		if (i == -PlaneSize) { glColor3f(.6, .3, .3); }
		else { glColor3f(.25, .25, .25); };
		glVertex3f(i, 0, -PlaneSize);
		glVertex3f(i, 0, PlaneSize);
		if (i == -PlaneSize) { glColor3f(.3, .3, .6); }
		else { glColor3f(.25, .25, .25); };
		glVertex3f(-PlaneSize, 0, i);
		glVertex3f(PlaneSize, 0, i);
	};
	glEnd();
	glPopMatrix();
}
<commit_msg>Enable depthMask at draw end and Update Color with variable<commit_after>#include "Plane.h"
#include <GL/glew.h>
#include <MathGeoLib/include/Math/float3.h>
#include <MathGeoLib/include/Math/MathFunc.h>
#include "Globals.h"

::Plane::Plane(int planeSize) :
	Primitive(), PlaneSize(planeSize) {}

::Plane::Plane(const float3& position, Quat& rotation, int planeSize) :
	Primitive(position, rotation), PlaneSize(planeSize) {}

::Plane::Plane(const float3& position, Quat& rotation, const float3& color, int planeSize) :
	Primitive(position, rotation, color), PlaneSize(planeSize) {}

::Plane::~Plane() {}

void ::Plane::Draw()
{
	glDepthMask(GL_FALSE);
	glPushMatrix();
	glTranslatef(Position.x, Position.y, Position.z);
	float3 axis = Rotation.Axis();
	glRotatef(RadToDeg(Rotation.Angle()), axis.x, axis.y, axis.z);

	glColor4f(Color.x, Color.y, Color.z, 0.f);

	glBegin(GL_QUADS);
	glVertex3f(-PlaneSize, -0.001, -PlaneSize);
	glVertex3f(-PlaneSize, -0.001, PlaneSize);
	glVertex3f(PlaneSize, -0.001, PlaneSize);
	glVertex3f(PlaneSize, -0.001, -PlaneSize);
	glEnd();

	glBegin(GL_LINES);
	for (int i = -PlaneSize; i <= PlaneSize; i++) {
		if (i == -PlaneSize) { glColor3f(.6, .3, .3); }
		else { glColor3f(.25, .25, .25); };
		glVertex3f(i, 0, -PlaneSize);
		glVertex3f(i, 0, PlaneSize);
		if (i == -PlaneSize) { glColor3f(.3, .3, .6); }
		else { glColor3f(.25, .25, .25); };
		glVertex3f(-PlaneSize, 0, i);
		glVertex3f(PlaneSize, 0, i);
	};
	glEnd();
	glPopMatrix();
	glDepthMask(GL_TRUE);
}
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkFastNumericConversion.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
// .NAME vtkFastNumericConversion - Enables fast conversion of floating point to fixed point
// .SECTION Description
// vtkFastNumericConversion uses a portable (assuming IEEE format) method for converting single and
// double precision floating point values to a fixed point representation. This allows fast
// integer flooring on platforms, such as Intel X86, in which CPU floating point flooring
// algorithms are very slow. It is based on the techniques described in Chris Hecker's article,
// "Let's Get to the (Floating) Point", in Game Developer Magazine, Feb/Mar 1996, and the
// techniques described in Michael Herf's website, http://www.stereopsis.com/FPU.html.
// The Hecker article can be found at http://www.d6.com/users/checker/pdfs/gdmfp.pdf.
// Unfortunately, each of these techniques is incomplete, and doesn't floor properly,
// in a way that depends on how many bits are reserved for fixed point fractional use, due to
// failing to properly account for the default round-towards-even rounding mode of the X86. Thus,
// my implementation incorporates some rounding correction that undoes the rounding that the
// FPU performs during denormalization of the floating point value. Note that
// the rounding affect I'm talking about here is not the effect on the fistp instruction,
// but rather the effect that occurs during the denormalization of a value that occurs when
// adding it to a much larger value. The bits must be shifted to the right, and when a "1" bit
// falls off the edge, the rounding mode determines what happens next, in order
// to avoid completely "losing" the 1-bit. Furthermore, my implementation works on Linux, where the
// default precision mode is 64-bit extended precision.

// This class is contributed to VTK by Chris Volpe of Applied Research Associates, Inc.
// (My employer requires me to say that -- CRV)

#include "vtkFastNumericConversion.h"
#include "vtkObjectFactory.h"
#include "vtkTimerLog.h"

vtkCxxRevisionMacro(vtkFastNumericConversion, "1.3");
vtkStandardNewMacro(vtkFastNumericConversion);

int vtkFastNumericConversion::TestQuickFloor(double val)
  {
  return vtkFastNumericConversion::QuickFloor(val);
  }

int vtkFastNumericConversion::TestSafeFloor(double val)
  {
  return vtkFastNumericConversion::SafeFloor(val);
  }

int vtkFastNumericConversion::TestRound(double val)
  {
  return vtkFastNumericConversion::Round(val);
  }

int vtkFastNumericConversion::TestConvertFixedPointIntPart(double val)
  {
  int frac;
  return this->ConvertFixedPoint(val, frac);
  }

int vtkFastNumericConversion::TestConvertFixedPointFracPart(double val)
  {
  int frac;
  this->ConvertFixedPoint(val, frac);
  return frac;
  }

void vtkFastNumericConversion::InternalRebuild()
  {
  int i;
  this->fixRound=.5;
  for (i=this->internalReservedFracBits; i; i--)
    {
    this->fixRound *= .5;
    }
  this->fracMask = (1<<this->internalReservedFracBits)-1;
  this->fpDenormalizer = (static_cast<unsigned long>(1) << (52-30-this->internalReservedFracBits)) *
    this->two30() * this->BorrowBit();
  this->epTempDenormalizer = this->fpDenormalizer * (static_cast<unsigned long>(1) << (63-52));
  }

void vtkFastNumericConversion::PrintSelf(ostream &os, vtkIndent indent)
  {
  os << indent << "ReservedFracBits: " << this->internalReservedFracBits << endl;
  os << indent << "Bare time from last PerformanceTest() call: " << this->bare_time << endl;
  os << indent << "Cast time from last PerformanceTest() call: " << this->cast_time << endl;
  os << indent << "ConvertFixedPoint time from last PerformanceTest() call: " << this->convert_time << endl;
  os << indent << "QuickFloor time from last PerformanceTest() call: " << this->quickfloor_time << endl;
  os << indent << "SafeFloor time from last PerformanceTest() call: " << this->safefloor_time << endl;
  os << indent << "Round time from last PerformanceTest() call: " << this->round_time << endl;
  if (this->bare_time != 0.0)
    {
    // Don't do this if we haven't run the tests yet.
    os << indent << "Speedup ratio from cast to quickfloor is: " <<
      (this->cast_time-this->bare_time)/(this->quickfloor_time-this->bare_time) << endl;
    os << indent << "Speedup ratio from cast to safefloor is: " <<
      (this->cast_time-this->bare_time)/(this->safefloor_time-this->bare_time) << endl;
    os << indent << "Speedup ratio from cast to round is: " <<
      (this->cast_time-this->bare_time)/(this->round_time-this->bare_time) << endl;
    }
  }

void vtkFastNumericConversion::PerformanceTests(void)
  {
  const int inner_count = 10000;
  const int outer_count = 10000;
  double *dval = new double[inner_count];
  int *ival = new int[inner_count];
  int *frac = new int[inner_count];

  int i,o;
  vtkTimerLog *timer = vtkTimerLog::New();

  for (i=0; i<inner_count; i++)
    {
    dval[i] = i;
    ival[i] = 0;
    }

  timer->StartTimer();
  for (o=0; o<outer_count; o++)
    {
    for (i=0; i<inner_count; i++)
      {
      // Pure bit copy
      ival[i] = *reinterpret_cast<int *>(&dval[i]);
      }
    }
  timer->StopTimer();
  this->bare_time = timer->GetElapsedTime();

  // Compute cast time
  timer->StartTimer();
  for (o=0; o<outer_count; o++)
    {
    for (i=0; i<inner_count; i++)
      {
      ival[i] = static_cast<int>(dval[i]);
      }
    }
  timer->StopTimer();
  this->cast_time = timer->GetElapsedTime();

  // Compute convert time
  timer->StartTimer();
  for (o=0; o<outer_count; o++)
    {
    for (i=0; i<inner_count; i++)
      {
      ival[i] = this->ConvertFixedPoint(dval[i], frac[i]);
      }
    }
  timer->StopTimer();
  this->convert_time = timer->GetElapsedTime();

  // Compute quickfloor time
  timer->StartTimer();
  for (o=0; o<outer_count; o++)
    {
    for (i=0; i<inner_count; i++)
      {
      ival[i] = vtkFastNumericConversion::QuickFloor(dval[i]);
      }
    }
  timer->StopTimer();
  this->quickfloor_time = timer->GetElapsedTime();

  // Compute safefloor time
  timer->StartTimer();
  for (o=0; o<outer_count; o++)
    {
    for (i=0; i<inner_count; i++)
      {
      ival[i] = vtkFastNumericConversion::SafeFloor(dval[i]);
      }
    }
  timer->StopTimer();
  this->safefloor_time = timer->GetElapsedTime();

  // Compute round time
  timer->StartTimer();
  for (o=0; o<outer_count; o++)
    {
    for (i=0; i<inner_count; i++)
      {
      ival[i] = vtkFastNumericConversion::Round(dval[i]);
      }
    }
  timer->StopTimer();
  this->round_time = timer->GetElapsedTime();

  delete [] dval;
  delete [] ival;
  delete [] frac;

  timer->Delete();
  }
<commit_msg>BUG: Fix divide by zero errors that occur when the test timing is just right...<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkFastNumericConversion.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
// .NAME vtkFastNumericConversion - Enables fast conversion of floating point to fixed point
// .SECTION Description
// vtkFastNumericConversion uses a portable (assuming IEEE format) method for converting single and
// double precision floating point values to a fixed point representation. This allows fast
// integer flooring on platforms, such as Intel X86, in which CPU floating point flooring
// algorithms are very slow. It is based on the techniques described in Chris Hecker's article,
// "Let's Get to the (Floating) Point", in Game Developer Magazine, Feb/Mar 1996, and the
// techniques described in Michael Herf's website, http://www.stereopsis.com/FPU.html.
// The Hecker article can be found at http://www.d6.com/users/checker/pdfs/gdmfp.pdf.
// Unfortunately, each of these techniques is incomplete, and doesn't floor properly,
// in a way that depends on how many bits are reserved for fixed point fractional use, due to
// failing to properly account for the default round-towards-even rounding mode of the X86. Thus,
// my implementation incorporates some rounding correction that undoes the rounding that the
// FPU performs during denormalization of the floating point value. Note that
// the rounding affect I'm talking about here is not the effect on the fistp instruction,
// but rather the effect that occurs during the denormalization of a value that occurs when
// adding it to a much larger value. The bits must be shifted to the right, and when a "1" bit
// falls off the edge, the rounding mode determines what happens next, in order
// to avoid completely "losing" the 1-bit. Furthermore, my implementation works on Linux, where the
// default precision mode is 64-bit extended precision.

// This class is contributed to VTK by Chris Volpe of Applied Research Associates, Inc.
// (My employer requires me to say that -- CRV)

#include "vtkFastNumericConversion.h"
#include "vtkObjectFactory.h"
#include "vtkTimerLog.h"

vtkCxxRevisionMacro(vtkFastNumericConversion, "1.4");
vtkStandardNewMacro(vtkFastNumericConversion);

int vtkFastNumericConversion::TestQuickFloor(double val)
  {
  return vtkFastNumericConversion::QuickFloor(val);
  }

int vtkFastNumericConversion::TestSafeFloor(double val)
  {
  return vtkFastNumericConversion::SafeFloor(val);
  }

int vtkFastNumericConversion::TestRound(double val)
  {
  return vtkFastNumericConversion::Round(val);
  }

int vtkFastNumericConversion::TestConvertFixedPointIntPart(double val)
  {
  int frac;
  return this->ConvertFixedPoint(val, frac);
  }

int vtkFastNumericConversion::TestConvertFixedPointFracPart(double val)
  {
  int frac;
  this->ConvertFixedPoint(val, frac);
  return frac;
  }

void vtkFastNumericConversion::InternalRebuild()
  {
  int i;
  this->fixRound=.5;
  for (i=this->internalReservedFracBits; i; i--)
    {
    this->fixRound *= .5;
    }
  this->fracMask = (1<<this->internalReservedFracBits)-1;
  this->fpDenormalizer = (static_cast<unsigned long>(1) << (52-30-this->internalReservedFracBits)) *
    this->two30() * this->BorrowBit();
  this->epTempDenormalizer = this->fpDenormalizer * (static_cast<unsigned long>(1) << (63-52));
  }

void vtkFastNumericConversion::PrintSelf(ostream &os, vtkIndent indent)
  {
  os << indent << "ReservedFracBits: " << this->internalReservedFracBits << endl;
  os << indent << "Bare time from last PerformanceTest() call: " << this->bare_time << endl;
  os << indent << "Cast time from last PerformanceTest() call: " << this->cast_time << endl;
  os << indent << "ConvertFixedPoint time from last PerformanceTest() call: " << this->convert_time << endl;
  os << indent << "QuickFloor time from last PerformanceTest() call: " << this->quickfloor_time << endl;
  os << indent << "SafeFloor time from last PerformanceTest() call: " << this->safefloor_time << endl;
  os << indent << "Round time from last PerformanceTest() call: " << this->round_time << endl;
  if (this->bare_time != 0.0)
    {
    // Don't do this if we haven't run the tests yet.
    if (this->quickfloor_time-this->bare_time > 0.0)
      {
      os << indent << "Speedup ratio from cast to quickfloor is: " <<
        (this->cast_time-this->bare_time)/(this->quickfloor_time-this->bare_time) << endl;
      }
    else
      {
      os << indent << "quickfloor_time <= bare_time, cannot calculate speedup ratio" << endl;
      }

    if (this->safefloor_time-this->bare_time > 0.0)
      {
      os << indent << "Speedup ratio from cast to safefloor is: " <<
        (this->cast_time-this->bare_time)/(this->safefloor_time-this->bare_time) << endl;
      }
    else
      {
      os << indent << "safefloor_time <= bare_time, cannot calculate speedup ratio" << endl;
      }

    if (this->round_time-this->bare_time > 0.0)
      {
      os << indent << "Speedup ratio from cast to round is: " <<
        (this->cast_time-this->bare_time)/(this->round_time-this->bare_time) << endl;
      }
    else
      {
      os << indent << "round_time <= bare_time, cannot calculate speedup ratio" << endl;
      }
    }
  }

void vtkFastNumericConversion::PerformanceTests(void)
  {
  const int inner_count = 10000;
  const int outer_count = 10000;
  double *dval = new double[inner_count];
  int *ival = new int[inner_count];
  int *frac = new int[inner_count];

  int i,o;
  vtkTimerLog *timer = vtkTimerLog::New();

  for (i=0; i<inner_count; i++)
    {
    dval[i] = i;
    ival[i] = 0;
    }

  timer->StartTimer();
  for (o=0; o<outer_count; o++)
    {
    for (i=0; i<inner_count; i++)
      {
      // Pure bit copy
      ival[i] = *reinterpret_cast<int *>(&dval[i]);
      }
    }
  timer->StopTimer();
  this->bare_time = timer->GetElapsedTime();

  // Compute cast time
  timer->StartTimer();
  for (o=0; o<outer_count; o++)
    {
    for (i=0; i<inner_count; i++)
      {
      ival[i] = static_cast<int>(dval[i]);
      }
    }
  timer->StopTimer();
  this->cast_time = timer->GetElapsedTime();

  // Compute convert time
  timer->StartTimer();
  for (o=0; o<outer_count; o++)
    {
    for (i=0; i<inner_count; i++)
      {
      ival[i] = this->ConvertFixedPoint(dval[i], frac[i]);
      }
    }
  timer->StopTimer();
  this->convert_time = timer->GetElapsedTime();

  // Compute quickfloor time
  timer->StartTimer();
  for (o=0; o<outer_count; o++)
    {
    for (i=0; i<inner_count; i++)
      {
      ival[i] = vtkFastNumericConversion::QuickFloor(dval[i]);
      }
    }
  timer->StopTimer();
  this->quickfloor_time = timer->GetElapsedTime();

  // Compute safefloor time
  timer->StartTimer();
  for (o=0; o<outer_count; o++)
    {
    for (i=0; i<inner_count; i++)
      {
      ival[i] = vtkFastNumericConversion::SafeFloor(dval[i]);
      }
    }
  timer->StopTimer();
  this->safefloor_time = timer->GetElapsedTime();

  // Compute round time
  timer->StartTimer();
  for (o=0; o<outer_count; o++)
    {
    for (i=0; i<inner_count; i++)
      {
      ival[i] = vtkFastNumericConversion::Round(dval[i]);
      }
    }
  timer->StopTimer();
  this->round_time = timer->GetElapsedTime();

  delete [] dval;
  delete [] ival;
  delete [] frac;

  timer->Delete();
  }
<|endoftext|>


<commit_before><commit_msg>Update comment<commit_after><|endoftext|>