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

#include <unordered_map>

#include "class_names.h"
#include "compiler_helpers.h"
#include "dbg_primitive.h"
#include "i_cor_debug_helper.h"
#include "type_signature.h"

namespace google_cloud_debugger {

bool NumericCompilerHelper::IsImplicitNumericConversionable(
    const TypeSignature &source, const TypeSignature &target) {
  const CorElementType &source_type = source.cor_type;
  const CorElementType &target_type = target.cor_type;
  // Most of the logic here is from implicit numeric conversions:
  // https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/conversions#implicit-conversions
  switch (source_type) {
    case CorElementType::ELEMENT_TYPE_I1: {
      switch (target_type) {
        case CorElementType::ELEMENT_TYPE_I1:
        case CorElementType::ELEMENT_TYPE_I2:
        case CorElementType::ELEMENT_TYPE_I4:
        case CorElementType::ELEMENT_TYPE_I8:
        case CorElementType::ELEMENT_TYPE_R4:
        case CorElementType::ELEMENT_TYPE_R8:
          return true;
        default:
          return false;
      }
    }
    case CorElementType::ELEMENT_TYPE_U1: {
      switch (target_type) {
        case CorElementType::ELEMENT_TYPE_U1:
        case CorElementType::ELEMENT_TYPE_I2:
        case CorElementType::ELEMENT_TYPE_U2:
        case CorElementType::ELEMENT_TYPE_I4:
        case CorElementType::ELEMENT_TYPE_U4:
        case CorElementType::ELEMENT_TYPE_I8:
        case CorElementType::ELEMENT_TYPE_U8:
        case CorElementType::ELEMENT_TYPE_R4:
        case CorElementType::ELEMENT_TYPE_R8:
          return true;
        default:
          return false;
      }
    }
    case CorElementType::ELEMENT_TYPE_I2: {
      switch (target_type) {
        case CorElementType::ELEMENT_TYPE_I2:
        case CorElementType::ELEMENT_TYPE_I4:
        case CorElementType::ELEMENT_TYPE_I8:
        case CorElementType::ELEMENT_TYPE_R4:
        case CorElementType::ELEMENT_TYPE_R8:
          return true;
        default:
          return false;
      }
    }
    case CorElementType::ELEMENT_TYPE_U2: {
      switch (target_type) {
        case CorElementType::ELEMENT_TYPE_U2:
        case CorElementType::ELEMENT_TYPE_I4:
        case CorElementType::ELEMENT_TYPE_U4:
        case CorElementType::ELEMENT_TYPE_I8:
        case CorElementType::ELEMENT_TYPE_U8:
        case CorElementType::ELEMENT_TYPE_R4:
        case CorElementType::ELEMENT_TYPE_R8:
          return true;
        default:
          return false;
      }
    }
    case CorElementType::ELEMENT_TYPE_I4: {
      switch (target_type) {
        case CorElementType::ELEMENT_TYPE_I4:
        case CorElementType::ELEMENT_TYPE_I8:
        case CorElementType::ELEMENT_TYPE_R4:
        case CorElementType::ELEMENT_TYPE_R8:
          return true;
        default:
          return false;
      }
    }
    case CorElementType::ELEMENT_TYPE_U4: {
      switch (target_type) {
        case CorElementType::ELEMENT_TYPE_U4:
        case CorElementType::ELEMENT_TYPE_I8:
        case CorElementType::ELEMENT_TYPE_U8:
        case CorElementType::ELEMENT_TYPE_R4:
        case CorElementType::ELEMENT_TYPE_R8:
          return true;
        default:
          return false;
      }
    }
    case CorElementType::ELEMENT_TYPE_I8: {
      switch (target_type) {
        case CorElementType::ELEMENT_TYPE_I8:
        case CorElementType::ELEMENT_TYPE_R4:
        case CorElementType::ELEMENT_TYPE_R8:
          return true;
        default:
          return false;
      }
    }
    case CorElementType::ELEMENT_TYPE_U8: {
      switch (target_type) {
        case CorElementType::ELEMENT_TYPE_U8:
        case CorElementType::ELEMENT_TYPE_R4:
        case CorElementType::ELEMENT_TYPE_R8:
          return true;
        default:
          return false;
      }
    }
    case CorElementType::ELEMENT_TYPE_CHAR: {
      switch (target_type) {
        case CorElementType::ELEMENT_TYPE_CHAR:
        case CorElementType::ELEMENT_TYPE_U2:
        case CorElementType::ELEMENT_TYPE_I4:
        case CorElementType::ELEMENT_TYPE_U4:
        case CorElementType::ELEMENT_TYPE_I8:
        case CorElementType::ELEMENT_TYPE_U8:
        case CorElementType::ELEMENT_TYPE_R4:
        case CorElementType::ELEMENT_TYPE_R8:
          return true;
        default:
          return false;
      }
    }
    case CorElementType::ELEMENT_TYPE_R4: {
      switch (target_type) {
        case CorElementType::ELEMENT_TYPE_R4:
        case CorElementType::ELEMENT_TYPE_R8:
          return true;
        default:
          return false;
      }
    }
    case CorElementType::ELEMENT_TYPE_R8: {
      switch (target_type) {
        case CorElementType::ELEMENT_TYPE_R8:
          return true;
        default:
          return false;
      }
    }
    default:
      return false;
  }
}

bool NumericCompilerHelper::IsNumericallyPromotedToInt(
    const CorElementType &source) {
  return source == CorElementType::ELEMENT_TYPE_CHAR ||
         source == CorElementType::ELEMENT_TYPE_I1 ||
         source == CorElementType::ELEMENT_TYPE_U1 ||
         source == CorElementType::ELEMENT_TYPE_I2;
}

// Returns true for I1, I2, I4 and I8 types.
inline bool IsSignedIntegralType(const CorElementType &element_type) {
  return element_type == CorElementType::ELEMENT_TYPE_I1 ||
         element_type == CorElementType::ELEMENT_TYPE_I2 ||
         element_type == CorElementType::ELEMENT_TYPE_I4 ||
         element_type == CorElementType::ELEMENT_TYPE_I8;
}

bool NumericCompilerHelper::BinaryNumericalPromotion(const CorElementType &arg1,
                                                     const CorElementType &arg2,
                                                     CorElementType *result,
                                                     std::ostream *err_stream) {
  if (!TypeCompilerHelper::IsNumericalType(arg1) &&
      !TypeCompilerHelper::IsNumericalType(arg2)) {
    *err_stream << "Both arguments has to be of numerical types.";
    return false;
  }

  // TODO(quoct): Add support for Decimal.
  if (arg1 == CorElementType::ELEMENT_TYPE_R8 ||
      arg2 == CorElementType::ELEMENT_TYPE_R8) {
    *result = CorElementType::ELEMENT_TYPE_R8;
    return true;
  } else if (arg1 == CorElementType::ELEMENT_TYPE_R4 ||
             arg2 == CorElementType::ELEMENT_TYPE_R4) {
    *result = CorElementType::ELEMENT_TYPE_R4;
    return true;
  } else if (arg1 == CorElementType::ELEMENT_TYPE_U8 ||
             arg2 == CorElementType::ELEMENT_TYPE_U8) {
    // If the other operand is of type sbyte, short, int or long,
    // an error will occur. This is because no integral type exists that can
    // represent the full range of ulong as well as the signed integral types.
    if (IsSignedIntegralType(arg1) || IsSignedIntegralType(arg2)) {
      *err_stream << "If one of the argument is an unsigned long, "
                  << "the other cannot be a signed integral type.";
      return false;
    }
    *result = CorElementType::ELEMENT_TYPE_U8;
    return true;
  } else if (arg1 == CorElementType::ELEMENT_TYPE_I8 ||
             arg2 == CorElementType::ELEMENT_TYPE_I8) {
    *result = CorElementType::ELEMENT_TYPE_I8;
    return true;
  } else if (arg1 == CorElementType::ELEMENT_TYPE_U4 ||
             arg2 == CorElementType::ELEMENT_TYPE_U4) {
    // If 1 of the operand is sbyte, short or int,
    // the result will be long. We can simply call
    // IsSignedIntegralType without worrying about arg1
    // being an I8 type because that is already checked above.
    if (IsSignedIntegralType(arg1)) {
      *result = CorElementType::ELEMENT_TYPE_I8;
      return true;
    }

    if (IsSignedIntegralType(arg2)) {
      *result = CorElementType::ELEMENT_TYPE_I8;
      return true;
    }

    *result = CorElementType::ELEMENT_TYPE_U4;
    return true;
  } else {
    // Otherwise, both operands are converted to int.
    *result = CorElementType::ELEMENT_TYPE_I4;
    return true;
  }
}

bool TypeCompilerHelper::IsNumericalType(const CorElementType &cor_type) {
  return IsIntegralType(cor_type) ||
         cor_type == CorElementType::ELEMENT_TYPE_R4 ||
         cor_type == CorElementType::ELEMENT_TYPE_R8;
}

bool TypeCompilerHelper::IsIntegralType(const CorElementType &cor_type) {
  return cor_type == CorElementType::ELEMENT_TYPE_I1 ||
         cor_type == CorElementType::ELEMENT_TYPE_U1 ||
         cor_type == CorElementType::ELEMENT_TYPE_I2 ||
         cor_type == CorElementType::ELEMENT_TYPE_U2 ||
         cor_type == CorElementType::ELEMENT_TYPE_I4 ||
         cor_type == CorElementType::ELEMENT_TYPE_U4 ||
         cor_type == CorElementType::ELEMENT_TYPE_I8 ||
         cor_type == CorElementType::ELEMENT_TYPE_U8 ||
         cor_type == CorElementType::ELEMENT_TYPE_CHAR;
}

bool TypeCompilerHelper::IsArrayType(const CorElementType &array_type) {
  return array_type == CorElementType::ELEMENT_TYPE_ARRAY ||
         array_type == CorElementType::ELEMENT_TYPE_SZARRAY;
}

bool TypeCompilerHelper::IsObjectType(const CorElementType &cor_type) {
  return cor_type == CorElementType::ELEMENT_TYPE_OBJECT ||
         cor_type == CorElementType::ELEMENT_TYPE_CLASS ||
         cor_type == CorElementType::ELEMENT_TYPE_VALUETYPE;
}

CorElementType TypeCompilerHelper::ConvertStringToCorElementType(
    const std::string &type_string) {
  static std::unordered_map<std::string, CorElementType> string_to_cor_type{
      {kCharClassName, CorElementType::ELEMENT_TYPE_BOOLEAN},
      {kSByteClassName, CorElementType::ELEMENT_TYPE_I1},
      {kCharClassName, CorElementType::ELEMENT_TYPE_CHAR},
      {kByteClassName, CorElementType::ELEMENT_TYPE_U1},
      {kInt16ClassName, CorElementType::ELEMENT_TYPE_I2},
      {kUInt16ClassName, CorElementType::ELEMENT_TYPE_U2},
      {kInt32ClassName, CorElementType::ELEMENT_TYPE_I4},
      {kUInt32ClassName, CorElementType::ELEMENT_TYPE_U4},
      {kInt64ClassName, CorElementType::ELEMENT_TYPE_I8},
      {kUInt64ClassName, CorElementType::ELEMENT_TYPE_U8},
      {kStringClassName, CorElementType::ELEMENT_TYPE_STRING},
      {kObjectClassName, CorElementType::ELEMENT_TYPE_OBJECT}};

  if (string_to_cor_type.find(type_string) != string_to_cor_type.end()) {
    return string_to_cor_type[type_string];
  } else {
    auto open_bracket = type_string.find("[");
    if (open_bracket == std::string::npos) {
      return CorElementType::ELEMENT_TYPE_OBJECT;
    }

    auto closing_bracket = type_string.find("]");
    if (closing_bracket == std::string::npos ||
        closing_bracket < open_bracket) {
      return CorElementType::ELEMENT_TYPE_OBJECT;
    }

    // This means the type is something like System.Int32[],
    // which represents a simple array.
    if (open_bracket + 1 == closing_bracket) {
      return CorElementType::ELEMENT_TYPE_SZARRAY;
    }

    // This means the type is something like System.Int32[,], which is
    // a multidimensional array.
    return CorElementType::ELEMENT_TYPE_ARRAY;
  }
}

HRESULT TypeCompilerHelper::ConvertCorElementTypeToString(
    const CorElementType &cor_type, std::string *result) {
  static std::unordered_map<CorElementType, std::string> cor_type_to_string{
      {CorElementType::ELEMENT_TYPE_BOOLEAN, kBooleanClassName},
      {CorElementType::ELEMENT_TYPE_I1, kSByteClassName},
      {CorElementType::ELEMENT_TYPE_CHAR, kCharClassName},
      {CorElementType::ELEMENT_TYPE_U1, kByteClassName},
      {CorElementType::ELEMENT_TYPE_I2, kInt16ClassName},
      {CorElementType::ELEMENT_TYPE_U2, kUInt16ClassName},
      {CorElementType::ELEMENT_TYPE_I4, kInt32ClassName},
      {CorElementType::ELEMENT_TYPE_U4, kUInt32ClassName},
      {CorElementType::ELEMENT_TYPE_I8, kInt64ClassName},
      {CorElementType::ELEMENT_TYPE_U8, kUInt64ClassName},
      {CorElementType::ELEMENT_TYPE_R4, kSingleClassName},
      {CorElementType::ELEMENT_TYPE_R8, kDoubleClassName},
      {CorElementType::ELEMENT_TYPE_I, kIntPtrClassName},
      {CorElementType::ELEMENT_TYPE_U, kUIntPtrClassName},
      {CorElementType::ELEMENT_TYPE_STRING, kStringClassName},
      {CorElementType::ELEMENT_TYPE_OBJECT, kObjectClassName}};

  if (result == nullptr) {
    return E_INVALIDARG;
  }

  if (cor_type_to_string.find(cor_type) != cor_type_to_string.end()) {
    *result = cor_type_to_string[cor_type];
    return S_OK;
  }

  return E_FAIL;
}

HRESULT TypeCompilerHelper::IsBaseClass(
    mdTypeDef source_class, IMetaDataImport *source_class_metadata,
    const std::vector<CComPtr<ICorDebugAssembly>> &loaded_assemblies,
    const std::string &target_class, ICorDebugHelper *debug_helper,
    std::ostream *err_stream) {
  HRESULT hr;
  mdTypeDef current_class_token = source_class;
  CComPtr<IMetaDataImport> current_metadata_import;
  std::string current_class_name;
  mdToken current_base_class_token = source_class;

  current_metadata_import = source_class_metadata;
  int max_class_to_traverse = 10;
  while (max_class_to_traverse >= 0) {
    max_class_to_traverse -= 1;
    hr = debug_helper->GetTypeNameFromMdTypeDef(
        current_class_token, current_metadata_import, &current_class_name,
        &current_base_class_token, err_stream);
    if (FAILED(hr)) {
      return hr;
    }

    if (current_class_name.compare(target_class) == 0) {
      return S_OK;
    }

    if (current_class_name.compare(kObjectClassName)) {
      return E_FAIL;
    }

    // Retrieves the base class token and metadata import.
    CorTokenType token_type =
        (CorTokenType)(TypeFromToken(current_base_class_token));
    if (token_type == CorTokenType::mdtTypeDef) {
      // No need to change the IMetaDataImport since we are still in the same
      // module.
      current_class_token = current_base_class_token;
    } else if (token_type == CorTokenType::mdtTypeRef) {
      CComPtr<IMetaDataImport> resolved_metadata_import;
      mdTypeDef resolved_class_token;
      hr = debug_helper->GetMdTypeDefAndMetaDataFromTypeRef(
          current_base_class_token, loaded_assemblies, current_metadata_import,
          &resolved_class_token, &resolved_metadata_import, err_stream);
      if (FAILED(hr)) {
        return hr;
      }

      current_class_token = resolved_class_token;
      current_metadata_import = resolved_metadata_import;
    } else {
      // Not supported.
      *err_stream << "Only mdTypeDef and mdTypeRef tokens are supported.";
      return E_NOTIMPL;
    }
  }

  return E_FAIL;
}

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

#include <unordered_map>

#include "class_names.h"
#include "compiler_helpers.h"
#include "dbg_primitive.h"
#include "i_cor_debug_helper.h"
#include "type_signature.h"

namespace google_cloud_debugger {

bool NumericCompilerHelper::IsImplicitNumericConversionable(
    const TypeSignature &source, const TypeSignature &target) {
  const CorElementType &source_type = source.cor_type;
  const CorElementType &target_type = target.cor_type;
  // Most of the logic here is from implicit numeric conversions:
  // https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/conversions#implicit-conversions
  switch (source_type) {
    case CorElementType::ELEMENT_TYPE_I1: {
      switch (target_type) {
        case CorElementType::ELEMENT_TYPE_I1:
        case CorElementType::ELEMENT_TYPE_I2:
        case CorElementType::ELEMENT_TYPE_I4:
        case CorElementType::ELEMENT_TYPE_I8:
        case CorElementType::ELEMENT_TYPE_R4:
        case CorElementType::ELEMENT_TYPE_R8:
          return true;
        default:
          return false;
      }
    }
    case CorElementType::ELEMENT_TYPE_U1: {
      switch (target_type) {
        case CorElementType::ELEMENT_TYPE_U1:
        case CorElementType::ELEMENT_TYPE_I2:
        case CorElementType::ELEMENT_TYPE_U2:
        case CorElementType::ELEMENT_TYPE_I4:
        case CorElementType::ELEMENT_TYPE_U4:
        case CorElementType::ELEMENT_TYPE_I8:
        case CorElementType::ELEMENT_TYPE_U8:
        case CorElementType::ELEMENT_TYPE_R4:
        case CorElementType::ELEMENT_TYPE_R8:
          return true;
        default:
          return false;
      }
    }
    case CorElementType::ELEMENT_TYPE_I2: {
      switch (target_type) {
        case CorElementType::ELEMENT_TYPE_I2:
        case CorElementType::ELEMENT_TYPE_I4:
        case CorElementType::ELEMENT_TYPE_I8:
        case CorElementType::ELEMENT_TYPE_R4:
        case CorElementType::ELEMENT_TYPE_R8:
          return true;
        default:
          return false;
      }
    }
    case CorElementType::ELEMENT_TYPE_U2: {
      switch (target_type) {
        case CorElementType::ELEMENT_TYPE_U2:
        case CorElementType::ELEMENT_TYPE_I4:
        case CorElementType::ELEMENT_TYPE_U4:
        case CorElementType::ELEMENT_TYPE_I8:
        case CorElementType::ELEMENT_TYPE_U8:
        case CorElementType::ELEMENT_TYPE_R4:
        case CorElementType::ELEMENT_TYPE_R8:
          return true;
        default:
          return false;
      }
    }
    case CorElementType::ELEMENT_TYPE_I4: {
      switch (target_type) {
        case CorElementType::ELEMENT_TYPE_I4:
        case CorElementType::ELEMENT_TYPE_I8:
        case CorElementType::ELEMENT_TYPE_R4:
        case CorElementType::ELEMENT_TYPE_R8:
          return true;
        default:
          return false;
      }
    }
    case CorElementType::ELEMENT_TYPE_U4: {
      switch (target_type) {
        case CorElementType::ELEMENT_TYPE_U4:
        case CorElementType::ELEMENT_TYPE_I8:
        case CorElementType::ELEMENT_TYPE_U8:
        case CorElementType::ELEMENT_TYPE_R4:
        case CorElementType::ELEMENT_TYPE_R8:
          return true;
        default:
          return false;
      }
    }
    case CorElementType::ELEMENT_TYPE_I8: {
      switch (target_type) {
        case CorElementType::ELEMENT_TYPE_I8:
        case CorElementType::ELEMENT_TYPE_R4:
        case CorElementType::ELEMENT_TYPE_R8:
          return true;
        default:
          return false;
      }
    }
    case CorElementType::ELEMENT_TYPE_U8: {
      switch (target_type) {
        case CorElementType::ELEMENT_TYPE_U8:
        case CorElementType::ELEMENT_TYPE_R4:
        case CorElementType::ELEMENT_TYPE_R8:
          return true;
        default:
          return false;
      }
    }
    case CorElementType::ELEMENT_TYPE_CHAR: {
      switch (target_type) {
        case CorElementType::ELEMENT_TYPE_CHAR:
        case CorElementType::ELEMENT_TYPE_U2:
        case CorElementType::ELEMENT_TYPE_I4:
        case CorElementType::ELEMENT_TYPE_U4:
        case CorElementType::ELEMENT_TYPE_I8:
        case CorElementType::ELEMENT_TYPE_U8:
        case CorElementType::ELEMENT_TYPE_R4:
        case CorElementType::ELEMENT_TYPE_R8:
          return true;
        default:
          return false;
      }
    }
    case CorElementType::ELEMENT_TYPE_R4: {
      switch (target_type) {
        case CorElementType::ELEMENT_TYPE_R4:
        case CorElementType::ELEMENT_TYPE_R8:
          return true;
        default:
          return false;
      }
    }
    case CorElementType::ELEMENT_TYPE_R8: {
      switch (target_type) {
        case CorElementType::ELEMENT_TYPE_R8:
          return true;
        default:
          return false;
      }
    }
    default:
      return false;
  }
}

bool NumericCompilerHelper::IsNumericallyPromotedToInt(
    const CorElementType &source) {
  return source == CorElementType::ELEMENT_TYPE_CHAR ||
         source == CorElementType::ELEMENT_TYPE_I1 ||
         source == CorElementType::ELEMENT_TYPE_U1 ||
         source == CorElementType::ELEMENT_TYPE_I2;
}

// Returns true for I1, I2, I4 and I8 types.
inline bool IsSignedIntegralType(const CorElementType &element_type) {
  return element_type == CorElementType::ELEMENT_TYPE_I1 ||
         element_type == CorElementType::ELEMENT_TYPE_I2 ||
         element_type == CorElementType::ELEMENT_TYPE_I4 ||
         element_type == CorElementType::ELEMENT_TYPE_I8;
}

bool NumericCompilerHelper::BinaryNumericalPromotion(const CorElementType &arg1,
                                                     const CorElementType &arg2,
                                                     CorElementType *result,
                                                     std::ostream *err_stream) {
  if (!TypeCompilerHelper::IsNumericalType(arg1) &&
      !TypeCompilerHelper::IsNumericalType(arg2)) {
    *err_stream << "Both arguments has to be of numerical types.";
    return false;
  }

  // TODO(quoct): Add support for Decimal.
  if (arg1 == CorElementType::ELEMENT_TYPE_R8 ||
      arg2 == CorElementType::ELEMENT_TYPE_R8) {
    *result = CorElementType::ELEMENT_TYPE_R8;
    return true;
  } else if (arg1 == CorElementType::ELEMENT_TYPE_R4 ||
             arg2 == CorElementType::ELEMENT_TYPE_R4) {
    *result = CorElementType::ELEMENT_TYPE_R4;
    return true;
  } else if (arg1 == CorElementType::ELEMENT_TYPE_U8 ||
             arg2 == CorElementType::ELEMENT_TYPE_U8) {
    // If the other operand is of type sbyte, short, int or long,
    // an error will occur. This is because no integral type exists that can
    // represent the full range of ulong as well as the signed integral types.
    if (IsSignedIntegralType(arg1) || IsSignedIntegralType(arg2)) {
      *err_stream << "If one of the argument is an unsigned long, "
                  << "the other cannot be a signed integral type.";
      return false;
    }
    *result = CorElementType::ELEMENT_TYPE_U8;
    return true;
  } else if (arg1 == CorElementType::ELEMENT_TYPE_I8 ||
             arg2 == CorElementType::ELEMENT_TYPE_I8) {
    *result = CorElementType::ELEMENT_TYPE_I8;
    return true;
  } else if (arg1 == CorElementType::ELEMENT_TYPE_U4 ||
             arg2 == CorElementType::ELEMENT_TYPE_U4) {
    // If 1 of the operand is sbyte, short or int,
    // the result will be long. We can simply call
    // IsSignedIntegralType without worrying about arg1
    // being an I8 type because that is already checked above.
    if (IsSignedIntegralType(arg1)) {
      *result = CorElementType::ELEMENT_TYPE_I8;
      return true;
    }

    if (IsSignedIntegralType(arg2)) {
      *result = CorElementType::ELEMENT_TYPE_I8;
      return true;
    }

    *result = CorElementType::ELEMENT_TYPE_U4;
    return true;
  } else {
    // Otherwise, both operands are converted to int.
    *result = CorElementType::ELEMENT_TYPE_I4;
    return true;
  }
}

bool TypeCompilerHelper::IsNumericalType(const CorElementType &cor_type) {
  return IsIntegralType(cor_type) ||
         cor_type == CorElementType::ELEMENT_TYPE_R4 ||
         cor_type == CorElementType::ELEMENT_TYPE_R8;
}

bool TypeCompilerHelper::IsIntegralType(const CorElementType &cor_type) {
  return cor_type == CorElementType::ELEMENT_TYPE_I1 ||
         cor_type == CorElementType::ELEMENT_TYPE_U1 ||
         cor_type == CorElementType::ELEMENT_TYPE_I2 ||
         cor_type == CorElementType::ELEMENT_TYPE_U2 ||
         cor_type == CorElementType::ELEMENT_TYPE_I4 ||
         cor_type == CorElementType::ELEMENT_TYPE_U4 ||
         cor_type == CorElementType::ELEMENT_TYPE_I8 ||
         cor_type == CorElementType::ELEMENT_TYPE_U8 ||
         cor_type == CorElementType::ELEMENT_TYPE_CHAR;
}

bool TypeCompilerHelper::IsArrayType(const CorElementType &array_type) {
  return array_type == CorElementType::ELEMENT_TYPE_ARRAY ||
         array_type == CorElementType::ELEMENT_TYPE_SZARRAY;
}

bool TypeCompilerHelper::IsObjectType(const CorElementType &cor_type) {
  return cor_type == CorElementType::ELEMENT_TYPE_OBJECT ||
         cor_type == CorElementType::ELEMENT_TYPE_CLASS ||
         cor_type == CorElementType::ELEMENT_TYPE_VALUETYPE;
}

CorElementType TypeCompilerHelper::ConvertStringToCorElementType(
    const std::string &type_string) {
  static std::unordered_map<std::string, CorElementType> string_to_cor_type{
      {kCharClassName, CorElementType::ELEMENT_TYPE_BOOLEAN},
      {kSByteClassName, CorElementType::ELEMENT_TYPE_I1},
      {kCharClassName, CorElementType::ELEMENT_TYPE_CHAR},
      {kByteClassName, CorElementType::ELEMENT_TYPE_U1},
      {kInt16ClassName, CorElementType::ELEMENT_TYPE_I2},
      {kUInt16ClassName, CorElementType::ELEMENT_TYPE_U2},
      {kInt32ClassName, CorElementType::ELEMENT_TYPE_I4},
      {kUInt32ClassName, CorElementType::ELEMENT_TYPE_U4},
      {kInt64ClassName, CorElementType::ELEMENT_TYPE_I8},
      {kUInt64ClassName, CorElementType::ELEMENT_TYPE_U8},
      {kStringClassName, CorElementType::ELEMENT_TYPE_STRING},
      {kObjectClassName, CorElementType::ELEMENT_TYPE_OBJECT}};

  if (string_to_cor_type.find(type_string) != string_to_cor_type.end()) {
    return string_to_cor_type[type_string];
  } else {
    auto open_bracket = type_string.find("[");
    if (open_bracket == std::string::npos) {
      return CorElementType::ELEMENT_TYPE_OBJECT;
    }

    auto closing_bracket = type_string.find("]");
    if (closing_bracket == std::string::npos ||
        closing_bracket < open_bracket) {
      return CorElementType::ELEMENT_TYPE_OBJECT;
    }

    // This means the type is something like System.Int32[],
    // which represents a simple array.
    if (open_bracket + 1 == closing_bracket) {
      return CorElementType::ELEMENT_TYPE_SZARRAY;
    }

    // This means the type is something like System.Int32[,], which is
    // a multidimensional array.
    return CorElementType::ELEMENT_TYPE_ARRAY;
  }
}

struct CorElementTypeHash {
  std::size_t operator()(CorElementType cor_type) const {
    return static_cast<std::size_t>(cor_type);
  }
};

HRESULT TypeCompilerHelper::ConvertCorElementTypeToString(
    const CorElementType &cor_type, std::string *result) {
  static std::unordered_map<CorElementType, std::string, CorElementTypeHash> cor_type_to_string{
      {CorElementType::ELEMENT_TYPE_BOOLEAN, kBooleanClassName},
      {CorElementType::ELEMENT_TYPE_I1, kSByteClassName},
      {CorElementType::ELEMENT_TYPE_CHAR, kCharClassName},
      {CorElementType::ELEMENT_TYPE_U1, kByteClassName},
      {CorElementType::ELEMENT_TYPE_I2, kInt16ClassName},
      {CorElementType::ELEMENT_TYPE_U2, kUInt16ClassName},
      {CorElementType::ELEMENT_TYPE_I4, kInt32ClassName},
      {CorElementType::ELEMENT_TYPE_U4, kUInt32ClassName},
      {CorElementType::ELEMENT_TYPE_I8, kInt64ClassName},
      {CorElementType::ELEMENT_TYPE_U8, kUInt64ClassName},
      {CorElementType::ELEMENT_TYPE_R4, kSingleClassName},
      {CorElementType::ELEMENT_TYPE_R8, kDoubleClassName},
      {CorElementType::ELEMENT_TYPE_I, kIntPtrClassName},
      {CorElementType::ELEMENT_TYPE_U, kUIntPtrClassName},
      {CorElementType::ELEMENT_TYPE_STRING, kStringClassName},
      {CorElementType::ELEMENT_TYPE_OBJECT, kObjectClassName}};

  if (result == nullptr) {
    return E_INVALIDARG;
  }

  if (cor_type_to_string.find(cor_type) != cor_type_to_string.end()) {
    *result = cor_type_to_string[cor_type];
    return S_OK;
  }

  return E_FAIL;
}

HRESULT TypeCompilerHelper::IsBaseClass(
    mdTypeDef source_class, IMetaDataImport *source_class_metadata,
    const std::vector<CComPtr<ICorDebugAssembly>> &loaded_assemblies,
    const std::string &target_class, ICorDebugHelper *debug_helper,
    std::ostream *err_stream) {
  HRESULT hr;
  mdTypeDef current_class_token = source_class;
  CComPtr<IMetaDataImport> current_metadata_import;
  std::string current_class_name;
  mdToken current_base_class_token = source_class;

  current_metadata_import = source_class_metadata;
  int max_class_to_traverse = 10;
  while (max_class_to_traverse >= 0) {
    max_class_to_traverse -= 1;
    hr = debug_helper->GetTypeNameFromMdTypeDef(
        current_class_token, current_metadata_import, &current_class_name,
        &current_base_class_token, err_stream);
    if (FAILED(hr)) {
      return hr;
    }

    if (current_class_name.compare(target_class) == 0) {
      return S_OK;
    }

    if (current_class_name.compare(kObjectClassName)) {
      return E_FAIL;
    }

    // Retrieves the base class token and metadata import.
    CorTokenType token_type =
        (CorTokenType)(TypeFromToken(current_base_class_token));
    if (token_type == CorTokenType::mdtTypeDef) {
      // No need to change the IMetaDataImport since we are still in the same
      // module.
      current_class_token = current_base_class_token;
    } else if (token_type == CorTokenType::mdtTypeRef) {
      CComPtr<IMetaDataImport> resolved_metadata_import;
      mdTypeDef resolved_class_token;
      hr = debug_helper->GetMdTypeDefAndMetaDataFromTypeRef(
          current_base_class_token, loaded_assemblies, current_metadata_import,
          &resolved_class_token, &resolved_metadata_import, err_stream);
      if (FAILED(hr)) {
        return hr;
      }

      current_class_token = resolved_class_token;
      current_metadata_import = resolved_metadata_import;
    } else {
      // Not supported.
      *err_stream << "Only mdTypeDef and mdTypeRef tokens are supported.";
      return E_NOTIMPL;
    }
  }

  return E_FAIL;
}

}  //  namespace google_cloud_debugger
<|endoftext|>


<commit_before>
#ifndef MANIFOLDS_FUNCTIONS_UNARY_MINUS_HH
#define MANIFOLDS_FUNCTIONS_UNARY_MINUS_HH

#include "full_function_defs.hh"
#include "function.hh"

namespace manifolds {

template <class Func>
struct UnaryMinus : Function<list<int_<24>, typename Func::indices>,
                             Func::input_dim, Func::output_dim>,
                    FunctionCommon<UnaryMinus<Func> > {
  static const bool stateless = is_stateless<Func>::value;
  static const ComplexOutputBehaviour complex_output = SameAsInput;
  UnaryMinus() {}
  UnaryMinus(const Func &f) : f(f) {}

  template <class... Args> auto eval(Args... args) const { return -f(args...); }

  auto GetFunction() const { return f; }

  auto GetFunctions() const { return make_my_tuple(f); }

private:
  Func f;
};

template <class T, class U> bool operator==(UnaryMinus<T>, U) { return false; }

template <class T> bool operator==(UnaryMinus<T> u1, UnaryMinus<T> u2) {
  return u1.GetFunction() == u2.GetFunction();
}
}
#endif
<commit_msg>clang-format<commit_after>
#ifndef MANIFOLDS_FUNCTIONS_UNARY_MINUS_HH
#define MANIFOLDS_FUNCTIONS_UNARY_MINUS_HH

#include "full_function_defs.hh"
#include "function.hh"

namespace manifolds {

template <class Func>
struct UnaryMinus : Function<list<int_<24>, typename Func::indices>,
                             Func::input_dim, Func::output_dim>,
                    FunctionCommon<UnaryMinus<Func> > {
  static const bool stateless = is_stateless<Func>::value;
  static const ComplexOutputBehaviour complex_output = SameAsInput;
  UnaryMinus() {}
  UnaryMinus(const Func &f) : f(f) {}

  template <class... Args> auto eval(Args... args) const { return -f(args...); }

  auto GetFunction() const { return f; }

  auto GetFunctions() const { return make_my_tuple(f); }

private:
  Func f;
};

template <class T, class U> bool operator==(UnaryMinus<T>, U) { return false; }

template <class T> bool operator==(UnaryMinus<T> u1, UnaryMinus<T> u2) {
  return u1.GetFunction() == u2.GetFunction();
}

template <class F> UnaryMinus<F> Negative(F f) { return UnaryMinus<F>(f); }
}
#endif
<|endoftext|>


<commit_before>///////////////////////////////////////////////////////////////////////////////////////////////////
// OpenGL Mathematics Copyright (c) 2005 - 2013 G-Truc Creation (www.g-truc.net)
///////////////////////////////////////////////////////////////////////////////////////////////////
// Created : 2005-12-21
// Updated : 2007-08-14
// Licence : This source is under MIT License
// File    : glm/gtx/euler_angles.inl
///////////////////////////////////////////////////////////////////////////////////////////////////

namespace glm
{
	template <typename T>
	GLM_FUNC_QUALIFIER detail::tmat4x4<T, defaultp> eulerAngleX
	(
		T const & angleX
	)
	{
		T cosX = glm::cos(angleX);
		T sinX = glm::sin(angleX);

		return detail::tmat4x4<T, defaultp>(
			T(1), T(0), T(0), T(0),
			T(0), cosX, sinX, T(0),
			T(0),-sinX, cosX, T(0),
			T(0), T(0), T(0), T(1));
	}

	template <typename T>
	GLM_FUNC_QUALIFIER detail::tmat4x4<T, defaultp> eulerAngleY
	(
		T const & angleY
	)
	{
		T cosY = glm::cos(angleY);
		T sinY = glm::sin(angleY);

		return detail::tmat4x4<T, defaultp>(
			cosY,	T(0),	sinY,	T(0),
			T(0),	T(1),	T(0),	T(0),
			-sinY,	T(0),	cosY,	T(0),
			T(0),	T(0),	T(0),	T(1));
	}

	template <typename T>
	GLM_FUNC_QUALIFIER detail::tmat4x4<T, defaultp> eulerAngleZ
	(
		T const & angleZ
	)
	{
		T cosZ = glm::cos(angleZ);
		T sinZ = glm::sin(angleZ);

		return detail::tmat4x4<T, defaultp>(
			cosZ,	sinZ,	T(0), T(0),
			-sinZ,	cosZ,	T(0), T(0),
			T(0),	T(0),	T(1), T(0),
			T(0),	T(0),	T(0), T(1));
	}

	template <typename T>
	GLM_FUNC_QUALIFIER detail::tmat4x4<T, defaultp> eulerAngleXY
	(
		T const & angleX,
		T const & angleY
	)
	{
		T cosX = glm::cos(angleX);
		T sinX = glm::sin(angleX);
		T cosY = glm::cos(angleY);
		T sinY = glm::sin(angleY);

		return detail::tmat4x4<T, defaultp>(
			cosY,	-sinX * sinY,	cosX * sinY,	T(0),
			T(0),	cosX,			sinX,			T(0),
			-sinY,	-sinX * cosY,	cosX * cosY,	T(0),
			T(0),	T(0),			T(0),			T(1));
	}

	template <typename T>
	GLM_FUNC_QUALIFIER detail::tmat4x4<T, defaultp> eulerAngleYX
	(
		T const & angleY,
		T const & angleX
	)
	{
		T cosX = glm::cos(angleX);
		T sinX = glm::sin(angleX);
		T cosY = glm::cos(angleY);
		T sinY = glm::sin(angleY);

		return detail::tmat4x4<T, defaultp>(
			cosY,			T(0),		sinY,			T(0),
			-sinX * sinY,	cosX,		sinX * cosY,	T(0),
			-cosX * sinY,	-sinX,		cosX * cosY,	T(0),
			T(0),			T(0),		T(0),			T(1));
	}

	template <typename T>
	GLM_FUNC_QUALIFIER detail::tmat4x4<T, defaultp> eulerAngleXZ
	(
		T const & angleX,
		T const & angleZ
	)
	{
		return eulerAngleX(angleX) * eulerAngleZ(angleZ);
	}

	template <typename T>
	GLM_FUNC_QUALIFIER detail::tmat4x4<T, defaultp> eulerAngleZX
	(
		T const & angleZ,
		T const & angleX
	)
	{
		return eulerAngleZ(angleZ) * eulerAngleX(angleX);
	}

	template <typename T>
	GLM_FUNC_QUALIFIER detail::tmat4x4<T, defaultp> eulerAngleYXZ
	(
		T const & yaw,
		T const & pitch,
		T const & roll
	)
	{
		T tmp_ch = glm::cos(yaw);
		T tmp_sh = glm::sin(yaw);
		T tmp_cp = glm::cos(pitch);
		T tmp_sp = glm::sin(pitch);
		T tmp_cb = glm::cos(roll);
		T tmp_sb = glm::sin(roll);

		detail::tmat4x4<T, defaultp> Result;
		Result[0][0] = tmp_ch * tmp_cb + tmp_sh * tmp_sp * tmp_sb;
		Result[0][1] = tmp_sb * tmp_cp;
		Result[0][2] = -tmp_sh * tmp_cb + tmp_ch * tmp_sp * tmp_sb;
		Result[0][3] = static_cast<T>(0);
		Result[1][0] = -tmp_ch * tmp_sb + tmp_sh * tmp_sp * tmp_cb;
		Result[1][1] = tmp_cb * tmp_cp;
		Result[1][2] = tmp_sb * tmp_sh + tmp_ch * tmp_sp * tmp_cb;
		Result[1][3] = static_cast<T>(0);
		Result[2][0] = tmp_sh * tmp_cp;
		Result[2][1] = -tmp_sp;
		Result[2][2] = tmp_ch * tmp_cp;
		Result[2][3] = static_cast<T>(0);
		Result[3][0] = static_cast<T>(0);
		Result[3][1] = static_cast<T>(0);
		Result[3][2] = static_cast<T>(0);
		Result[3][3] = static_cast<T>(1);
		return Result;
	}

	template <typename T>
	GLM_FUNC_QUALIFIER detail::tmat4x4<T, defaultp> yawPitchRoll
	(
		T const & yaw,
		T const & pitch,
		T const & roll
	)
	{
		T tmp_ch = glm::cos(yaw);
		T tmp_sh = glm::sin(yaw);
		T tmp_cp = glm::cos(pitch);
		T tmp_sp = glm::sin(pitch);
		T tmp_cb = glm::cos(roll);
		T tmp_sb = glm::sin(roll);

		detail::tmat4x4<T, defaultp> Result;
		Result[0][0] = tmp_ch * tmp_cb + tmp_sh * tmp_sp * tmp_sb;
		Result[0][1] = tmp_sb * tmp_cp;
		Result[0][2] = -tmp_sh * tmp_cb + tmp_ch * tmp_sp * tmp_sb;
		Result[0][3] = static_cast<T>(0);
		Result[1][0] = -tmp_ch * tmp_sb + tmp_sh * tmp_sp * tmp_cb;
		Result[1][1] = tmp_cb * tmp_cp;
		Result[1][2] = tmp_sb * tmp_sh + tmp_ch * tmp_sp * tmp_cb;
		Result[1][3] = static_cast<T>(0);
		Result[2][0] = tmp_sh * tmp_cp;
		Result[2][1] = -tmp_sp;
		Result[2][2] = tmp_ch * tmp_cp;
		Result[2][3] = static_cast<T>(0);
		Result[3][0] = static_cast<T>(0);
		Result[3][1] = static_cast<T>(0);
		Result[3][2] = static_cast<T>(0);
		Result[3][3] = static_cast<T>(1);
		return Result;
	}

	template <typename T>
	GLM_FUNC_QUALIFIER detail::tmat2x2<T, defaultp> orientate2
	(
		T const & angle
	)
	{
		T c = glm::cos(angle);
		T s = glm::sin(angle);

		detail::tmat2x2<T, defaultp> Result;
		Result[0][0] = c;
		Result[0][1] = s;
		Result[1][0] = -s;
		Result[1][1] = c;
		return Result;
	}

	template <typename T>
	GLM_FUNC_QUALIFIER detail::tmat3x3<T, defaultp> orientate3
	(
		T const & angle
	)
	{
		T c = glm::cos(angle);
		T s = glm::sin(angle);

		detail::tmat3x3<T, defaultp> Result;
		Result[0][0] = c;
		Result[0][1] = s;
		Result[0][2] = 0.0f;
		Result[1][0] = -s;
		Result[1][1] = c;
		Result[1][2] = 0.0f;
		Result[2][0] = 0.0f;
		Result[2][1] = 0.0f;
		Result[2][2] = 1.0f;
		return Result;
	}

	template <typename T, precision P>
	GLM_FUNC_QUALIFIER detail::tmat3x3<T, P> orientate3
	(
		detail::tvec3<T, P> const & angles
	)
	{
		return detail::tmat3x3<T, P>(yawPitchRoll(angles.x, angles.y, angles.z));
	}

	template <typename T, precision P>
	GLM_FUNC_QUALIFIER detail::tmat4x4<T, P> orientate4
	(
		detail::tvec3<T, P> const & angles
	)
	{
		return yawPitchRoll(angles.z, angles.x, angles.y);
	}
}//namespace glm
<commit_msg>Changed sign for eulerAngleY to make it consistent with the others<commit_after>///////////////////////////////////////////////////////////////////////////////////////////////////
// OpenGL Mathematics Copyright (c) 2005 - 2013 G-Truc Creation (www.g-truc.net)
///////////////////////////////////////////////////////////////////////////////////////////////////
// Created : 2005-12-21
// Updated : 2007-08-14
// Licence : This source is under MIT License
// File    : glm/gtx/euler_angles.inl
///////////////////////////////////////////////////////////////////////////////////////////////////

namespace glm
{
	template <typename T>
	GLM_FUNC_QUALIFIER detail::tmat4x4<T, defaultp> eulerAngleX
	(
		T const & angleX
	)
	{
		T cosX = glm::cos(angleX);
		T sinX = glm::sin(angleX);

		return detail::tmat4x4<T, defaultp>(
			T(1), T(0), T(0), T(0),
			T(0), cosX, sinX, T(0),
			T(0),-sinX, cosX, T(0),
			T(0), T(0), T(0), T(1));
	}

	template <typename T>
	GLM_FUNC_QUALIFIER detail::tmat4x4<T, defaultp> eulerAngleY
	(
		T const & angleY
	)
	{
		T cosY = glm::cos(angleY);
		T sinY = glm::sin(angleY);

		return detail::tmat4x4<T, defaultp>(
			cosY,	T(0),	-sinY,	T(0),
			T(0),	T(1),	T(0),	T(0),
			sinY,	T(0),	cosY,	T(0),
			T(0),	T(0),	T(0),	T(1));
	}

	template <typename T>
	GLM_FUNC_QUALIFIER detail::tmat4x4<T, defaultp> eulerAngleZ
	(
		T const & angleZ
	)
	{
		T cosZ = glm::cos(angleZ);
		T sinZ = glm::sin(angleZ);

		return detail::tmat4x4<T, defaultp>(
			cosZ,	sinZ,	T(0), T(0),
			-sinZ,	cosZ,	T(0), T(0),
			T(0),	T(0),	T(1), T(0),
			T(0),	T(0),	T(0), T(1));
	}

	template <typename T>
	GLM_FUNC_QUALIFIER detail::tmat4x4<T, defaultp> eulerAngleXY
	(
		T const & angleX,
		T const & angleY
	)
	{
		T cosX = glm::cos(angleX);
		T sinX = glm::sin(angleX);
		T cosY = glm::cos(angleY);
		T sinY = glm::sin(angleY);

		return detail::tmat4x4<T, defaultp>(
			cosY,	-sinX * sinY,	cosX * sinY,	T(0),
			T(0),	cosX,			sinX,			T(0),
			-sinY,	-sinX * cosY,	cosX * cosY,	T(0),
			T(0),	T(0),			T(0),			T(1));
	}

	template <typename T>
	GLM_FUNC_QUALIFIER detail::tmat4x4<T, defaultp> eulerAngleYX
	(
		T const & angleY,
		T const & angleX
	)
	{
		T cosX = glm::cos(angleX);
		T sinX = glm::sin(angleX);
		T cosY = glm::cos(angleY);
		T sinY = glm::sin(angleY);

		return detail::tmat4x4<T, defaultp>(
			cosY,			T(0),		sinY,			T(0),
			-sinX * sinY,	cosX,		sinX * cosY,	T(0),
			-cosX * sinY,	-sinX,		cosX * cosY,	T(0),
			T(0),			T(0),		T(0),			T(1));
	}

	template <typename T>
	GLM_FUNC_QUALIFIER detail::tmat4x4<T, defaultp> eulerAngleXZ
	(
		T const & angleX,
		T const & angleZ
	)
	{
		return eulerAngleX(angleX) * eulerAngleZ(angleZ);
	}

	template <typename T>
	GLM_FUNC_QUALIFIER detail::tmat4x4<T, defaultp> eulerAngleZX
	(
		T const & angleZ,
		T const & angleX
	)
	{
		return eulerAngleZ(angleZ) * eulerAngleX(angleX);
	}

	template <typename T>
	GLM_FUNC_QUALIFIER detail::tmat4x4<T, defaultp> eulerAngleYXZ
	(
		T const & yaw,
		T const & pitch,
		T const & roll
	)
	{
		T tmp_ch = glm::cos(yaw);
		T tmp_sh = glm::sin(yaw);
		T tmp_cp = glm::cos(pitch);
		T tmp_sp = glm::sin(pitch);
		T tmp_cb = glm::cos(roll);
		T tmp_sb = glm::sin(roll);

		detail::tmat4x4<T, defaultp> Result;
		Result[0][0] = tmp_ch * tmp_cb + tmp_sh * tmp_sp * tmp_sb;
		Result[0][1] = tmp_sb * tmp_cp;
		Result[0][2] = -tmp_sh * tmp_cb + tmp_ch * tmp_sp * tmp_sb;
		Result[0][3] = static_cast<T>(0);
		Result[1][0] = -tmp_ch * tmp_sb + tmp_sh * tmp_sp * tmp_cb;
		Result[1][1] = tmp_cb * tmp_cp;
		Result[1][2] = tmp_sb * tmp_sh + tmp_ch * tmp_sp * tmp_cb;
		Result[1][3] = static_cast<T>(0);
		Result[2][0] = tmp_sh * tmp_cp;
		Result[2][1] = -tmp_sp;
		Result[2][2] = tmp_ch * tmp_cp;
		Result[2][3] = static_cast<T>(0);
		Result[3][0] = static_cast<T>(0);
		Result[3][1] = static_cast<T>(0);
		Result[3][2] = static_cast<T>(0);
		Result[3][3] = static_cast<T>(1);
		return Result;
	}

	template <typename T>
	GLM_FUNC_QUALIFIER detail::tmat4x4<T, defaultp> yawPitchRoll
	(
		T const & yaw,
		T const & pitch,
		T const & roll
	)
	{
		T tmp_ch = glm::cos(yaw);
		T tmp_sh = glm::sin(yaw);
		T tmp_cp = glm::cos(pitch);
		T tmp_sp = glm::sin(pitch);
		T tmp_cb = glm::cos(roll);
		T tmp_sb = glm::sin(roll);

		detail::tmat4x4<T, defaultp> Result;
		Result[0][0] = tmp_ch * tmp_cb + tmp_sh * tmp_sp * tmp_sb;
		Result[0][1] = tmp_sb * tmp_cp;
		Result[0][2] = -tmp_sh * tmp_cb + tmp_ch * tmp_sp * tmp_sb;
		Result[0][3] = static_cast<T>(0);
		Result[1][0] = -tmp_ch * tmp_sb + tmp_sh * tmp_sp * tmp_cb;
		Result[1][1] = tmp_cb * tmp_cp;
		Result[1][2] = tmp_sb * tmp_sh + tmp_ch * tmp_sp * tmp_cb;
		Result[1][3] = static_cast<T>(0);
		Result[2][0] = tmp_sh * tmp_cp;
		Result[2][1] = -tmp_sp;
		Result[2][2] = tmp_ch * tmp_cp;
		Result[2][3] = static_cast<T>(0);
		Result[3][0] = static_cast<T>(0);
		Result[3][1] = static_cast<T>(0);
		Result[3][2] = static_cast<T>(0);
		Result[3][3] = static_cast<T>(1);
		return Result;
	}

	template <typename T>
	GLM_FUNC_QUALIFIER detail::tmat2x2<T, defaultp> orientate2
	(
		T const & angle
	)
	{
		T c = glm::cos(angle);
		T s = glm::sin(angle);

		detail::tmat2x2<T, defaultp> Result;
		Result[0][0] = c;
		Result[0][1] = s;
		Result[1][0] = -s;
		Result[1][1] = c;
		return Result;
	}

	template <typename T>
	GLM_FUNC_QUALIFIER detail::tmat3x3<T, defaultp> orientate3
	(
		T const & angle
	)
	{
		T c = glm::cos(angle);
		T s = glm::sin(angle);

		detail::tmat3x3<T, defaultp> Result;
		Result[0][0] = c;
		Result[0][1] = s;
		Result[0][2] = 0.0f;
		Result[1][0] = -s;
		Result[1][1] = c;
		Result[1][2] = 0.0f;
		Result[2][0] = 0.0f;
		Result[2][1] = 0.0f;
		Result[2][2] = 1.0f;
		return Result;
	}

	template <typename T, precision P>
	GLM_FUNC_QUALIFIER detail::tmat3x3<T, P> orientate3
	(
		detail::tvec3<T, P> const & angles
	)
	{
		return detail::tmat3x3<T, P>(yawPitchRoll(angles.x, angles.y, angles.z));
	}

	template <typename T, precision P>
	GLM_FUNC_QUALIFIER detail::tmat4x4<T, P> orientate4
	(
		detail::tvec3<T, P> const & angles
	)
	{
		return yawPitchRoll(angles.z, angles.x, angles.y);
	}
}//namespace glm
<|endoftext|>


<commit_before>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * Modified by ScyllaDB
 * Copyright 2015 ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "gms/application_state.hh"
#include <seastar/core/sstring.hh>
#include <ostream>
#include <map>
#include "seastarx.hh"

namespace gms {

static const std::map<application_state, sstring> application_state_names = {
    {application_state::STATUS,                 "STATUS"},
    {application_state::LOAD,                   "LOAD"},
    {application_state::SCHEMA,                 "SCHEMA"},
    {application_state::DC,                     "DC"},
    {application_state::RACK,                   "RACK"},
    {application_state::RELEASE_VERSION,        "RELEASE_VERSION"},
    {application_state::REMOVAL_COORDINATOR,    "REMOVAL_COORDINATOR"},
    {application_state::INTERNAL_IP,            "INTERNAL_IP"},
    {application_state::RPC_ADDRESS,            "RPC_ADDRESS"},
    {application_state::SEVERITY,               "SEVERITY"},
    {application_state::NET_VERSION,            "NET_VERSION"},
    {application_state::HOST_ID,                "HOST_ID"},
    {application_state::TOKENS,                 "TOKENS"},
    {application_state::SUPPORTED_FEATURES,     "SUPPORTED_FEATURES"},
    {application_state::CACHE_HITRATES,         "CACHE_HITRATES"},
};

std::ostream& operator<<(std::ostream& os, const application_state& m) {
    auto it = application_state_names.find(m);
    if (it != application_state_names.end()) {
        os << application_state_names.at(m);
    } else {
        os << "UNKNOWN";
    }
    return os;
}

}

<commit_msg>gossip: Print SCHEMA_TABLES_VERSION correctly<commit_after>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * Modified by ScyllaDB
 * Copyright 2015 ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "gms/application_state.hh"
#include <seastar/core/sstring.hh>
#include <ostream>
#include <map>
#include "seastarx.hh"

namespace gms {

static const std::map<application_state, sstring> application_state_names = {
    {application_state::STATUS,                 "STATUS"},
    {application_state::LOAD,                   "LOAD"},
    {application_state::SCHEMA,                 "SCHEMA"},
    {application_state::DC,                     "DC"},
    {application_state::RACK,                   "RACK"},
    {application_state::RELEASE_VERSION,        "RELEASE_VERSION"},
    {application_state::REMOVAL_COORDINATOR,    "REMOVAL_COORDINATOR"},
    {application_state::INTERNAL_IP,            "INTERNAL_IP"},
    {application_state::RPC_ADDRESS,            "RPC_ADDRESS"},
    {application_state::SEVERITY,               "SEVERITY"},
    {application_state::NET_VERSION,            "NET_VERSION"},
    {application_state::HOST_ID,                "HOST_ID"},
    {application_state::TOKENS,                 "TOKENS"},
    {application_state::SUPPORTED_FEATURES,     "SUPPORTED_FEATURES"},
    {application_state::CACHE_HITRATES,         "CACHE_HITRATES"},
    {application_state::SCHEMA_TABLES_VERSION,  "SCHEMA_TABLES_VERSION"},
};

std::ostream& operator<<(std::ostream& os, const application_state& m) {
    auto it = application_state_names.find(m);
    if (it != application_state_names.end()) {
        os << application_state_names.at(m);
    } else {
        os << "UNKNOWN";
    }
    return os;
}

}

<|endoftext|>


<commit_before>/*
 * WindowTestLayer.cpp
 *
 *  Created on: Sep 27, 2011
 *      Author: slundquist
 */

#include "WindowTestLayer.hpp"
#include <utils/conversions.h>

namespace PV {

WindowTestLayer::WindowTestLayer(const char * name, HyPerCol * hc, int numChannels) {
   initialize_base();
   initialize(name, hc, numChannels);
}

WindowTestLayer::WindowTestLayer(const char * name, HyPerCol * hc){
   initialize_base();
   initialize(name, hc, MAX_CHANNELS);
}

int WindowTestLayer::initialize_base()
{
   //windowLayerName = NULL;
   //windowLayer = NULL;
   return PV_SUCCESS;
}

int WindowTestLayer::initialize(const char * name, HyPerCol * hc, int num_channels)
{
   ANNLayer::initialize(name, hc, num_channels);
   //PVParams * params = parent->parameters();
   //windowLayerName = params->stringValue(name, "windowLayerName", NULL);
   //if (windowLayerName == NULL){
   //   fprintf(stderr, "WindowTestLayer \"%s\" error: windowLayerName must be specified.\n", name);
   //   abort();
   //}
   return PV_SUCCESS;
}

int WindowTestLayer::communicateInitInfo() {
   int status = ANNLayer::communicateInitInfo();
   //HyPerLayer * origLayer = parent->getLayerFromName(windowLayerName);
   //if (origLayer ==NULL) {
   //   fprintf(stderr, "WindowTestLayer \"%s\" error: windowLayerName \"%s\" is not a layer in the HyPerCol.\n", name, windowLayerName);
   //   abort();
   //}
   ////For now, the window information must come from HyPerLCALayer
   //windowLayer = dynamic_cast<HyPerLCALayer *>(origLayer);
   //if (windowLayer ==NULL) {
   //   fprintf(stderr, "WindowTestLayer \"%s\" error: windowLayerName \"%s\" must be a HyPerLCALayer.\n", name, windowLayerName);
   //   abort();
   //}
   return status;
}

int WindowTestLayer::allocateDataStructures() {
   int status = ANNLayer::allocateDataStructures();
   if (status==PV_SUCCESS) {
      setActivitytoOne();
   }
   return status;
}

// set activity to global x/y/f position, using position in border/margin as required
int WindowTestLayer::setActivitytoOne(){
   //Make sure window layer is the same size as current layer
   //const PVLayerLoc * windowLoc = windowLayer->getLayerLoc();
   const PVLayerLoc * thisLoc = this->getLayerLoc();
   //if(windowLoc->nx != thisLoc->nx || windowLoc->ny != thisLoc->ny || windowLoc->nf != thisLoc->nf || windowLoc->nb != thisLoc->nb){
   //   fprintf(stderr, "WindowTestLayer \"%s\" error: Size (including margins) must equal to the window layer.\n", name);
   //   abort();
   //}
   for (int kLocalExt = 0; kLocalExt < clayer->numExtended; kLocalExt++){
      //int kWindow = layerIndexExt(kLocalExt, thisLoc, windowLoc);
      //int kxGlobalExt = kxPos(kWindow, windowLoc->nx + 2*windowLoc->nb, windowLoc->ny + 2*windowLoc->nb, windowLoc->nf) + windowLoc->kx0;
      //int kyGlobalExt = kyPos(kWindow, windowLoc->nx + 2*windowLoc->nb, windowLoc->ny + 2*windowLoc->nb, windowLoc->nf) + windowLoc->ky0;
      //int kxGlobalExt = kxPos(kLocalExt, windowLoc->nx + 2*windowLoc->nb, windowLoc->ny + 2*windowLoc->nb, windowLoc->nf) + windowLoc->kx0;
      //int kyGlobalExt = kyPos(kLocalExt, windowLoc->nx + 2*windowLoc->nb, windowLoc->ny + 2*windowLoc->nb, windowLoc->nf) + windowLoc->ky0;
      //Get window from windowLayer
      //int windowId = windowLayer->calcWindow(kxGlobalExt, kyGlobalExt);
      clayer->activity->data[kLocalExt] = 1;
   }
   return PV_SUCCESS;
}

int WindowTestLayer::updateState(double timed, double dt)
{
   //updateV();
   //setActivity();
   //resetGSynBuffers();
   //updateActiveIndices();

   return PV_SUCCESS;
}

int WindowTestLayer::publish(InterColComm* comm, double timed)
{
   setActivitytoOne();
   int status = comm->publish(this, clayer->activity);
   return status;

   //return HyPerLayer::publish(comm, time);
}

} /* namespace PV */
<commit_msg>Eliminating unused-variable warning<commit_after>/*
 * WindowTestLayer.cpp
 *
 *  Created on: Sep 27, 2011
 *      Author: slundquist
 */

#include "WindowTestLayer.hpp"
#include <utils/conversions.h>

namespace PV {

WindowTestLayer::WindowTestLayer(const char * name, HyPerCol * hc, int numChannels) {
   initialize_base();
   initialize(name, hc, numChannels);
}

WindowTestLayer::WindowTestLayer(const char * name, HyPerCol * hc){
   initialize_base();
   initialize(name, hc, MAX_CHANNELS);
}

int WindowTestLayer::initialize_base()
{
   //windowLayerName = NULL;
   //windowLayer = NULL;
   return PV_SUCCESS;
}

int WindowTestLayer::initialize(const char * name, HyPerCol * hc, int num_channels)
{
   ANNLayer::initialize(name, hc, num_channels);
   //PVParams * params = parent->parameters();
   //windowLayerName = params->stringValue(name, "windowLayerName", NULL);
   //if (windowLayerName == NULL){
   //   fprintf(stderr, "WindowTestLayer \"%s\" error: windowLayerName must be specified.\n", name);
   //   abort();
   //}
   return PV_SUCCESS;
}

int WindowTestLayer::communicateInitInfo() {
   int status = ANNLayer::communicateInitInfo();
   //HyPerLayer * origLayer = parent->getLayerFromName(windowLayerName);
   //if (origLayer ==NULL) {
   //   fprintf(stderr, "WindowTestLayer \"%s\" error: windowLayerName \"%s\" is not a layer in the HyPerCol.\n", name, windowLayerName);
   //   abort();
   //}
   ////For now, the window information must come from HyPerLCALayer
   //windowLayer = dynamic_cast<HyPerLCALayer *>(origLayer);
   //if (windowLayer ==NULL) {
   //   fprintf(stderr, "WindowTestLayer \"%s\" error: windowLayerName \"%s\" must be a HyPerLCALayer.\n", name, windowLayerName);
   //   abort();
   //}
   return status;
}

int WindowTestLayer::allocateDataStructures() {
   int status = ANNLayer::allocateDataStructures();
   if (status==PV_SUCCESS) {
      setActivitytoOne();
   }
   return status;
}

// set activity to global x/y/f position, using position in border/margin as required
int WindowTestLayer::setActivitytoOne(){
   //Make sure window layer is the same size as current layer
   //const PVLayerLoc * windowLoc = windowLayer->getLayerLoc();
   //const PVLayerLoc * thisLoc = this->getLayerLoc();
   //if(windowLoc->nx != thisLoc->nx || windowLoc->ny != thisLoc->ny || windowLoc->nf != thisLoc->nf || windowLoc->nb != thisLoc->nb){
   //   fprintf(stderr, "WindowTestLayer \"%s\" error: Size (including margins) must equal to the window layer.\n", name);
   //   abort();
   //}
   for (int kLocalExt = 0; kLocalExt < clayer->numExtended; kLocalExt++){
      //int kWindow = layerIndexExt(kLocalExt, thisLoc, windowLoc);
      //int kxGlobalExt = kxPos(kWindow, windowLoc->nx + 2*windowLoc->nb, windowLoc->ny + 2*windowLoc->nb, windowLoc->nf) + windowLoc->kx0;
      //int kyGlobalExt = kyPos(kWindow, windowLoc->nx + 2*windowLoc->nb, windowLoc->ny + 2*windowLoc->nb, windowLoc->nf) + windowLoc->ky0;
      //int kxGlobalExt = kxPos(kLocalExt, windowLoc->nx + 2*windowLoc->nb, windowLoc->ny + 2*windowLoc->nb, windowLoc->nf) + windowLoc->kx0;
      //int kyGlobalExt = kyPos(kLocalExt, windowLoc->nx + 2*windowLoc->nb, windowLoc->ny + 2*windowLoc->nb, windowLoc->nf) + windowLoc->ky0;
      //Get window from windowLayer
      //int windowId = windowLayer->calcWindow(kxGlobalExt, kyGlobalExt);
      clayer->activity->data[kLocalExt] = 1;
   }
   return PV_SUCCESS;
}

int WindowTestLayer::updateState(double timed, double dt)
{
   //updateV();
   //setActivity();
   //resetGSynBuffers();
   //updateActiveIndices();

   return PV_SUCCESS;
}

int WindowTestLayer::publish(InterColComm* comm, double timed)
{
   setActivitytoOne();
   int status = comm->publish(this, clayer->activity);
   return status;

   //return HyPerLayer::publish(comm, time);
}

} /* namespace PV */
<|endoftext|>


<commit_before>#pragma once

#include "utility/memory_cast.hpp"

#include "sha3.h"

#include <assert.h>
#include <array>
#include <stdint.h>

template <size_t NBits>
class Sha3_Hasher {
public:
	inline Sha3_Hasher() noexcept {
		if constexpr (NBits == 256)
			sha3_Init256(&_c);
		else if constexpr (NBits == 384)
				sha3_Init384(&_c);
		else if constexpr (NBits == 256)
				sha3_Init512(&_c);
		else
			static_assert(NBits == 256, "The following SHA3 width is supported: 256, 384, 512 bits");
	}

	inline void update(const void * const bufIn, const size_t len) noexcept {
		assert(!_finalized);
		sha3_Update(&_c, bufIn, len);
	}

	template <typename T>
	inline void update(T&& value) noexcept {
		static_assert(std::is_trivial_v<std::remove_reference_t<T>>);
		this->update(std::addressof(value), sizeof(value));
	}

	inline std::array<uint8_t, NBits / 8> getHash() noexcept {
		assert(!_finalized);

		const void* const hashData = sha3_Finalize(&_c);
		std::array<uint8_t, NBits / 8> hashDataArray;
		::memcpy(hashDataArray.data(), hashData, hashDataArray.size());
		_finalized = true;
		return hashDataArray;
	}

	inline uint64_t get64BitHash() noexcept {
		const auto fullHash = getHash();

		uint64_t hash64 = 0;
		for (size_t offset = 0; offset < fullHash.size(); offset += sizeof(uint64_t))
		{
			const auto eightBytes = memory_cast<uint64_t>(fullHash.data() + offset);
			hash64 ^= eightBytes;
		}

		return hash64;
	}

private:
	sha3_context _c;
	bool _finalized = false;
};

inline uint64_t sha3_64bit(const void * const bufIn, const size_t len) noexcept
{
	Sha3_Hasher<256> hasher;
	hasher.update(bufIn, len);
	return hasher.get64BitHash();
}
<commit_msg>Sha3_Hasher added<commit_after>#pragma once

#include "utility/memory_cast.hpp"

#include "sha3.h"

#include <assert.h>
#include <array>
#include <stdint.h>

template <size_t NBits>
class Sha3_Hasher {
public:
	Sha3_Hasher() noexcept
	{
		if constexpr (NBits == 256)
			sha3_Init256(&_c);
		else if constexpr (NBits == 384)
			sha3_Init384(&_c);
		else if constexpr (NBits == 256)
			sha3_Init512(&_c);
		else
			static_assert(NBits == 256, "The following SHA3 width is supported: 256, 384, 512 bits");
	}

	void update(const void * const bufIn, const size_t len) noexcept
	{
		assert(!_finalized);
		if (len > 0) // it's unclear whether sha3_Update support 0 length. In fact, it seems to underflow it and enter an [almost] infinite loop.
			sha3_Update(&_c, bufIn, len);
		else
			assert(len > 0);
	}

	void update(const std::string& str) noexcept
	{
		this->update(str.data(), str.size());
	}

	template <typename T, typename = std::enable_if_t<is_trivially_serializable_v<std::remove_reference_t<T>>>>
	void update(T&& value) noexcept
	{
		static_assert(is_trivially_serializable_v<std::remove_reference_t<T>>);
		this->update(std::addressof(value), sizeof(value));
	}

	std::array<uint8_t, NBits / 8> getHash() noexcept
	{
		assert(!_finalized);

		const void* const hashData = sha3_Finalize(&_c);
		std::array<uint8_t, NBits / 8> hashDataArray;
		::memcpy(hashDataArray.data(), hashData, hashDataArray.size());
		_finalized = true;
		return hashDataArray;
	}

	uint64_t get64BitHash() noexcept
	{
		const auto fullHash = getHash();

		uint64_t hash64 = 0;
		for (size_t offset = 0; offset < fullHash.size(); offset += sizeof(uint64_t))
		{
			const auto eightBytes = memory_cast<uint64_t>(fullHash.data() + offset);
			hash64 ^= eightBytes;
		}

		return hash64;
	}

private:
	sha3_context _c;
	bool _finalized = false;
};

inline uint64_t sha3_64bit(const void * const bufIn, const size_t len) noexcept
{
	Sha3_Hasher<256> hasher;
	hasher.update(bufIn, len);
	return hasher.get64BitHash();
}
<|endoftext|>


<commit_before>/* Copyright (c) 2015 Brian R. Bondy. Distributed under the MPL2 license.
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "./hash_set_wrap.h"

namespace HashSetWrap {

using v8::Function;
using v8::FunctionCallbackInfo;
using v8::FunctionTemplate;
using v8::Isolate;
using v8::Local;
using v8::Number;
using v8::Object;
using v8::Persistent;
using v8::String;
using v8::Boolean;
using v8::Value;
using v8::NewStringType;

#if V8_MAJOR_VERSION >= 7
#define CHECK_SET(X) X.Check()
#else
#define CHECK_SET(X) (void)X
#endif

Persistent<Function> HashSetWrap::constructor;

HashSetWrap::HashSetWrap(uint32_t bucket_count, bool multi_set)
  : HashSet(bucket_count, multi_set) {
}

HashSetWrap::~HashSetWrap() {
}

void HashSetWrap::Init(Local<Object> exports) {
  Isolate* isolate = exports->GetIsolate();

  // Prepare constructor template
  Local<FunctionTemplate> tpl = FunctionTemplate::New(isolate, New);
  tpl->SetClassName(String::NewFromUtf8(isolate, "HashSet"));
  tpl->InstanceTemplate()->SetInternalFieldCount(1);

  // Prototype
  NODE_SET_PROTOTYPE_METHOD(tpl, "add", HashSetWrap::AddItem);
  NODE_SET_PROTOTYPE_METHOD(tpl, "exists", HashSetWrap::ItemExists);

  constructor.Reset(isolate,
    tpl->GetFunction(isolate->GetCurrentContext()).ToLocalChecked());
  CHECK_SET(exports->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "HashSet", NewStringType::kNormal).ToLocalChecked(),
  tpl->GetFunction(isolate->GetCurrentContext()).ToLocalChecked()));
  // exports->Set(String::NewFromUtf8(isolate, "HashSet"),
  //   tpl->GetFunction(isolate->GetCurrentContext()).ToLocalChecked());
}

void HashSetWrap::New(const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = args.GetIsolate();

  if (args.IsConstructCall()) {
    // Invoked as constructor: `new HashSet(...)`
    HashSetWrap* obj = new HashSetWrap(1024, false);
    obj->Wrap(args.This());
    args.GetReturnValue().Set(args.This());
  } else {
    // Invoked as plain function `HashSet(...)`, turn into construct call.
    const int argc = 1;
    Local<Value> argv[argc] = { args[0] };
    Local<Function> cons = Local<Function>::New(isolate, constructor);
    args.GetReturnValue().Set(
      cons->NewInstance(isolate->GetCurrentContext(), argc, argv)
        .ToLocalChecked());
  }
}

void HashSetWrap::AddItem(const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = args.GetIsolate();
  String::Utf8Value str(isolate,
    args[0]->ToString(isolate->GetCurrentContext())
      .FromMaybe(v8::Local<v8::String>()));
  const char * buffer = *str;

  HashSetWrap* obj = ObjectWrap::Unwrap<HashSetWrap>(args.Holder());
  obj->Add(ExampleData(buffer));
}

void HashSetWrap::ItemExists(const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = args.GetIsolate();
  String::Utf8Value str(isolate,
    args[0]->ToString(isolate->GetCurrentContext())
      .FromMaybe(v8::Local<v8::String>()));
  const char * buffer = *str;

  HashSetWrap* obj = ObjectWrap::Unwrap<HashSetWrap>(args.Holder());
  bool exists = obj->Exists(ExampleData(buffer));

  args.GetReturnValue().Set(Boolean::New(isolate, exists));
}

}  // namespace HashSetWrap
<commit_msg>change export setClass<commit_after>/* Copyright (c) 2015 Brian R. Bondy. Distributed under the MPL2 license.
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "./hash_set_wrap.h"

namespace HashSetWrap {

using v8::Function;
using v8::FunctionCallbackInfo;
using v8::FunctionTemplate;
using v8::Isolate;
using v8::Local;
using v8::Number;
using v8::Object;
using v8::Persistent;
using v8::String;
using v8::Boolean;
using v8::Value;
using v8::NewStringType;

#if V8_MAJOR_VERSION >= 7
#define CHECK_SET(X) X.Check()
#else
#define CHECK_SET(X) (void)X
#endif

Persistent<Function> HashSetWrap::constructor;

HashSetWrap::HashSetWrap(uint32_t bucket_count, bool multi_set)
  : HashSet(bucket_count, multi_set) {
}

HashSetWrap::~HashSetWrap() {
}

void HashSetWrap::Init(Local<Object> exports) {
  Isolate* isolate = exports->GetIsolate();

  // Prepare constructor template
  Local<FunctionTemplate> tpl = FunctionTemplate::New(isolate, New);
  //tpl->SetClassName(String::NewFromUtf8(isolate, "HashSet"));
  tpl->SetClassName(String::NewFromUtf8(isolate, "HashSet", NewStringType::kNormal).ToLocalChecked());
  tpl->InstanceTemplate()->SetInternalFieldCount(1);

  // Prototype
  NODE_SET_PROTOTYPE_METHOD(tpl, "add", HashSetWrap::AddItem);
  NODE_SET_PROTOTYPE_METHOD(tpl, "exists", HashSetWrap::ItemExists);

  constructor.Reset(isolate,
    tpl->GetFunction(isolate->GetCurrentContext()).ToLocalChecked());
  CHECK_SET(exports->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "HashSetecp", NewStringType::kNormal).ToLocalChecked(),
  tpl->GetFunction(isolate->GetCurrentContext()).ToLocalChecked()));
  // exports->Set(String::NewFromUtf8(isolate, "HashSet"),
  //   tpl->GetFunction(isolate->GetCurrentContext()).ToLocalChecked());
}

void HashSetWrap::New(const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = args.GetIsolate();

  if (args.IsConstructCall()) {
    // Invoked as constructor: `new HashSet(...)`
    HashSetWrap* obj = new HashSetWrap(1024, false);
    obj->Wrap(args.This());
    args.GetReturnValue().Set(args.This());
  } else {
    // Invoked as plain function `HashSet(...)`, turn into construct call.
    const int argc = 1;
    Local<Value> argv[argc] = { args[0] };
    Local<Function> cons = Local<Function>::New(isolate, constructor);
    args.GetReturnValue().Set(
      cons->NewInstance(isolate->GetCurrentContext(), argc, argv)
        .ToLocalChecked());
  }
}

void HashSetWrap::AddItem(const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = args.GetIsolate();
  String::Utf8Value str(isolate,
    args[0]->ToString(isolate->GetCurrentContext())
      .FromMaybe(v8::Local<v8::String>()));
  const char * buffer = *str;

  HashSetWrap* obj = ObjectWrap::Unwrap<HashSetWrap>(args.Holder());
  obj->Add(ExampleData(buffer));
}

void HashSetWrap::ItemExists(const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = args.GetIsolate();
  String::Utf8Value str(isolate,
    args[0]->ToString(isolate->GetCurrentContext())
      .FromMaybe(v8::Local<v8::String>()));
  const char * buffer = *str;

  HashSetWrap* obj = ObjectWrap::Unwrap<HashSetWrap>(args.Holder());
  bool exists = obj->Exists(ExampleData(buffer));

  args.GetReturnValue().Set(Boolean::New(isolate, exists));
}

}  // namespace HashSetWrap
<|endoftext|>


<commit_before>/*
 * Chemharp, an efficient IO library for chemistry file formats
 * Copyright (C) 2015 Guillaume Fraux
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/
*/

#include "chemharp/Topology.hpp"
#include "chemharp/Error.hpp"
#include <algorithm>

using namespace harp;
using std::vector;

void Connectivity::recalculate() const{
    _angles.clear();
    _dihedrals.clear();
    for (auto const& bond1 : _bonds){
        // Find angles
        for (auto const& bond2 : _bonds){
            if (bond1 == bond2) continue;
            // Initializing angle to an invalid value
            angle angle1(static_cast<size_t>(-1), static_cast<size_t>(-2), static_cast<size_t>(-3));
            if (bond1[0] == bond2[1]) {
                angle1 = angle(bond2[0], bond2[1], bond1[1]);
                _angles.insert(angle1);
            } else if (bond1[1] == bond2[0]) {
                angle1 = angle(bond1[0], bond1[1], bond2[1]);
                _angles.insert(angle1);
            } else if (bond1[1] == bond2[1]) {
                angle1 = angle(bond1[0], bond1[1], bond2[0]);
                _angles.insert(angle1);
            } else if (bond1[0] == bond2[0]) {
                angle1 = angle(bond1[1], bond1[0], bond2[1]);
                _angles.insert(angle1);
            } else {
                // We will not find any dihedral angle from these bonds
                continue;
            }
            // Find dihedral angles
            for (auto const& bond3 : _bonds){
                if (bond2 == bond3) continue;

                if (angle1[2] == bond3[0] && angle1[1] != bond3[1]){
                    _dihedrals.insert(dihedral(angle1[0], angle1[1], angle1[2], bond3[1]));
                } else if (angle1[0] == bond3[1] && angle1[1] != bond3[0]) {
                    _dihedrals.insert(dihedral(bond3[0], angle1[0], angle1[1], angle1[2]));
                } else if (angle1[2] == bond3[0] || angle1[2] == bond3[1]) {
                    // TODO this is an improper dihedral
                }
            }
        }
    }
    uptodate = true;
}

void Connectivity::clear(){
    _bonds.clear();
    _angles.clear();
    _dihedrals.clear();
}

const std::unordered_set<bond>& Connectivity::bonds() const {
    if (!uptodate)
        recalculate();
    return _bonds;
}

const std::unordered_set<angle>& Connectivity::angles() const {
    if (!uptodate)
        recalculate();
    return _angles;
}

const std::unordered_set<dihedral>& Connectivity::dihedrals() const {
    if (!uptodate)
        recalculate();
    return _dihedrals;
}

void Connectivity::add_bond(size_t i, size_t j){
    uptodate = false;
    _bonds.insert(bond(i, j));
}

void Connectivity::remove_bond(size_t i, size_t j){
    uptodate = false;
    auto pos = _bonds.find(bond(i, j));
    if (pos != _bonds.end()){
        _bonds.erase(pos);
    }
}

/******************************************************************************/

Topology::Topology(size_t natoms) {
    resize(natoms);
}

Topology::Topology() : Topology(0) {}

void Topology::append(const Atom& _atom){
    size_t index = static_cast<size_t>(-1);

    for (size_t i = 0 ; i<_templates.size(); i++)
        if (_templates[i] == _atom)
            index = i;
    if (index == static_cast<size_t>(-1)) { // Atom not found
        _templates.push_back(_atom);
        index = _templates.size() - 1;
    }

    _atoms.push_back(index);
}

void Topology::remove(size_t idx) {
    if (idx < _atoms.size())
        _atoms.erase(begin(_atoms) + idx);
    auto bonds = _connect.bonds();
    for (auto& bond : bonds){
        if (bond[0] == idx || bond[1] == idx)
            _connect.remove_bond(bond[0], bond[1]);
    }
    recalculate();
}

vector<bond> Topology::bonds() const{
    vector<bond> res;
    res.insert(begin(res), begin(_connect.bonds()), end(_connect.bonds()));
    return std::move(res);
}

vector<angle> Topology::angles() const{
    vector<angle> res;
    res.insert(begin(res), begin(_connect.angles()), end(_connect.angles()));
    return std::move(res);
}

vector<dihedral> Topology::dihedrals() const{
    vector<dihedral> res;
    res.insert(begin(res), begin(_connect.dihedrals()), end(_connect.dihedrals()));
    return std::move(res);
}

bool Topology::isbond(size_t i, size_t j) const  {
    auto bonds = _connect.bonds();
    auto pos = bonds.find(bond(i, j));
    return pos != end(bonds);
}

bool Topology::isangle(size_t i, size_t j, size_t k) const {
    auto angles = _connect.angles();
    auto pos = angles.find(angle(i, j, k));
    return pos != end(angles);
}

bool Topology::isdihedral(size_t i, size_t j, size_t k, size_t m) const {
    auto dihedrals = _connect.dihedrals();
    auto pos = dihedrals.find(dihedral(i, j, k, m));
    return pos != end(dihedrals);
}

void Topology::clear(){
    _templates.clear();
    _atoms.clear();
    _connect.clear();
}

Topology harp::dummy_topology(size_t natoms){
    Topology top(0);
    for (size_t i=0; i<natoms; i++)
        top.append(Atom(Atom::UNDEFINED));
    return top;
}
<commit_msg>Fix a warning on Clang<commit_after>/*
 * Chemharp, an efficient IO library for chemistry file formats
 * Copyright (C) 2015 Guillaume Fraux
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/
*/

#include "chemharp/Topology.hpp"
#include "chemharp/Error.hpp"
#include <algorithm>

using namespace harp;
using std::vector;

void Connectivity::recalculate() const{
    _angles.clear();
    _dihedrals.clear();
    for (auto const& bond1 : _bonds){
        // Find angles
        for (auto const& bond2 : _bonds){
            if (bond1 == bond2) continue;
            // Initializing angle to an invalid value
            angle angle1(static_cast<size_t>(-1), static_cast<size_t>(-2), static_cast<size_t>(-3));
            if (bond1[0] == bond2[1]) {
                angle1 = angle(bond2[0], bond2[1], bond1[1]);
                _angles.insert(angle1);
            } else if (bond1[1] == bond2[0]) {
                angle1 = angle(bond1[0], bond1[1], bond2[1]);
                _angles.insert(angle1);
            } else if (bond1[1] == bond2[1]) {
                angle1 = angle(bond1[0], bond1[1], bond2[0]);
                _angles.insert(angle1);
            } else if (bond1[0] == bond2[0]) {
                angle1 = angle(bond1[1], bond1[0], bond2[1]);
                _angles.insert(angle1);
            } else {
                // We will not find any dihedral angle from these bonds
                continue;
            }
            // Find dihedral angles
            for (auto const& bond3 : _bonds){
                if (bond2 == bond3) continue;

                if (angle1[2] == bond3[0] && angle1[1] != bond3[1]){
                    _dihedrals.insert(dihedral(angle1[0], angle1[1], angle1[2], bond3[1]));
                } else if (angle1[0] == bond3[1] && angle1[1] != bond3[0]) {
                    _dihedrals.insert(dihedral(bond3[0], angle1[0], angle1[1], angle1[2]));
                } else if (angle1[2] == bond3[0] || angle1[2] == bond3[1]) {
                    // TODO this is an improper dihedral
                }
            }
        }
    }
    uptodate = true;
}

void Connectivity::clear(){
    _bonds.clear();
    _angles.clear();
    _dihedrals.clear();
}

const std::unordered_set<bond>& Connectivity::bonds() const {
    if (!uptodate)
        recalculate();
    return _bonds;
}

const std::unordered_set<angle>& Connectivity::angles() const {
    if (!uptodate)
        recalculate();
    return _angles;
}

const std::unordered_set<dihedral>& Connectivity::dihedrals() const {
    if (!uptodate)
        recalculate();
    return _dihedrals;
}

void Connectivity::add_bond(size_t i, size_t j){
    uptodate = false;
    _bonds.insert(bond(i, j));
}

void Connectivity::remove_bond(size_t i, size_t j){
    uptodate = false;
    auto pos = _bonds.find(bond(i, j));
    if (pos != _bonds.end()){
        _bonds.erase(pos);
    }
}

/******************************************************************************/

Topology::Topology(size_t natoms) {
    resize(natoms);
}

Topology::Topology() : Topology(0) {}

void Topology::append(const Atom& _atom){
    size_t index = static_cast<size_t>(-1);

    for (size_t i = 0 ; i<_templates.size(); i++)
        if (_templates[i] == _atom)
            index = i;
    if (index == static_cast<size_t>(-1)) { // Atom not found
        _templates.push_back(_atom);
        index = _templates.size() - 1;
    }

    _atoms.push_back(index);
}

void Topology::remove(size_t idx) {
    if (idx < _atoms.size())
        _atoms.erase(begin(_atoms) + idx);
    auto bonds = _connect.bonds();
    for (auto& bond : bonds){
        if (bond[0] == idx || bond[1] == idx)
            _connect.remove_bond(bond[0], bond[1]);
    }
    recalculate();
}

vector<bond> Topology::bonds() const{
    vector<bond> res;
    res.insert(begin(res), begin(_connect.bonds()), end(_connect.bonds()));
    return res;
}

vector<angle> Topology::angles() const{
    vector<angle> res;
    res.insert(begin(res), begin(_connect.angles()), end(_connect.angles()));
    return res;
}

vector<dihedral> Topology::dihedrals() const{
    vector<dihedral> res;
    res.insert(begin(res), begin(_connect.dihedrals()), end(_connect.dihedrals()));
    return res;
}

bool Topology::isbond(size_t i, size_t j) const  {
    auto bonds = _connect.bonds();
    auto pos = bonds.find(bond(i, j));
    return pos != end(bonds);
}

bool Topology::isangle(size_t i, size_t j, size_t k) const {
    auto angles = _connect.angles();
    auto pos = angles.find(angle(i, j, k));
    return pos != end(angles);
}

bool Topology::isdihedral(size_t i, size_t j, size_t k, size_t m) const {
    auto dihedrals = _connect.dihedrals();
    auto pos = dihedrals.find(dihedral(i, j, k, m));
    return pos != end(dihedrals);
}

void Topology::clear(){
    _templates.clear();
    _atoms.clear();
    _connect.clear();
}

Topology harp::dummy_topology(size_t natoms){
    Topology top(0);
    for (size_t i=0; i<natoms; i++)
        top.append(Atom(Atom::UNDEFINED));
    return top;
}
<|endoftext|>